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;
33 using Microsoft.Build.Framework;
34 using Mono.XBuild.Utilities;
36 namespace Microsoft.Build.BuildEngine {
41 TaskDatabase defaultTasks;
42 bool defaultTasksRegistered;
43 const string defaultTasksProjectName = "Microsoft.Common.tasks";
44 EventSource eventSource;
46 BuildPropertyGroup globalProperties;
47 IDictionary importedProjects;
49 bool onlyLogCriticalEvents;
52 static Engine globalEngine;
53 static Version version;
57 version = new Version ("0.1");
65 // engine should be invoked with path where binary files are
66 // to find microsoft.build.tasks
67 public Engine (string binPath)
69 this.binPath = binPath;
70 this.buildEnabled = true;
71 this.projects = new Hashtable ();
72 this.eventSource = new EventSource ();
73 this.loggers = new ArrayList ();
74 this.buildStarted = false;
75 this.globalProperties = new BuildPropertyGroup ();
77 RegisterDefaultTasks ();
81 public bool BuildProject (Project project)
83 return project.Build ();
87 public bool BuildProject (Project project, string targetName)
89 return BuildProject (project, new string[] { targetName}, new Hashtable (), BuildSettings.None);
93 public bool BuildProject (Project project, string[] targetNames)
95 return BuildProject (project, targetNames, new Hashtable (), BuildSettings.None);
99 public bool BuildProject (Project project,
100 string[] targetNames,
101 IDictionary targetOutputs)
103 return BuildProject (project, targetNames, targetOutputs, BuildSettings.None);
106 [MonoTODO ("use buildFlags")]
107 public bool BuildProject (Project project,
108 string[] targetNames,
109 IDictionary targetOutputs,
110 BuildSettings buildFlags)
114 LogProjectStarted (project, targetNames);
116 result = project.Build (targetNames, targetOutputs);
118 LogProjectFinished (project, result);
124 public bool BuildProjectFile (string projectFile)
126 throw new NotImplementedException ();
130 public bool BuildProjectFile (string projectFile,
133 throw new NotImplementedException ();
137 public bool BuildProjectFile (string projectFile,
138 string[] targetNames)
140 throw new NotImplementedException ();
144 public bool BuildProjectFile (string projectFile,
145 string[] targetNames,
146 BuildPropertyGroup globalProperties)
148 return BuildProjectFile (projectFile, targetNames, globalProperties, new Hashtable (), BuildSettings.None);
152 public bool BuildProjectFile (string projectFile,
153 string[] targetNames,
154 BuildPropertyGroup globalProperties,
155 IDictionary targetOutputs)
157 return BuildProjectFile (projectFile, targetNames, globalProperties, targetOutputs, BuildSettings.None);
160 [MonoTODO ("use buildFlags")]
161 public bool BuildProjectFile (string projectFile,
162 string[] targetNames,
163 BuildPropertyGroup globalProperties,
164 IDictionary targetOutputs,
165 BuildSettings buildFlags)
170 if (projects.Contains (projectFile)) {
171 project = (Project) projects [projectFile];
172 LogProjectStarted (project, targetNames);
173 result = project.Build (targetNames, targetOutputs);
178 LogProjectFinished (project, result);
183 private void CheckBinPath ()
185 if (BinPath == null) {
186 throw new InvalidOperationException ("Before a project can be instantiated, " +
187 "Engine.BinPath must be set to the location on disk where MSBuild " +
188 "is installed. This is used to evaluate $(MSBuildBinPath).");
192 public Project CreateNewProject ()
194 if (defaultTasksRegistered == true)
196 // FIXME: I don't really know if it should be here
198 return new Project (this);
201 public Project GetLoadedProject (string projectFullFileName)
203 if (projectFullFileName == null)
204 throw new ArgumentNullException ("projectFullFileName");
206 return (Project) projects [projectFullFileName];
209 internal void RemoveLoadedProject (Project p)
211 if (p.FullFileName != String.Empty)
212 projects.Remove (p.FullFileName);
215 internal void AddLoadedProject (Project p)
217 if (p.FullFileName != String.Empty)
218 projects.Add (p.FullFileName, p);
221 public void UnloadProject (Project project)
223 if (project.ParentEngine != this)
224 throw new InvalidOperationException ("This project is not loaded in this engine");
226 project.CheckUnloaded ();
228 if (project.FullFileName != String.Empty)
229 projects.Remove (project.FullFileName);
234 public void UnloadAllProjects ()
236 foreach (DictionaryEntry e in projects)
237 UnloadProject ((Project) e.Value);
241 public void RegisterLogger (ILogger logger)
244 throw new ArgumentNullException ("logger");
246 logger.Initialize (eventSource);
247 loggers.Add (logger);
251 public void UnregisterAllLoggers ()
253 // FIXME: check if build succeeded
254 LogBuildFinished (true);
255 foreach (ILogger i in loggers) {
261 private void LogProjectStarted (Project project, string[] targetNames)
263 ProjectStartedEventArgs psea;
264 if (targetNames.Length == 0) {
265 if (project.DefaultTargets != String.Empty)
266 psea = new ProjectStartedEventArgs ("Project started.", null, project.FullFileName,
267 project.DefaultTargets, null, null);
269 psea = new ProjectStartedEventArgs ("Project started.", null, project.FullFileName, "default", null, null);
271 psea = new ProjectStartedEventArgs ("Project started.", null, project.FullFileName, String.Join (";",
272 targetNames), null, null);
273 eventSource.FireProjectStarted (this, psea);
276 private void LogProjectFinished (Project project, bool succeeded)
278 ProjectFinishedEventArgs pfea;
279 pfea = new ProjectFinishedEventArgs ("Project started.", null, project.FullFileName, succeeded);
280 eventSource.FireProjectFinished (this, pfea);
283 private void LogBuildStarted ()
285 BuildStartedEventArgs bsea;
286 bsea = new BuildStartedEventArgs ("Build started.", null);
287 eventSource.FireBuildStarted (this, bsea);
290 private void LogBuildFinished (bool succeeded)
292 BuildFinishedEventArgs bfea;
293 bfea = new BuildFinishedEventArgs ("Build finished.", null, succeeded);
294 eventSource.FireBuildFinished (this, bfea);
297 private void RegisterDefaultTasks ()
299 this.defaultTasksRegistered = false;
301 Project defaultTasksProject = CreateNewProject ();
303 if (binPath != null) {
304 if (File.Exists (Path.Combine (binPath, defaultTasksProjectName)) == true) {
305 defaultTasksProject.Load (Path.Combine (binPath, defaultTasksProjectName));
306 defaultTasks = defaultTasksProject.TaskDatabase;
308 defaultTasks = new TaskDatabase ();
311 defaultTasks = new TaskDatabase ();
314 this.defaultTasksRegistered = true;
317 public string BinPath {
318 get { return binPath; }
319 set { binPath = value; }
322 public bool BuildEnabled {
323 get { return buildEnabled; }
324 set { buildEnabled = value; }
327 public static Version Version {
328 get { return version; }
331 public static Engine GlobalEngine {
333 if (globalEngine == null)
334 globalEngine = new Engine ();
339 public BuildPropertyGroup GlobalProperties {
340 get { return globalProperties; }
341 set { globalProperties = value; }
344 public bool OnlyLogCriticalEvents {
345 get { return eventSource.OnlyLogCriticalEvents; }
346 set { eventSource.OnlyLogCriticalEvents = value; }
349 internal EventSource EventSource {
350 get { return eventSource; }
353 internal bool DefaultTasksRegistered {
354 get { return defaultTasksRegistered; }
357 internal TaskDatabase DefaultTasks {
358 get { return defaultTasks; }