/// <summary> /// Creates a new task and adds it to the end of the list of tasks. /// </summary> /// <param name="taskName">The name of the task to create.</param> /// <param name="condition">The task's condition.</param> /// <param name="continueOnError">The continue on error flag.</param> /// <param name="msbuildRuntime">The MSBuild runtime.</param> /// <param name="msbuildArchitecture">The MSBuild architecture.</param> /// <returns>The new task instance.</returns> internal ProjectTaskInstance AddTask(string taskName, string condition, string continueOnError, string msbuildRuntime, string msbuildArchitecture) { ErrorUtilities.VerifyThrowInternalLength(taskName, "taskName"); ProjectTaskInstance task = new ProjectTaskInstance(taskName, _location, condition ?? String.Empty, continueOnError ?? String.Empty, msbuildRuntime ?? String.Empty, msbuildArchitecture ?? String.Empty); this.AddProjectTargetInstanceChild(task); return(task); }
/// <summary> /// Creates a new task and adds it to the end of the list of tasks. /// </summary> /// <param name="taskName">The name of the task to create.</param> /// <param name="condition">The task's condition.</param> /// <param name="continueOnError">The continue on error flag.</param> /// <returns>The new task instance.</returns> internal ProjectTaskInstance AddTask(string taskName, string condition, string continueOnError) { ProjectTaskInstance task = AddTask(taskName, condition, continueOnError, String.Empty, String.Empty); return(task); }
bool RunBuildTask (ProjectTargetInstance target, ProjectTaskInstance taskInstance, TargetResult targetResult, InternalBuildArguments args) { var request = submission.BuildRequest; var host = request.HostServices == null ? null : request.HostServices.GetHostObject (request.ProjectFullPath, target.Name, taskInstance.Name); // Create Task instance. var factoryIdentityParameters = new Dictionary<string,string> (); #if NET_4_5 factoryIdentityParameters ["MSBuildRuntime"] = taskInstance.MSBuildRuntime; factoryIdentityParameters ["MSBuildArchitecture"] = taskInstance.MSBuildArchitecture; #endif var task = args.BuildTaskFactory.CreateTask (taskInstance.Name, factoryIdentityParameters, this); if (task == null) throw new InvalidOperationException (string.Format ("TaskFactory {0} returned null Task", args.BuildTaskFactory)); LogMessageEvent (new BuildMessageEventArgs (string.Format ("Using task {0} from {1}", taskInstance.Name, task.GetType ()), null, null, MessageImportance.Low)); task.HostObject = host; task.BuildEngine = this; // Prepare task parameters. var evaluator = new ExpressionEvaluator (project); var evaluatedTaskParams = taskInstance.Parameters.Select (p => new KeyValuePair<string,string> (p.Key, project.ExpandString (evaluator, p.Value))); var requiredProps = task.GetType ().GetProperties () .Where (p => p.CanWrite && p.GetCustomAttributes (typeof (RequiredAttribute), true).Any ()); var missings = requiredProps.Where (p => !evaluatedTaskParams.Any (tp => tp.Key.Equals (p.Name, StringComparison.OrdinalIgnoreCase))); if (missings.Any ()) throw new InvalidOperationException (string.Format ("Task {0} of type {1} is used without specifying mandatory property: {2}", taskInstance.Name, task.GetType (), string.Join (", ", missings.Select (p => p.Name).ToArray ()))); foreach (var p in evaluatedTaskParams) { switch (p.Key.ToLower ()) { case "condition": case "continueonerror": continue; } var prop = task.GetType ().GetProperty (p.Key); if (prop == null) throw new InvalidOperationException (string.Format ("Task {0} does not have property {1}", taskInstance.Name, p.Key)); if (!prop.CanWrite) throw new InvalidOperationException (string.Format ("Task {0} has property {1} but it is read-only.", taskInstance.Name, p.Key)); if (string.IsNullOrEmpty (p.Value) && !requiredProps.Contains (prop)) continue; try { prop.SetValue (task, ConvertTo (p.Value, prop.PropertyType, evaluator), null); } catch (Exception ex) { throw new InvalidOperationException (string.Format ("Failed to convert '{0}' for property '{1}' of type {2}", p.Value, prop.Name, prop.PropertyType), ex); } } // Do execute task. bool taskSuccess = false; event_source.FireTaskStarted (this, new TaskStartedEventArgs ("Task Started", null, project.FullPath, taskInstance.FullPath, taskInstance.Name)); try { taskSuccess = task.Execute (); if (!taskSuccess) { targetResult.Failure (null); if (!ContinueOnError) { return false; } } else { // Evaluate task output properties and items. foreach (var to in taskInstance.Outputs) { if (!project.EvaluateCondition (to.Condition)) continue; var toItem = to as ProjectTaskOutputItemInstance; var toProp = to as ProjectTaskOutputPropertyInstance; string taskParameter = toItem != null ? toItem.TaskParameter : toProp.TaskParameter; var pi = task.GetType ().GetProperty (taskParameter); if (pi == null) throw new InvalidOperationException (string.Format ("Task {0} does not have property {1} specified as TaskParameter", taskInstance.Name, toItem.TaskParameter)); if (!pi.CanRead) throw new InvalidOperationException (string.Format ("Task {0} has property {1} specified as TaskParameter, but it is write-only", taskInstance.Name, toItem.TaskParameter)); var value = pi.GetValue (task, null); var valueString = ConvertFrom (value); if (toItem != null) { LogMessageEvent (new BuildMessageEventArgs (string.Format ("Output Item {0} from TaskParameter {1}: {2}", toItem.ItemType, toItem.TaskParameter, valueString), null, null, MessageImportance.Low)); Action<ITaskItem> addItem = i => { var metadata = new ArrayList (i.MetadataNames).ToArray ().Cast<string> ().Select (n => new KeyValuePair<string,string> (n, i.GetMetadata (n))); args.Project.AddItem (toItem.ItemType, i.ItemSpec, metadata); }; var taskItemArray = value as ITaskItem []; if (taskItemArray != null) { foreach (var ti in taskItemArray) addItem (ti); } else { var taskItem = value as ITaskItem; if (taskItem != null) addItem (taskItem); else foreach (var item in valueString.Split (';')) args.Project.AddItem (toItem.ItemType, item); } } else { LogMessageEvent (new BuildMessageEventArgs (string.Format ("Output Property {0} from TaskParameter {1}: {2}", toProp.PropertyName, toProp.TaskParameter, valueString), null, null, MessageImportance.Low)); args.Project.SetProperty (toProp.PropertyName, valueString); } } } } finally { event_source.FireTaskFinished (this, new TaskFinishedEventArgs ("Task Finished", null, project.FullPath, taskInstance.FullPath, taskInstance.Name, taskSuccess)); } return true; }
// FIXME: Exception should be caught at caller site. bool DoBuildTarget (ProjectTargetInstance target, TargetResult targetResult, InternalBuildArguments args) { var request = submission.BuildRequest; // Here we check cancellation (only after TargetStarted event). if (args.CheckCancel ()) { targetResult.Failure (new BuildAbortedException ("Build has canceled")); return false; } try { foreach (var child in target.Children) { // Evaluate additional target properties var tp = child as ProjectPropertyGroupTaskInstance; if (tp != null) { if (!args.Project.EvaluateCondition (tp.Condition)) continue; foreach (var p in tp.Properties) { if (!args.Project.EvaluateCondition (p.Condition)) continue; var value = args.Project.ExpandString (p.Value); project.SetProperty (p.Name, value); } continue; } var ii = child as ProjectItemGroupTaskInstance; if (ii != null) { if (!args.Project.EvaluateCondition (ii.Condition)) continue; foreach (var item in ii.Items) { if (!args.Project.EvaluateCondition (item.Condition)) continue; project.AddItem (item.ItemType, project.ExpandString (item.Include)); } continue; } var task = child as ProjectTaskInstance; if (task != null) { current_task = task; if (!args.Project.EvaluateCondition (task.Condition)) { LogMessageEvent (new BuildMessageEventArgs (string.Format ("Task '{0}' was skipped because condition '{1}' wasn't met.", task.Name, task.Condition), null, null, MessageImportance.Low)); continue; } if (!RunBuildTask (target, task, targetResult, args)) return false; continue; } var onError = child as ProjectOnErrorInstance; if (onError != null) continue; // evaluated under catch clause. throw new NotSupportedException (string.Format ("Unexpected Target element children \"{0}\"", child.GetType ())); } } catch (Exception ex) { // fallback task specified by OnError element foreach (var c in target.Children.OfType<ProjectOnErrorInstance> ()) { if (!args.Project.EvaluateCondition (c.Condition)) continue; foreach (var fallbackTarget in project.ExpandString (c.ExecuteTargets).Split (';')) BuildTargetByName (fallbackTarget, args); } int line = target.Location != null ? target.Location.Line : 0; int col = target.Location != null ? target.Location.Column : 0; LogErrorEvent (new BuildErrorEventArgs (null, null, target.FullPath, line, col, 0, 0, ex.Message, null, null)); targetResult.Failure (ex); return false; } return true; }
/// <summary> /// Builds the task specified by the XML. /// </summary> /// <param name="loggingContext">The logging context of the target</param> /// <param name="requestEntry">The build request entry being built</param> /// <param name="targetBuilderCallback">The target builder callback.</param> /// <param name="taskInstance">The task instance.</param> /// <param name="mode">The mode in which to execute tasks.</param> /// <param name="inferLookup">The lookup to be used for inference.</param> /// <param name="executeLookup">The lookup to be used during execution.</param> /// <returns>The result of running the task batch.</returns> /// <remarks> /// The ExecuteTask method takes a task as specified by XML and executes it. This procedure is comprised /// of the following steps: /// 1. Loading the Task from its containing assembly by looking it up in the task registry /// 2. Determining if the task is batched. If it is, create the batches and execute each as if it were a non-batched task /// 3. If the task is not batched, execute it. /// 4. If the task was batched, hold on to its Lookup until all of the natches are done, then merge them. /// </remarks> public async Task<WorkUnitResult> ExecuteTask(TargetLoggingContext loggingContext, BuildRequestEntry requestEntry, ITargetBuilderCallback targetBuilderCallback, ProjectTargetInstanceChild taskInstance, TaskExecutionMode mode, Lookup inferLookup, Lookup executeLookup, CancellationToken cancellationToken) { ErrorUtilities.VerifyThrow(taskInstance != null, "Need to specify the task instance."); _buildRequestEntry = requestEntry; _targetBuilderCallback = targetBuilderCallback; _cancellationToken = cancellationToken; _targetChildInstance = taskInstance; // In the case of Intrinsic tasks, taskNode will end up null. Currently this is how we distinguish // intrinsic from extrinsic tasks. _taskNode = taskInstance as ProjectTaskInstance; if (_taskNode != null && requestEntry.Request.HostServices != null) { _taskHostObject = requestEntry.Request.HostServices.GetHostObject(requestEntry.RequestConfiguration.Project.FullPath, loggingContext.Target.Name, _taskNode.Name); } _projectFullPath = requestEntry.RequestConfiguration.Project.FullPath; // this.handleId = handleId; No handles // this.parentModule = parentModule; No task execution module _continueOnError = ContinueOnError.ErrorAndStop; _targetLoggingContext = loggingContext; WorkUnitResult taskResult = new WorkUnitResult(WorkUnitResultCode.Failed, WorkUnitActionCode.Stop, null); if ((mode & TaskExecutionMode.InferOutputsOnly) == TaskExecutionMode.InferOutputsOnly) { taskResult = await ExecuteTask(TaskExecutionMode.InferOutputsOnly, inferLookup); } if ((mode & TaskExecutionMode.ExecuteTaskAndGatherOutputs) == TaskExecutionMode.ExecuteTaskAndGatherOutputs) { taskResult = await ExecuteTask(TaskExecutionMode.ExecuteTaskAndGatherOutputs, executeLookup); } return taskResult; }
bool DoBuildTarget (ProjectTargetInstance target, TargetResult targetResult, InternalBuildArguments args) { var request = submission.BuildRequest; // Here we check cancellation (only after TargetStarted event). if (args.CheckCancel ()) { targetResult.Failure (new BuildAbortedException ("Build has canceled")); return false; } var propsToRestore = new Dictionary<string,string> (); var itemsToRemove = new List<ProjectItemInstance> (); try { // Evaluate additional target properties foreach (var c in target.Children.OfType<ProjectPropertyGroupTaskInstance> ()) { if (!args.Project.EvaluateCondition (c.Condition)) continue; foreach (var p in c.Properties) { if (!args.Project.EvaluateCondition (p.Condition)) continue; var value = args.Project.ExpandString (p.Value); propsToRestore.Add (p.Name, project.GetPropertyValue (value)); project.SetProperty (p.Name, value); } } // Evaluate additional target items foreach (var c in target.Children.OfType<ProjectItemGroupTaskInstance> ()) { if (!args.Project.EvaluateCondition (c.Condition)) continue; foreach (var item in c.Items) { if (!args.Project.EvaluateCondition (item.Condition)) continue; Func<string,ProjectItemInstance> creator = i => new ProjectItemInstance (project, item.ItemType, item.Metadata.Select (m => new KeyValuePair<string,string> (m.Name, m.Value)), i); foreach (var ti in project.GetAllItems (item.Include, item.Exclude, creator, creator, s => s == item.ItemType, (ti, s) => ti.SetMetadata ("RecurseDir", s))) itemsToRemove.Add (ti); } } foreach (var c in target.Children.OfType<ProjectOnErrorInstance> ()) { if (!args.Project.EvaluateCondition (c.Condition)) continue; throw new NotImplementedException (); } // run tasks foreach (var ti in target.Children.OfType<ProjectTaskInstance> ()) { current_task = ti; if (!args.Project.EvaluateCondition (ti.Condition)) { LogMessageEvent (new BuildMessageEventArgs (string.Format ("Task '{0}' was skipped because condition '{1}' wasn't met.", ti.Name, ti.Condition), null, null, MessageImportance.Low)); continue; } if (!RunBuildTask (target, ti, targetResult, args)) return false; } } finally { // restore temporary property state to the original state. foreach (var p in propsToRestore) { if (p.Value == string.Empty) project.RemoveProperty (p.Key); else project.SetProperty (p.Key, p.Value); } foreach (var item in itemsToRemove) project.RemoveItem (item); } return true; }
/// <summary> /// Creates a new task and adds it to the end of the list of tasks. /// </summary> /// <param name="taskName">The name of the task to create.</param> /// <param name="condition">The task's condition.</param> /// <param name="continueOnError">The continue on error flag.</param> /// <returns>The new task instance.</returns> internal ProjectTaskInstance AddTask(string taskName, string condition, string continueOnError, string msbuildRuntime, string msbuildArchitecture) { ErrorUtilities.VerifyThrowInternalLength(taskName, "taskName"); ProjectTaskInstance task = new ProjectTaskInstance(taskName, _location, condition ?? String.Empty, continueOnError ?? String.Empty, msbuildRuntime ?? String.Empty, msbuildArchitecture ?? String.Empty); this.AddProjectTargetInstanceChild(task); return task; }