2 // Engine.cs: Main engine of XBuild.
5 // Marek Sieradzki (marek.sieradzki@gmail.com)
7 // (C) 2005 Marek Sieradzki
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections;
32 using System.Collections.Generic;
34 using Microsoft.Build.Framework;
35 using Mono.XBuild.Utilities;
37 namespace Microsoft.Build.BuildEngine {
42 TaskDatabase defaultTasks;
43 bool defaultTasksRegistered;
44 const string defaultTasksProjectName = "Microsoft.Common.tasks";
45 EventSource eventSource;
47 BuildPropertyGroup globalProperties;
48 //IDictionary importedProjects;
49 List <ILogger> loggers;
50 //bool onlyLogCriticalEvents;
51 Dictionary <string, Project> projects;
53 static Engine globalEngine;
54 static Version version;
58 version = new Version ("0.1");
66 // engine should be invoked with path where binary files are
67 // to find microsoft.build.tasks
68 public Engine (string binPath)
70 this.binPath = binPath;
71 this.buildEnabled = true;
72 this.projects = new Dictionary <string, Project> ();
73 this.eventSource = new EventSource ();
74 this.loggers = new List <ILogger> ();
75 this.buildStarted = false;
76 this.globalProperties = new BuildPropertyGroup ();
78 RegisterDefaultTasks ();
82 public bool BuildProject (Project project)
84 return project.Build ();
88 public bool BuildProject (Project project, string targetName)
90 return BuildProject (project, new string[] { targetName}, null, BuildSettings.None);
94 public bool BuildProject (Project project, string[] targetNames)
96 return BuildProject (project, targetNames, null, BuildSettings.None);
100 public bool BuildProject (Project project,
101 string[] targetNames,
102 IDictionary targetOutputs)
104 return BuildProject (project, targetNames, targetOutputs, BuildSettings.None);
107 [MonoTODO ("use buildFlags")]
108 public bool BuildProject (Project project,
109 string[] targetNames,
110 IDictionary targetOutputs,
111 BuildSettings buildFlags)
115 LogProjectStarted (project, targetNames);
117 result = project.Build (targetNames, targetOutputs);
119 LogProjectFinished (project, result);
125 public bool BuildProjectFile (string projectFile)
127 throw new NotImplementedException ();
131 public bool BuildProjectFile (string projectFile,
134 throw new NotImplementedException ();
138 public bool BuildProjectFile (string projectFile,
139 string[] targetNames)
141 throw new NotImplementedException ();
145 public bool BuildProjectFile (string projectFile,
146 string[] targetNames,
147 BuildPropertyGroup globalProperties)
149 return BuildProjectFile (projectFile, targetNames, globalProperties, null, BuildSettings.None);
153 public bool BuildProjectFile (string projectFile,
154 string[] targetNames,
155 BuildPropertyGroup globalProperties,
156 IDictionary targetOutputs)
158 return BuildProjectFile (projectFile, targetNames, globalProperties, targetOutputs, BuildSettings.None);
161 [MonoTODO ("use buildFlags")]
162 public bool BuildProjectFile (string projectFile,
163 string[] targetNames,
164 BuildPropertyGroup globalProperties,
165 IDictionary targetOutputs,
166 BuildSettings buildFlags)
171 if (projects.ContainsKey (projectFile)) {
172 project = (Project) projects [projectFile];
173 LogProjectStarted (project, targetNames);
174 result = project.Build (targetNames, targetOutputs);
176 project = CreateNewProject ();
177 project.Load (projectFile);
178 LogProjectStarted (project, targetNames);
179 result = project.Build (targetNames, targetOutputs);
182 LogProjectFinished (project, result);
187 private void CheckBinPath ()
189 if (BinPath == null) {
190 throw new InvalidOperationException ("Before a project can be instantiated, " +
191 "Engine.BinPath must be set to the location on disk where MSBuild " +
192 "is installed. This is used to evaluate $(MSBuildBinPath).");
196 public Project CreateNewProject ()
198 if (defaultTasksRegistered)
200 // FIXME: I don't really know if it should be here
202 return new Project (this);
205 public Project GetLoadedProject (string projectFullFileName)
207 if (projectFullFileName == null)
208 throw new ArgumentNullException ("projectFullFileName");
210 return projects [projectFullFileName];
213 internal void RemoveLoadedProject (Project p)
215 if (p.FullFileName != String.Empty)
216 projects.Remove (p.FullFileName);
219 internal void AddLoadedProject (Project p)
221 if (p.FullFileName != String.Empty)
222 projects.Add (p.FullFileName, p);
225 public void UnloadProject (Project project)
227 if (project.ParentEngine != this)
228 throw new InvalidOperationException ("The \"Project\" object specified does not belong to the correct \"Engine\" object.");
230 project.CheckUnloaded ();
232 if (project.FullFileName != String.Empty)
233 projects.Remove (project.FullFileName);
238 public void UnloadAllProjects ()
240 foreach (KeyValuePair <string, Project> e in projects)
241 UnloadProject (e.Value);
245 public void RegisterLogger (ILogger logger)
248 throw new ArgumentNullException ("logger");
250 logger.Initialize (eventSource);
251 loggers.Add (logger);
255 public void UnregisterAllLoggers ()
257 // FIXME: check if build succeeded
258 LogBuildFinished (true);
259 foreach (ILogger i in loggers) {
265 private void LogProjectStarted (Project project, string[] targetNames)
267 ProjectStartedEventArgs psea;
268 if (targetNames.Length == 0) {
269 if (project.DefaultTargets != String.Empty)
270 psea = new ProjectStartedEventArgs ("Project started.", null, project.FullFileName,
271 project.DefaultTargets, null, null);
273 psea = new ProjectStartedEventArgs ("Project started.", null, project.FullFileName, "default", null, null);
275 psea = new ProjectStartedEventArgs ("Project started.", null, project.FullFileName, String.Join (";",
276 targetNames), null, null);
277 eventSource.FireProjectStarted (this, psea);
280 private void LogProjectFinished (Project project, bool succeeded)
282 ProjectFinishedEventArgs pfea;
283 pfea = new ProjectFinishedEventArgs ("Project started.", null, project.FullFileName, succeeded);
284 eventSource.FireProjectFinished (this, pfea);
287 private void LogBuildStarted ()
289 BuildStartedEventArgs bsea;
290 bsea = new BuildStartedEventArgs ("Build started.", null);
291 eventSource.FireBuildStarted (this, bsea);
294 private void LogBuildFinished (bool succeeded)
296 BuildFinishedEventArgs bfea;
297 bfea = new BuildFinishedEventArgs ("Build finished.", null, succeeded);
298 eventSource.FireBuildFinished (this, bfea);
301 private void RegisterDefaultTasks ()
303 this.defaultTasksRegistered = false;
305 Project defaultTasksProject = CreateNewProject ();
307 if (binPath != null) {
308 if (File.Exists (Path.Combine (binPath, defaultTasksProjectName))) {
309 defaultTasksProject.Load (Path.Combine (binPath, defaultTasksProjectName));
310 defaultTasks = defaultTasksProject.TaskDatabase;
312 defaultTasks = new TaskDatabase ();
315 defaultTasks = new TaskDatabase ();
318 this.defaultTasksRegistered = true;
321 public string BinPath {
322 get { return binPath; }
323 set { binPath = value; }
326 public bool BuildEnabled {
327 get { return buildEnabled; }
328 set { buildEnabled = value; }
331 public static Version Version {
332 get { return version; }
335 public static Engine GlobalEngine {
337 if (globalEngine == null)
338 globalEngine = new Engine ();
343 public BuildPropertyGroup GlobalProperties {
344 get { return globalProperties; }
345 set { globalProperties = value; }
348 public bool OnlyLogCriticalEvents {
349 get { return eventSource.OnlyLogCriticalEvents; }
350 set { eventSource.OnlyLogCriticalEvents = value; }
353 internal EventSource EventSource {
354 get { return eventSource; }
357 internal bool DefaultTasksRegistered {
358 get { return defaultTasksRegistered; }
361 internal TaskDatabase DefaultTasks {
362 get { return defaultTasks; }