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