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