buildTasks.Remove (buildTask);
}
- internal bool Build ()
+ bool Build ()
+ {
+ return Build (null);
+ }
+
+ internal bool Build (string built_targets_key)
{
bool executeOnErrors;
- return Build (out executeOnErrors);
+ return Build (built_targets_key, out executeOnErrors);
+ }
+
+ bool Build (string built_targets_key, out bool executeOnErrors)
+ {
+ project.PushThisFileProperty (TargetFile);
+ try {
+ return BuildActual (built_targets_key, out executeOnErrors);
+ } finally {
+ project.PopThisFileProperty ();
+ }
}
- internal bool Build (out bool executeOnErrors)
+ bool BuildActual (string built_targets_key, out bool executeOnErrors)
{
bool result = false;
executeOnErrors = false;
+ // built targets are keyed by the particular set of global
+ // properties. So, a different set could allow a target
+ // to run again
+ built_targets_key = project.GetKeyForTarget (Name);
+ if (project.ParentEngine.BuiltTargetsOutputByName.ContainsKey (built_targets_key)) {
+ LogTargetSkipped ();
+ return true;
+ }
+
+ // Push a null/empty batch, effectively clearing it
+ project.PushBatch (null, null);
if (!ConditionParser.ParseAndEvaluate (Condition, Project)) {
LogMessage (MessageImportance.Low,
"Target {0} skipped due to false condition: {1}",
Name, Condition);
+ project.PopBatch ();
return true;
}
} catch (Exception e) {
LogError ("Error building target {0}: {1}", Name, e.ToString ());
return false;
+ } finally {
+ project.PopBatch ();
}
+ project.ParentEngine.BuiltTargetsOutputByName [built_targets_key] = (ITaskItem[]) Outputs.Clone ();
+
return result;
}
if (DependsOnTargets != String.Empty) {
deps = new Expression ();
- deps.Parse (DependsOnTargets, true);
+ deps.Parse (DependsOnTargets, ParseOptions.AllowItemsNoMetadataAndSplit);
targetNames = (string []) deps.ConvertTo (Project, typeof (string []));
foreach (string dep_name in targetNames) {
t = project.Targets [dep_name.Trim ()];
executeOnErrors = false;
foreach (Target t in deps) {
if (t.BuildState == BuildState.NotStarted)
- if (!t.Build (out executeOnErrors))
+ if (!t.Build (null, out executeOnErrors))
return false;
if (t.BuildState == BuildState.Started)
throw new InvalidProjectFileException ("Cycle in target dependencies detected");
}
}
+ void LogTargetSkipped ()
+ {
+ BuildMessageEventArgs bmea;
+ bmea = new BuildMessageEventArgs (String.Format (
+ "Target {0} skipped, as it has already been built.", Name),
+ null, null, MessageImportance.Low);
+
+ project.ParentEngine.EventSource.FireMessageRaised (this, bmea);
+ }
+
void LogError (string message, params object [] messageArgs)
{
if (message == null)
get { return project; }
}
+ internal string TargetFile {
+ get {
+ if (importedProject != null)
+ return importedProject.FullFileName;
+ return project != null ? project.FullFileName : String.Empty;
+ }
+ }
+
internal List<BuildTask> BuildTasks {
get { return buildTasks; }
}
return new ITaskItem [0];
Expression e = new Expression ();
- e.Parse (outputs, true);
+ e.Parse (outputs, ParseOptions.AllowItemsNoMetadataAndSplit);
return (ITaskItem []) e.ConvertTo (project, typeof (ITaskItem []));
}