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}, new Hashtable (), BuildSettings.None);
94 public bool BuildProject (Project project, string[] targetNames)
96 return BuildProject (project, targetNames, new Hashtable (), 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, new Hashtable (), 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);
179 LogProjectFinished (project, result);
184 private void CheckBinPath ()
186 if (BinPath == null) {
187 throw new InvalidOperationException ("Before a project can be instantiated, " +
188 "Engine.BinPath must be set to the location on disk where MSBuild " +
189 "is installed. This is used to evaluate $(MSBuildBinPath).");
193 public Project CreateNewProject ()
195 if (defaultTasksRegistered == true)
197 // FIXME: I don't really know if it should be here
199 return new Project (this);
202 public Project GetLoadedProject (string projectFullFileName)
204 if (projectFullFileName == null)
205 throw new ArgumentNullException ("projectFullFileName");
207 return (Project) projects [projectFullFileName];
210 internal void RemoveLoadedProject (Project p)
212 if (p.FullFileName != String.Empty)
213 projects.Remove (p.FullFileName);
216 internal void AddLoadedProject (Project p)
218 if (p.FullFileName != String.Empty)
219 projects.Add (p.FullFileName, p);
222 public void UnloadProject (Project project)
224 if (project.ParentEngine != this)
225 throw new InvalidOperationException ("This project is not loaded in this engine");
227 project.CheckUnloaded ();
229 if (project.FullFileName != String.Empty)
230 projects.Remove (project.FullFileName);
235 public void UnloadAllProjects ()
237 foreach (KeyValuePair <string, Project> e in projects)
238 UnloadProject ((Project) e.Value);
242 public void RegisterLogger (ILogger logger)
245 throw new ArgumentNullException ("logger");
247 logger.Initialize (eventSource);
248 loggers.Add (logger);
252 public void UnregisterAllLoggers ()
254 // FIXME: check if build succeeded
255 LogBuildFinished (true);
256 foreach (ILogger i in loggers) {
262 private void LogProjectStarted (Project project, string[] targetNames)
264 ProjectStartedEventArgs psea;
265 if (targetNames.Length == 0) {
266 if (project.DefaultTargets != String.Empty)
267 psea = new ProjectStartedEventArgs ("Project started.", null, project.FullFileName,
268 project.DefaultTargets, null, null);
270 psea = new ProjectStartedEventArgs ("Project started.", null, project.FullFileName, "default", null, null);
272 psea = new ProjectStartedEventArgs ("Project started.", null, project.FullFileName, String.Join (";",
273 targetNames), null, null);
274 eventSource.FireProjectStarted (this, psea);
277 private void LogProjectFinished (Project project, bool succeeded)
279 ProjectFinishedEventArgs pfea;
280 pfea = new ProjectFinishedEventArgs ("Project started.", null, project.FullFileName, succeeded);
281 eventSource.FireProjectFinished (this, pfea);
284 private void LogBuildStarted ()
286 BuildStartedEventArgs bsea;
287 bsea = new BuildStartedEventArgs ("Build started.", null);
288 eventSource.FireBuildStarted (this, bsea);
291 private void LogBuildFinished (bool succeeded)
293 BuildFinishedEventArgs bfea;
294 bfea = new BuildFinishedEventArgs ("Build finished.", null, succeeded);
295 eventSource.FireBuildFinished (this, bfea);
298 private void RegisterDefaultTasks ()
300 this.defaultTasksRegistered = false;
302 Project defaultTasksProject = CreateNewProject ();
304 if (binPath != null) {
305 if (File.Exists (Path.Combine (binPath, defaultTasksProjectName)) == true) {
306 defaultTasksProject.Load (Path.Combine (binPath, defaultTasksProjectName));
307 defaultTasks = defaultTasksProject.TaskDatabase;
309 defaultTasks = new TaskDatabase ();
312 defaultTasks = new TaskDatabase ();
315 this.defaultTasksRegistered = true;
318 public string BinPath {
319 get { return binPath; }
320 set { binPath = value; }
323 public bool BuildEnabled {
324 get { return buildEnabled; }
325 set { buildEnabled = value; }
328 public static Version Version {
329 get { return version; }
332 public static Engine GlobalEngine {
334 if (globalEngine == null)
335 globalEngine = new Engine ();
340 public BuildPropertyGroup GlobalProperties {
341 get { return globalProperties; }
342 set { globalProperties = value; }
345 public bool OnlyLogCriticalEvents {
346 get { return eventSource.OnlyLogCriticalEvents; }
347 set { eventSource.OnlyLogCriticalEvents = value; }
350 internal EventSource EventSource {
351 get { return eventSource; }
354 internal bool DefaultTasksRegistered {
355 get { return defaultTasksRegistered; }
358 internal TaskDatabase DefaultTasks {
359 get { return defaultTasks; }