X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FMicrosoft.Build.Engine%2FMicrosoft.Build.BuildEngine%2FTarget.cs;h=b039112044481ba408352640fecd09baf3127f28;hb=d531a7515eaad9fb1c2ca9fff160851fa70aa168;hp=7fa93211063e2503d15a4cc4332f434e00e18f6a;hpb=52f8ef62f94df5fcf312e2df50401a18b92a8943;p=mono.git diff --git a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/Target.cs b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/Target.cs index 7fa93211063..b0391120444 100644 --- a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/Target.cs +++ b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/Target.cs @@ -32,21 +32,22 @@ using System.Collections; using System.Collections.Generic; using System.Xml; using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; namespace Microsoft.Build.BuildEngine { public class Target : IEnumerable { - BatchingImpl batchingImpl; + TargetBatchingImpl batchingImpl; BuildState buildState; Engine engine; - bool isImported; + ImportedProject importedProject; string name; Project project; XmlElement targetElement; List onErrorElements; List buildTasks; - internal Target (XmlElement targetElement, Project project) + internal Target (XmlElement targetElement, Project project, ImportedProject importedProject) { if (project == null) throw new ArgumentNullException ("project"); @@ -58,21 +59,25 @@ namespace Microsoft.Build.BuildEngine { this.project = project; this.engine = project.ParentEngine; - this.isImported = false;; + this.importedProject = importedProject; this.onErrorElements = new List (); this.buildState = BuildState.NotStarted; this.buildTasks = new List (); - this.batchingImpl = new BatchingImpl (project, this.targetElement); + this.batchingImpl = new TargetBatchingImpl (project, this.targetElement); + bool onErrorFound = false; foreach (XmlNode xn in targetElement.ChildNodes) { if (xn is XmlElement) { XmlElement xe = (XmlElement) xn; if (xe.Name == "OnError") { onErrorElements.Add (xe); - continue; - } - buildTasks.Add (new BuildTask (xe, this)); + onErrorFound = true; + } else if (onErrorFound) + throw new InvalidProjectFileException ( + "The element must be last under element . Found element instead."); + else + buildTasks.Add (new BuildTask (xe, this)); } } } @@ -80,7 +85,15 @@ namespace Microsoft.Build.BuildEngine { [MonoTODO] public BuildTask AddNewTask (string taskName) { - throw new NotImplementedException (); + if (taskName == null) + throw new ArgumentNullException ("taskName"); + + XmlElement task = project.XmlDocument.CreateElement (taskName, Project.XmlNamespace); + targetElement.AppendChild (task); + BuildTask bt = new BuildTask (task, this); + buildTasks.Add (bt); + + return bt; } public IEnumerator GetEnumerator () @@ -89,6 +102,7 @@ namespace Microsoft.Build.BuildEngine { yield return bt; } + // FIXME: shouldn't we remove it from XML? public void RemoveTask (BuildTask buildTask) { if (buildTask == null) @@ -96,65 +110,89 @@ namespace Microsoft.Build.BuildEngine { buildTasks.Remove (buildTask); } + // FIXME: log errors instead of throwing exceptions internal bool Build () { + bool deps; bool result; - - buildState = BuildState.Started; + + // log that target is being skipped + if (!ConditionParser.ParseAndEvaluate (Condition, Project)) + return true; + + try { + buildState = BuildState.Started; + deps = BuildDependencies (GetDependencies ()); + + result = deps ? DoBuild () : false; + + buildState = BuildState.Finished; + // FIXME: log it + } catch (Exception e) { + LogError ("Error building target {0}: {1}", Name, e.ToString ()); + return false; + } + + return result; + } + + List GetDependencies () + { + List list = new List (); + Target t; + string [] targetNames; + Expression deps; if (DependsOnTargets != String.Empty) { - Expression dependencies = new Expression (); - dependencies.Parse (DependsOnTargets); - - string[] targetsToBuildFirst = (string[]) dependencies.ConvertTo (Project, typeof (string[])); - foreach (string target in targetsToBuildFirst) { - string trimmed = target.Trim (); - Target t = (Target) project.Targets [trimmed]; + deps = new Expression (); + deps.Parse (DependsOnTargets, true); + targetNames = (string []) deps.ConvertTo (Project, typeof (string [])); + foreach (string name in targetNames) { + t = project.Targets [name.Trim ()]; if (t == null) - throw new InvalidProjectFileException (String.Format ("Target {0} not found.", trimmed)); - if (t.BuildState == BuildState.NotStarted) { - t.Build (); - } - if (t.BuildState == BuildState.Started) - throw new InvalidProjectFileException ("Cycle in target dependencies detected."); + throw new InvalidProjectFileException (String.Format ("Target '{0}' not found.", name.Trim ())); + list.Add (t); } } - - result = RealBuild (); - buildState = BuildState.Finished; - - return result; + return list; + } + + bool BuildDependencies (List deps) + { + foreach (Target t in deps) { + if (t.BuildState == BuildState.NotStarted) + if (!t.Build ()) + return false; + if (t.BuildState == BuildState.Started) + throw new InvalidProjectFileException ("Cycle in target dependencies detected"); + } + + return true; } - private bool RealBuild () + bool DoBuild () { - bool executeOnErrors = false; + bool executeOnErrors; bool result = true; + + if (BuildTasks.Count == 0) + // nothing to do + return true; - LogTargetStarted (); - - if (batchingImpl.BuildNeeded ()) { - foreach (BuildTask bt in buildTasks) { - result = batchingImpl.BatchBuildTask (bt); - - if (!result && !bt.ContinueOnError) { - executeOnErrors = true; - break; - } - } - } else { - LogTargetSkipped (); + try { + result = batchingImpl.Build (this, out executeOnErrors); + } catch (Exception e) { + LogError ("Error building target {0}: {1}", Name, e.ToString ()); + throw; } - LogTargetFinished (result); - if (executeOnErrors == true) ExecuteOnErrors (); return result; } - private void ExecuteOnErrors () + void ExecuteOnErrors () { foreach (XmlElement onError in onErrorElements) { // FIXME: add condition @@ -166,28 +204,15 @@ namespace Microsoft.Build.BuildEngine { } } - private void LogTargetSkipped () - { - BuildMessageEventArgs bmea; - bmea = new BuildMessageEventArgs (String.Format ("Skipping target \"{0}\" because its outputs are up-to-date.", - name), null, "MSBuild", MessageImportance.Normal); - engine.EventSource.FireMessageRaised (this, bmea); - } - - private void LogTargetStarted () - { - TargetStartedEventArgs tsea; - string projectFile = project.FullFileName; - tsea = new TargetStartedEventArgs ("Target " + name + " started.", null, name, projectFile, null); - engine.EventSource.FireTargetStarted (this, tsea); - } - - private void LogTargetFinished (bool succeeded) + void LogError (string message, params object [] messageArgs) { - TargetFinishedEventArgs tfea; - string projectFile = project.FullFileName; - tfea = new TargetFinishedEventArgs ("Target " + name + " finished.", null, name, projectFile, null, succeeded); - engine.EventSource.FireTargetFinished (this, tfea); + if (message == null) + throw new ArgumentException ("message"); + + BuildErrorEventArgs beea = new BuildErrorEventArgs ( + null, null, null, 0, 0, 0, 0, String.Format (message, messageArgs), + null, null); + engine.EventSource.FireErrorRaised (this, beea); } public string Condition { @@ -201,8 +226,7 @@ namespace Microsoft.Build.BuildEngine { } public bool IsImported { - get { return isImported; } - internal set { isImported = value; } + get { return importedProject != null; } } public string Name { @@ -212,10 +236,31 @@ namespace Microsoft.Build.BuildEngine { internal Project Project { get { return project; } } + + internal List BuildTasks { + get { return buildTasks; } + } + + internal Engine Engine { + get { return engine; } + } internal BuildState BuildState { get { return buildState; } } + + internal ITaskItem [] Outputs { + get { + string outputs = targetElement.GetAttribute ("Outputs"); + if (outputs == String.Empty) + return new ITaskItem [0]; + + Expression e = new Expression (); + e.Parse (outputs, true); + + return (ITaskItem []) e.ConvertTo (project, typeof (ITaskItem [])); + } + } } internal enum BuildState {