2007-02-03 Marek Sieradzki <marek.sieradzki@gmail.com>
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / Engine.cs
index c71d3e01b464fb03d03dd4913140d2c617fe287d..9f6befa5da82440cf5f0c08f740b53fe3a1ef62f 100644 (file)
 
 using System;
 using System.Collections;
+using System.Collections.Generic;
+using System.IO;
 using Microsoft.Build.Framework;
+using Mono.XBuild.Utilities;
 
 namespace Microsoft.Build.BuildEngine {
        public class Engine {
                
                string                  binPath;
                bool                    buildEnabled;
+               TaskDatabase            defaultTasks;
+               bool                    defaultTasksRegistered;
+               const string            defaultTasksProjectName = "Microsoft.Common.tasks";
                EventSource             eventSource;
                bool                    buildStarted;
                BuildPropertyGroup      globalProperties;
-               IDictionary             importedProjects;
-               IList                   loggers;
-               bool                    onlyLogCriticalEvents;
-               IDictionary             projects;
+               //IDictionary           importedProjects;
+               List <ILogger>          loggers;
+               //bool                  onlyLogCriticalEvents;
+               Dictionary <string, Project>    projects;
 
                static Engine           globalEngine;
                static Version          version;
@@ -63,13 +69,13 @@ namespace Microsoft.Build.BuildEngine {
                {
                        this.binPath = binPath;
                        this.buildEnabled = true;
-                       this.projects = new Hashtable ();
+                       this.projects = new Dictionary <string, Project> ();
                        this.eventSource = new EventSource ();
-                       this.loggers = new ArrayList ();
+                       this.loggers = new List <ILogger> ();
                        this.buildStarted = false;
                        this.globalProperties = new BuildPropertyGroup ();
                        
-                       // FIXME:add loading of default tasks
+                       RegisterDefaultTasks ();
                }
                
                [MonoTODO]
@@ -81,13 +87,13 @@ namespace Microsoft.Build.BuildEngine {
                [MonoTODO]
                public bool BuildProject (Project project, string targetName)
                {
-                       return BuildProject (project, new string[] { targetName}, new Hashtable (), BuildSettings.None);
+                       return BuildProject (project, new string[] { targetName}, null, BuildSettings.None);
                }
                
                [MonoTODO]
                public bool BuildProject (Project project, string[] targetNames)
                {
-                       return BuildProject (project, targetNames, new Hashtable (), BuildSettings.None);
+                       return BuildProject (project, targetNames, null, BuildSettings.None);
                }
 
                [MonoTODO]
@@ -105,6 +111,8 @@ namespace Microsoft.Build.BuildEngine {
                                          BuildSettings buildFlags)
                {
                        bool result;
+
+                       StartBuild ();
                        
                        LogProjectStarted (project, targetNames);
                                
@@ -140,7 +148,7 @@ namespace Microsoft.Build.BuildEngine {
                                              string[] targetNames,
                                              BuildPropertyGroup globalProperties)
                {
-                       return BuildProjectFile (projectFile, targetNames, globalProperties, new Hashtable (), BuildSettings.None);
+                       return BuildProjectFile (projectFile, targetNames, globalProperties, null, BuildSettings.None);
                }
                
                [MonoTODO]
@@ -161,21 +169,26 @@ namespace Microsoft.Build.BuildEngine {
                {
                        bool result;
                        Project project;
+
+                       StartBuild ();
                        
-                       if (projects.Contains (projectFile)) {
+                       if (projects.ContainsKey (projectFile)) {
                                project = (Project) projects [projectFile];
                                LogProjectStarted (project, targetNames);
                                result = project.Build (targetNames, targetOutputs);
+                       } else {
+                               project = CreateNewProject ();
+                               project.Load (projectFile);
+                               LogProjectStarted (project, targetNames);
+                               result = project.Build (targetNames, targetOutputs);
                        }
-                       else
-                               return false;
                        
                        LogProjectFinished (project, result);
                        
                        return result;
                }
 
-               private void CheckBinPath ()
+               void CheckBinPath ()
                {
                        if (BinPath == null) {
                                throw new InvalidOperationException ("Before a project can be instantiated, " +
@@ -186,9 +199,8 @@ namespace Microsoft.Build.BuildEngine {
 
                public Project CreateNewProject ()
                {
-                       CheckBinPath ();
-                       // FIXME: I don't really know if it should be here
-                       LogBuildStarted ();
+                       if (defaultTasksRegistered)
+                               CheckBinPath ();
                        return new Project (this);
                }
 
@@ -197,7 +209,8 @@ namespace Microsoft.Build.BuildEngine {
                        if (projectFullFileName == null)
                                throw new ArgumentNullException ("projectFullFileName");
                        
-                       return (Project) projects [projectFullFileName];
+                       // FIXME: test it
+                       return projects [projectFullFileName];
                }
 
                internal void RemoveLoadedProject (Project p)
@@ -214,8 +227,11 @@ namespace Microsoft.Build.BuildEngine {
        
                public void UnloadProject (Project project)
                {
+                       if (project == null)
+                               throw new ArgumentNullException ("project");
+
                        if (project.ParentEngine != this)
-                               throw new InvalidOperationException ("This project is not loaded in this engine");
+                               throw new InvalidOperationException ("The \"Project\" object specified does not belong to the correct \"Engine\" object.");
                        
                        project.CheckUnloaded ();
                        
@@ -227,8 +243,8 @@ namespace Microsoft.Build.BuildEngine {
 
                public void UnloadAllProjects ()
                {
-                       foreach (DictionaryEntry e in projects)
-                               UnloadProject ((Project) e.Value);
+                       foreach (KeyValuePair <string, Project> e in projects)
+                               UnloadProject (e.Value);
                }
 
                [MonoTODO]
@@ -245,14 +261,23 @@ namespace Microsoft.Build.BuildEngine {
                public void UnregisterAllLoggers ()
                {
                        // FIXME: check if build succeeded
+                       // FIXME: it shouldn't be here
                        LogBuildFinished (true);
                        foreach (ILogger i in loggers) {
                                i.Shutdown ();
                        }
                        loggers.Clear ();
                }
+
+               internal void StartBuild ()
+               {
+                       if (!buildStarted) {
+                               LogBuildStarted ();
+                               buildStarted = true;
+                       }
+               }
                
-               private void LogProjectStarted (Project project, string[] targetNames)
+               void LogProjectStarted (Project project, string [] targetNames)
                {
                        ProjectStartedEventArgs psea;
                        if (targetNames.Length == 0) {
@@ -267,26 +292,44 @@ namespace Microsoft.Build.BuildEngine {
                        eventSource.FireProjectStarted (this, psea);
                }
                
-               private void LogProjectFinished (Project project, bool succeeded)
+               void LogProjectFinished (Project project, bool succeeded)
                {
                        ProjectFinishedEventArgs pfea;
                        pfea = new ProjectFinishedEventArgs ("Project started.", null, project.FullFileName, succeeded);
                        eventSource.FireProjectFinished (this, pfea);
                }
                
-               private void LogBuildStarted ()
+               void LogBuildStarted ()
                {
                        BuildStartedEventArgs bsea;
                        bsea = new BuildStartedEventArgs ("Build started.", null);
                        eventSource.FireBuildStarted (this, bsea);
                }
                
-               private void LogBuildFinished (bool succeeded)
+               void LogBuildFinished (bool succeeded)
                {
                        BuildFinishedEventArgs bfea;
                        bfea = new BuildFinishedEventArgs ("Build finished.", null, succeeded);
                        eventSource.FireBuildFinished (this, bfea);
                }
+               
+               void RegisterDefaultTasks ()
+               {
+                       this.defaultTasksRegistered = false;
+                       
+                       Project defaultTasksProject = CreateNewProject ();
+                       
+                       if (binPath != null) {
+                               if (File.Exists (Path.Combine (binPath, defaultTasksProjectName))) {
+                                       defaultTasksProject.Load (Path.Combine (binPath, defaultTasksProjectName));
+                                       defaultTasks = defaultTasksProject.TaskDatabase;
+                               } else
+                                       defaultTasks = new TaskDatabase ();
+                       } else
+                               defaultTasks = new TaskDatabase ();
+                       
+                       this.defaultTasksRegistered = true;
+               }
 
                public string BinPath {
                        get { return binPath; }
@@ -323,6 +366,14 @@ namespace Microsoft.Build.BuildEngine {
                internal EventSource EventSource {
                        get { return eventSource; }
                }
+               
+               internal bool DefaultTasksRegistered {
+                       get { return defaultTasksRegistered; }
+               }
+               
+               internal TaskDatabase DefaultTasks {
+                       get { return defaultTasks; }
+               }
        }
 }