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)
117 LogProjectStarted (project, targetNames);
119 result = project.Build (targetNames, targetOutputs);
121 LogProjectFinished (project, result);
127 public bool BuildProjectFile (string projectFile)
129 throw new NotImplementedException ();
133 public bool BuildProjectFile (string projectFile,
136 throw new NotImplementedException ();
140 public bool BuildProjectFile (string projectFile,
141 string[] targetNames)
143 throw new NotImplementedException ();
147 public bool BuildProjectFile (string projectFile,
148 string[] targetNames,
149 BuildPropertyGroup globalProperties)
151 return BuildProjectFile (projectFile, targetNames, globalProperties, null, BuildSettings.None);
155 public bool BuildProjectFile (string projectFile,
156 string[] targetNames,
157 BuildPropertyGroup globalProperties,
158 IDictionary targetOutputs)
160 return BuildProjectFile (projectFile, targetNames, globalProperties, targetOutputs, BuildSettings.None);
163 [MonoTODO ("use buildFlags")]
164 public bool BuildProjectFile (string projectFile,
165 string[] targetNames,
166 BuildPropertyGroup globalProperties,
167 IDictionary targetOutputs,
168 BuildSettings buildFlags)
175 if (projects.ContainsKey (projectFile)) {
176 project = (Project) projects [projectFile];
177 LogProjectStarted (project, targetNames);
178 result = project.Build (targetNames, targetOutputs);
180 project = CreateNewProject ();
181 project.Load (projectFile);
182 LogProjectStarted (project, targetNames);
183 result = project.Build (targetNames, targetOutputs);
186 LogProjectFinished (project, result);
193 if (BinPath == null) {
194 throw new InvalidOperationException ("Before a project can be instantiated, " +
195 "Engine.BinPath must be set to the location on disk where MSBuild " +
196 "is installed. This is used to evaluate $(MSBuildBinPath).");
200 public Project CreateNewProject ()
202 if (defaultTasksRegistered)
204 return new Project (this);
207 public Project GetLoadedProject (string projectFullFileName)
209 if (projectFullFileName == null)
210 throw new ArgumentNullException ("projectFullFileName");
213 return projects [projectFullFileName];
216 internal void RemoveLoadedProject (Project p)
218 if (p.FullFileName != String.Empty)
219 projects.Remove (p.FullFileName);
222 internal void AddLoadedProject (Project p)
224 if (p.FullFileName != String.Empty)
225 projects.Add (p.FullFileName, p);
228 public void UnloadProject (Project project)
231 throw new ArgumentNullException ("project");
233 if (project.ParentEngine != this)
234 throw new InvalidOperationException ("The \"Project\" object specified does not belong to the correct \"Engine\" object.");
236 project.CheckUnloaded ();
238 if (project.FullFileName != String.Empty)
239 projects.Remove (project.FullFileName);
244 public void UnloadAllProjects ()
246 foreach (KeyValuePair <string, Project> e in projects)
247 UnloadProject (e.Value);
251 public void RegisterLogger (ILogger logger)
254 throw new ArgumentNullException ("logger");
256 logger.Initialize (eventSource);
257 loggers.Add (logger);
261 public void UnregisterAllLoggers ()
263 // FIXME: check if build succeeded
264 // FIXME: it shouldn't be here
265 LogBuildFinished (true);
266 foreach (ILogger i in loggers) {
272 internal void StartBuild ()
280 void LogProjectStarted (Project project, string [] targetNames)
282 ProjectStartedEventArgs psea;
283 if (targetNames.Length == 0) {
284 if (project.DefaultTargets != String.Empty)
285 psea = new ProjectStartedEventArgs ("Project started.", null, project.FullFileName,
286 project.DefaultTargets, null, null);
288 psea = new ProjectStartedEventArgs ("Project started.", null, project.FullFileName, "default", null, null);
290 psea = new ProjectStartedEventArgs ("Project started.", null, project.FullFileName, String.Join (";",
291 targetNames), null, null);
292 eventSource.FireProjectStarted (this, psea);
295 void LogProjectFinished (Project project, bool succeeded)
297 ProjectFinishedEventArgs pfea;
298 pfea = new ProjectFinishedEventArgs ("Project started.", null, project.FullFileName, succeeded);
299 eventSource.FireProjectFinished (this, pfea);
302 void LogBuildStarted ()
304 BuildStartedEventArgs bsea;
305 bsea = new BuildStartedEventArgs ("Build started.", null);
306 eventSource.FireBuildStarted (this, bsea);
309 void LogBuildFinished (bool succeeded)
311 BuildFinishedEventArgs bfea;
312 bfea = new BuildFinishedEventArgs ("Build finished.", null, succeeded);
313 eventSource.FireBuildFinished (this, bfea);
316 void RegisterDefaultTasks ()
318 this.defaultTasksRegistered = false;
320 Project defaultTasksProject = CreateNewProject ();
322 if (binPath != null) {
323 if (File.Exists (Path.Combine (binPath, defaultTasksProjectName))) {
324 defaultTasksProject.Load (Path.Combine (binPath, defaultTasksProjectName));
325 defaultTasks = defaultTasksProject.TaskDatabase;
327 defaultTasks = new TaskDatabase ();
329 defaultTasks = new TaskDatabase ();
331 this.defaultTasksRegistered = true;
334 public string BinPath {
335 get { return binPath; }
336 set { binPath = value; }
339 public bool BuildEnabled {
340 get { return buildEnabled; }
341 set { buildEnabled = value; }
344 public static Version Version {
345 get { return version; }
348 public static Engine GlobalEngine {
350 if (globalEngine == null)
351 globalEngine = new Engine ();
356 public BuildPropertyGroup GlobalProperties {
357 get { return globalProperties; }
358 set { globalProperties = value; }
361 public bool OnlyLogCriticalEvents {
362 get { return eventSource.OnlyLogCriticalEvents; }
363 set { eventSource.OnlyLogCriticalEvents = value; }
366 internal EventSource EventSource {
367 get { return eventSource; }
370 internal bool DefaultTasksRegistered {
371 get { return defaultTasksRegistered; }
374 internal TaskDatabase DefaultTasks {
375 get { return defaultTasks; }