2006-04-24 Marek Sieradzki <marek.sieradzki@gmail.com>
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / Engine.cs
1 //
2 // Engine.cs: Main engine of XBuild.
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 // 
7 // (C) 2005 Marek Sieradzki
8 //
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:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
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.
27
28 #if NET_2_0
29
30 using System;
31 using System.Collections;
32 using System.IO;
33 using Microsoft.Build.Framework;
34 using Mono.XBuild.Utilities;
35
36 namespace Microsoft.Build.BuildEngine {
37         public class Engine {
38                 
39                 string                  binPath;
40                 bool                    buildEnabled;
41                 TaskDatabase            defaultTasks;
42                 bool                    defaultTasksRegistered;
43                 const string            defaultTasksProjectName = "Microsoft.Common.tasks";
44                 EventSource             eventSource;
45                 bool                    buildStarted;
46                 BuildPropertyGroup      globalProperties;
47                 IDictionary             importedProjects;
48                 IList                   loggers;
49                 bool                    onlyLogCriticalEvents;
50                 IDictionary             projects;
51
52                 static Engine           globalEngine;
53                 static Version          version;
54
55                 static Engine ()
56                 {
57                         version = new Version ("0.1");
58                 }
59                 
60                 public Engine ()
61                         : this (null)
62                 {
63                 }
64
65                 // engine should be invoked with path where binary files are
66                 // to find microsoft.build.tasks
67                 public Engine (string binPath)
68                 {
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 ();
76                         
77                         RegisterDefaultTasks ();
78                 }
79                 
80                 [MonoTODO]
81                 public bool BuildProject (Project project)
82                 {
83                         return project.Build ();
84                 }
85                 
86                 [MonoTODO]
87                 public bool BuildProject (Project project, string targetName)
88                 {
89                         return BuildProject (project, new string[] { targetName}, new Hashtable (), BuildSettings.None);
90                 }
91                 
92                 [MonoTODO]
93                 public bool BuildProject (Project project, string[] targetNames)
94                 {
95                         return BuildProject (project, targetNames, new Hashtable (), BuildSettings.None);
96                 }
97
98                 [MonoTODO]
99                 public bool BuildProject (Project project,
100                                           string[] targetNames,
101                                           IDictionary targetOutputs)
102                 {
103                         return BuildProject (project, targetNames, targetOutputs, BuildSettings.None);
104                 }
105                 
106                 [MonoTODO ("use buildFlags")]
107                 public bool BuildProject (Project project,
108                                           string[] targetNames,
109                                           IDictionary targetOutputs,
110                                           BuildSettings buildFlags)
111                 {
112                         bool result;
113                         
114                         LogProjectStarted (project, targetNames);
115                                 
116                         result =  project.Build (targetNames, targetOutputs);
117                         
118                         LogProjectFinished (project, result);
119                         
120                         return result;
121                 }
122
123                 [MonoTODO]
124                 public bool BuildProjectFile (string projectFile)
125                 {
126                         throw new NotImplementedException ();
127                 }
128                 
129                 [MonoTODO]
130                 public bool BuildProjectFile (string projectFile,
131                                               string targetName)
132                 {
133                         throw new NotImplementedException ();
134                 }
135                 
136                 [MonoTODO]
137                 public bool BuildProjectFile (string projectFile,
138                                               string[] targetNames)
139                 {
140                         throw new NotImplementedException ();
141                 }
142                 
143                 [MonoTODO]
144                 public bool BuildProjectFile (string projectFile,
145                                               string[] targetNames,
146                                               BuildPropertyGroup globalProperties)
147                 {
148                         return BuildProjectFile (projectFile, targetNames, globalProperties, new Hashtable (), BuildSettings.None);
149                 }
150                 
151                 [MonoTODO]
152                 public bool BuildProjectFile (string projectFile,
153                                               string[] targetNames,
154                                               BuildPropertyGroup globalProperties,
155                                               IDictionary targetOutputs)
156                 {
157                         return BuildProjectFile (projectFile, targetNames, globalProperties, targetOutputs, BuildSettings.None);
158                 }
159                 
160                 [MonoTODO ("use buildFlags")]
161                 public bool BuildProjectFile (string projectFile,
162                                               string[] targetNames,
163                                               BuildPropertyGroup globalProperties,
164                                               IDictionary targetOutputs,
165                                               BuildSettings buildFlags)
166                 {
167                         bool result;
168                         Project project;
169                         
170                         if (projects.Contains (projectFile)) {
171                                 project = (Project) projects [projectFile];
172                                 LogProjectStarted (project, targetNames);
173                                 result = project.Build (targetNames, targetOutputs);
174                         }
175                         else
176                                 return false;
177                         
178                         LogProjectFinished (project, result);
179                         
180                         return result;
181                 }
182
183                 private void CheckBinPath ()
184                 {
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).");
189                         }
190                 }
191
192                 public Project CreateNewProject ()
193                 {
194                         if (defaultTasksRegistered == true)
195                                 CheckBinPath ();
196                         // FIXME: I don't really know if it should be here
197                         LogBuildStarted ();
198                         return new Project (this);
199                 }
200
201                 public Project GetLoadedProject (string projectFullFileName)
202                 {
203                         if (projectFullFileName == null)
204                                 throw new ArgumentNullException ("projectFullFileName");
205                         
206                         return (Project) projects [projectFullFileName];
207                 }
208
209                 internal void RemoveLoadedProject (Project p)
210                 {
211                         if (p.FullFileName != String.Empty)
212                                 projects.Remove (p.FullFileName);
213                 }
214
215                 internal void AddLoadedProject (Project p)
216                 {
217                         if (p.FullFileName != String.Empty)
218                                 projects.Add (p.FullFileName, p);
219                 }
220         
221                 public void UnloadProject (Project project)
222                 {
223                         if (project.ParentEngine != this)
224                                 throw new InvalidOperationException ("This project is not loaded in this engine");
225                         
226                         project.CheckUnloaded ();
227                         
228                         if (project.FullFileName != String.Empty)
229                                 projects.Remove (project.FullFileName);
230                         
231                         project.Unload ();
232                 }
233
234                 public void UnloadAllProjects ()
235                 {
236                         foreach (DictionaryEntry e in projects)
237                                 UnloadProject ((Project) e.Value);
238                 }
239
240                 [MonoTODO]
241                 public void RegisterLogger (ILogger logger)
242                 {
243                         if (logger == null)
244                                 throw new ArgumentNullException ("logger");
245                         
246                         logger.Initialize (eventSource);
247                         loggers.Add (logger);
248                 }
249                 
250                 [MonoTODO]
251                 public void UnregisterAllLoggers ()
252                 {
253                         // FIXME: check if build succeeded
254                         LogBuildFinished (true);
255                         foreach (ILogger i in loggers) {
256                                 i.Shutdown ();
257                         }
258                         loggers.Clear ();
259                 }
260                 
261                 private void LogProjectStarted (Project project, string[] targetNames)
262                 {
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);
268                                 else
269                                         psea = new ProjectStartedEventArgs ("Project started.", null, project.FullFileName, "default", null, null);
270                         } else
271                         psea = new ProjectStartedEventArgs ("Project started.", null, project.FullFileName, String.Join (";",
272                                 targetNames), null, null);
273                         eventSource.FireProjectStarted (this, psea);
274                 }
275                 
276                 private void LogProjectFinished (Project project, bool succeeded)
277                 {
278                         ProjectFinishedEventArgs pfea;
279                         pfea = new ProjectFinishedEventArgs ("Project started.", null, project.FullFileName, succeeded);
280                         eventSource.FireProjectFinished (this, pfea);
281                 }
282                 
283                 private void LogBuildStarted ()
284                 {
285                         BuildStartedEventArgs bsea;
286                         bsea = new BuildStartedEventArgs ("Build started.", null);
287                         eventSource.FireBuildStarted (this, bsea);
288                 }
289                 
290                 private void LogBuildFinished (bool succeeded)
291                 {
292                         BuildFinishedEventArgs bfea;
293                         bfea = new BuildFinishedEventArgs ("Build finished.", null, succeeded);
294                         eventSource.FireBuildFinished (this, bfea);
295                 }
296                 
297                 private void RegisterDefaultTasks ()
298                 {
299                         this.defaultTasksRegistered = false;
300                         
301                         Project defaultTasksProject = CreateNewProject ();
302                         
303                         if (binPath != null) {
304                                 if (File.Exists (Path.Combine (binPath, defaultTasksProjectName)) == true) {
305                                         defaultTasksProject.Load (Path.Combine (binPath, defaultTasksProjectName));
306                                         defaultTasks = defaultTasksProject.TaskDatabase;
307                                 } else {
308                                         defaultTasks = new TaskDatabase ();
309                                 }
310                         } else {
311                                 defaultTasks = new TaskDatabase ();
312                         }
313                         
314                         this.defaultTasksRegistered = true;
315                 }
316
317                 public string BinPath {
318                         get { return binPath; }
319                         set { binPath = value; }
320                 }
321
322                 public bool BuildEnabled {
323                         get { return buildEnabled; }
324                         set { buildEnabled = value; }
325                 }
326
327                 public static Version Version {
328                         get { return version; }
329                 }
330
331                 public static Engine GlobalEngine {
332                         get {
333                                 if (globalEngine == null)
334                                         globalEngine = new Engine ();
335                                 return globalEngine;
336                         }
337                 }
338
339                 public BuildPropertyGroup GlobalProperties {
340                         get { return globalProperties; }
341                         set { globalProperties = value; }
342                 }
343
344                 public bool OnlyLogCriticalEvents {
345                         get { return eventSource.OnlyLogCriticalEvents; }
346                         set { eventSource.OnlyLogCriticalEvents = value; }
347                 }
348                 
349                 internal EventSource EventSource {
350                         get { return eventSource; }
351                 }
352                 
353                 internal bool DefaultTasksRegistered {
354                         get { return defaultTasksRegistered; }
355                 }
356                 
357                 internal TaskDatabase DefaultTasks {
358                         get { return defaultTasks; }
359                 }
360         }
361 }
362
363 #endif