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;
52 Dictionary <string, ITaskItem[]> builtTargetsOutputByName;
54 static Engine globalEngine;
55 static Version version;
59 version = new Version ("0.1");
67 // engine should be invoked with path where binary files are
68 // to find microsoft.build.tasks
69 public Engine (string binPath)
71 this.binPath = binPath;
72 this.buildEnabled = true;
73 this.projects = new Dictionary <string, Project> ();
74 this.eventSource = new EventSource ();
75 this.loggers = new List <ILogger> ();
76 this.buildStarted = false;
77 this.globalProperties = new BuildPropertyGroup ();
78 this.builtTargetsOutputByName = new Dictionary<string, ITaskItem[]> ();
80 RegisterDefaultTasks ();
84 public bool BuildProject (Project project)
87 throw new ArgumentException ("project");
88 return project.Build ();
92 public bool BuildProject (Project project, string targetName)
95 throw new ArgumentException ("project");
96 if (targetName == null)
99 return BuildProject (project, new string[] { targetName}, null, BuildSettings.None);
103 public bool BuildProject (Project project, string[] targetNames)
105 return BuildProject (project, targetNames, null, BuildSettings.None);
109 public bool BuildProject (Project project,
110 string[] targetNames,
111 IDictionary targetOutputs)
113 return BuildProject (project, targetNames, targetOutputs, BuildSettings.None);
116 [MonoTODO ("use buildFlags")]
117 public bool BuildProject (Project project,
118 string[] targetNames,
119 IDictionary targetOutputs,
120 BuildSettings buildFlags)
123 throw new ArgumentException ("project");
124 if (targetNames == null)
128 return project.Build (targetNames, targetOutputs, buildFlags);
132 public bool BuildProjectFile (string projectFile)
134 throw new NotImplementedException ();
138 public bool BuildProjectFile (string projectFile,
141 throw new NotImplementedException ();
145 public bool BuildProjectFile (string projectFile,
146 string[] targetNames)
148 throw new NotImplementedException ();
152 public bool BuildProjectFile (string projectFile,
153 string[] targetNames,
154 BuildPropertyGroup globalProperties)
156 return BuildProjectFile (projectFile, targetNames, globalProperties, null, BuildSettings.None);
160 public bool BuildProjectFile (string projectFile,
161 string[] targetNames,
162 BuildPropertyGroup globalProperties,
163 IDictionary targetOutputs)
165 return BuildProjectFile (projectFile, targetNames, globalProperties, targetOutputs, BuildSettings.None);
168 [MonoTODO ("use buildFlags")]
169 public bool BuildProjectFile (string projectFile,
170 string[] targetNames,
171 BuildPropertyGroup globalProperties,
172 IDictionary targetOutputs,
173 BuildSettings buildFlags)
179 if (projects.ContainsKey (projectFile)) {
180 project = (Project) projects [projectFile];
182 project = CreateNewProject ();
183 project.Load (projectFile);
186 return project.Build (targetNames, targetOutputs, buildFlags);
191 if (BinPath == null) {
192 throw new InvalidOperationException ("Before a project can be instantiated, " +
193 "Engine.BinPath must be set to the location on disk where MSBuild " +
194 "is installed. This is used to evaluate $(MSBuildBinPath).");
198 public Project CreateNewProject ()
200 if (defaultTasksRegistered)
202 return new Project (this);
205 public Project GetLoadedProject (string projectFullFileName)
207 if (projectFullFileName == null)
208 throw new ArgumentNullException ("projectFullFileName");
211 return projects [projectFullFileName];
214 internal void RemoveLoadedProject (Project p)
216 if (p.FullFileName != String.Empty)
217 projects.Remove (p.FullFileName);
220 internal void AddLoadedProject (Project p)
222 if (p.FullFileName != String.Empty)
223 projects.Add (p.FullFileName, p);
226 public void UnloadProject (Project project)
229 throw new ArgumentNullException ("project");
231 if (project.ParentEngine != this)
232 throw new InvalidOperationException ("The \"Project\" object specified does not belong to the correct \"Engine\" object.");
234 project.CheckUnloaded ();
236 if (project.FullFileName != String.Empty)
237 projects.Remove (project.FullFileName);
242 public void UnloadAllProjects ()
244 foreach (KeyValuePair <string, Project> e in projects)
245 UnloadProject (e.Value);
249 public void RegisterLogger (ILogger logger)
252 throw new ArgumentNullException ("logger");
254 logger.Initialize (eventSource);
255 loggers.Add (logger);
259 public void UnregisterAllLoggers ()
261 // FIXME: check if build succeeded
262 // FIXME: it shouldn't be here
263 LogBuildFinished (true);
264 foreach (ILogger i in loggers) {
270 internal void StartBuild ()
278 void LogBuildStarted ()
280 BuildStartedEventArgs bsea;
281 bsea = new BuildStartedEventArgs ("Build started.", null);
282 eventSource.FireBuildStarted (this, bsea);
285 void LogBuildFinished (bool succeeded)
287 BuildFinishedEventArgs bfea;
288 bfea = new BuildFinishedEventArgs ("Build finished.", null, succeeded);
289 eventSource.FireBuildFinished (this, bfea);
292 void RegisterDefaultTasks ()
294 this.defaultTasksRegistered = false;
296 Project defaultTasksProject = CreateNewProject ();
298 if (binPath != null) {
299 if (File.Exists (Path.Combine (binPath, defaultTasksProjectName))) {
300 defaultTasksProject.Load (Path.Combine (binPath, defaultTasksProjectName));
301 defaultTasks = defaultTasksProject.TaskDatabase;
303 defaultTasks = new TaskDatabase ();
305 defaultTasks = new TaskDatabase ();
307 this.defaultTasksRegistered = true;
310 public string BinPath {
311 get { return binPath; }
312 set { binPath = value; }
315 public bool BuildEnabled {
316 get { return buildEnabled; }
317 set { buildEnabled = value; }
320 public static Version Version {
321 get { return version; }
324 public static Engine GlobalEngine {
326 if (globalEngine == null)
327 globalEngine = new Engine ();
332 public BuildPropertyGroup GlobalProperties {
333 get { return globalProperties; }
334 set { globalProperties = value; }
337 public bool OnlyLogCriticalEvents {
338 get { return eventSource.OnlyLogCriticalEvents; }
339 set { eventSource.OnlyLogCriticalEvents = value; }
342 internal EventSource EventSource {
343 get { return eventSource; }
346 internal bool DefaultTasksRegistered {
347 get { return defaultTasksRegistered; }
350 internal TaskDatabase DefaultTasks {
351 get { return defaultTasks; }
354 internal Dictionary<string, ITaskItem[]> BuiltTargetsOutputByName {
355 get { return builtTargetsOutputByName; }