private void ContinueRunningTasks ( ProjectBuildState buildContext, TaskExecutionContext taskExecutionContext, bool startingFirstTask ) { bool exitDueToError = true; try { // If this is the first task - initialize for running it if (startingFirstTask) { InitializeForRunningTargetBatches(); } // If run a task then process its outputs if (currentTask != targetElement.ChildNodes.Count && !startingFirstTask) { ProcessTaskOutputs(taskExecutionContext); } // Check if we processed the last node in a batch or terminated the batch due to error if (currentTask == targetElement.ChildNodes.Count || exitBatchDueToError) { FinishRunningSingleTargetBatch(); // On failure transition into unsuccessful state if (!targetBuildSuccessful) { overallSuccess = false; FinishRunningTargetBatches(buildContext); // Transition the state machine into building the error clause state InitializeOnErrorClauseExecution(); inProgressBuildState = InProgressBuildState.BuildingErrorClause; ExecuteErrorTarget(buildContext); exitDueToError = false; return; } //Check if this was the last bucket if (currentBucket == buckets.Count) { FinishRunningTargetBatches(buildContext); inProgressBuildState = InProgressBuildState.NotInProgress; // Notify targets that are waiting for the results NotifyBuildCompletion(Target.BuildState.CompletedSuccessfully, null); exitDueToError = false; return; } // Prepare the next bucket InitializeForRunningSingleTargetBatch(); } // Execute the current task ExecuteCurrentTask(buildContext); exitDueToError = false; } catch (InvalidProjectFileException e) { // Make sure the Invalid Project error gets logged *before* TargetFinished. Otherwise, // the log is confusing. this.parentEngine.LoggingServices.LogInvalidProjectFileError(targetBuildEventContext, e); throw; } finally { if (exitDueToError && loggedTargetStart) { // Log that the target has failed parentEngine.LoggingServices.LogTargetFinished( targetBuildEventContext, targetClass.Name, this.parentProject.FullFileName, targetClass.ProjectFileOfTargetElement, false); } } }
private void ExecuteErrorTarget ( ProjectBuildState buildContext ) { if (onErrorTargets != null && currentErrorTarget < onErrorTargets.Count) { // Get the Target object for the dependent target. string nameErrorTarget = onErrorTargets[currentErrorTarget]; Target targetToBuild = parentProject.Targets[nameErrorTarget]; // If we couldn't find the on error Target object, we have a problem. ProjectErrorUtilities.VerifyThrowInvalidProject(targetToBuild != null, targetElement, "TargetDoesNotExist", nameErrorTarget); // Update the name of the blocking target buildContext.AddBlockingTarget(nameErrorTarget); } else { // We completed building the error targets so this target is now failed and we have no more work to do onErrorTargets = null; inProgressBuildState = InProgressBuildState.NotInProgress; // Call the parent project to update targets waiting on us NotifyBuildCompletion(Target.BuildState.CompletedUnsuccessfully, null); } }
private void ContinueBuildingErrorClause (ProjectBuildState buildContext) { // Verify that the target is in the right state ErrorUtilities.VerifyThrow(inProgressBuildState == InProgressBuildState.BuildingErrorClause, "Wrong state"); // Check if all dependent targets have been evaluated ErrorUtilities.VerifyThrow(currentErrorTarget < onErrorTargets.Count, "No error targets left"); // Verify that the target we were waiting on has completed building string nameErrorTarget = onErrorTargets[currentErrorTarget]; ErrorUtilities.VerifyThrow( parentProject.Targets[nameErrorTarget].TargetBuildState != Target.BuildState.InProgress && parentProject.Targets[nameErrorTarget].TargetBuildState != Target.BuildState.NotStarted || buildContext.CurrentBuildContextState == ProjectBuildState.BuildContextState.ExceptionThrown, "This target should only be updated once the error target is completed"); if (buildContext.CurrentBuildContextState == ProjectBuildState.BuildContextState.ExceptionThrown) { inProgressBuildState = InProgressBuildState.NotInProgress; // Call the parent project to update targets waiting on us NotifyBuildCompletion(Target.BuildState.CompletedUnsuccessfully, buildContext); return; } // We don't care if the target has completed successfully, we simply move on to the next one currentErrorTarget++; ExecuteErrorTarget(buildContext); }
private void ExecuteDependentTarget ( ProjectBuildState buildContext ) { if (currentDependentTarget < dependsOnTargetNames.Count) { // Get the Target object for the dependent target. string nameDependentTarget = dependsOnTargetNames[currentDependentTarget]; Target targetToBuild = parentProject.Targets[nameDependentTarget]; // If we couldn't find the dependent Target object, we have a problem. ProjectErrorUtilities.VerifyThrowInvalidProject(targetToBuild != null, targetClass.DependsOnTargetsAttribute, "TargetDoesNotExist", nameDependentTarget); // Update the name of the blocking target buildContext.AddBlockingTarget(nameDependentTarget); } else { // We completed building the dependencies so we need to start running the tasks dependsOnTargetNames = null; inProgressBuildState = InProgressBuildState.RunningTasks; ContinueRunningTasks(buildContext, null, true); } }
private void ContinueBuildingDependencies (ProjectBuildState buildContext) { // Verify that the target is in the right state ErrorUtilities.VerifyThrow(inProgressBuildState == InProgressBuildState.BuildingDependencies, "Wrong state"); // Check if all dependent targets have been evaluated ErrorUtilities.VerifyThrow(currentDependentTarget < dependsOnTargetNames.Count, "No dependent targets left"); // Verify that the target we were waiting on has completed building string nameDependentTarget = dependsOnTargetNames[currentDependentTarget]; ErrorUtilities.VerifyThrow( parentProject.Targets[nameDependentTarget].TargetBuildState != Target.BuildState.InProgress && parentProject.Targets[nameDependentTarget].TargetBuildState != Target.BuildState.NotStarted || buildContext.CurrentBuildContextState == ProjectBuildState.BuildContextState.ExceptionThrown, "This target should only be updated once the dependent target is completed"); if (buildContext.CurrentBuildContextState == ProjectBuildState.BuildContextState.ExceptionThrown) { inProgressBuildState = InProgressBuildState.NotInProgress; // Call the parent project to update targets waiting on us NotifyBuildCompletion(Target.BuildState.CompletedUnsuccessfully, buildContext); return; } // If the dependent target failed to build we need to execute the onerrorclause (if there is one) // or mark this target as failed (if there is not an error clause) else if (parentProject.Targets[nameDependentTarget].TargetBuildState == Target.BuildState.CompletedUnsuccessfully) { // Transition the state machine into building the error clause state InitializeOnErrorClauseExecution(); inProgressBuildState = InProgressBuildState.BuildingErrorClause; ExecuteErrorTarget(buildContext); return; } // Now that the previous dependent target has been build we need to move to the next dependent target if // there is one currentDependentTarget++; // Execute the current target or transition to a different state if necessary ExecuteDependentTarget(buildContext); }
internal void ContinueBuild ( ProjectBuildState buildContext, TaskExecutionContext taskExecutionContext ) { // Verify that the target is in progress ErrorUtilities.VerifyThrow(inProgressBuildState != InProgressBuildState.NotInProgress, "Not in progress"); bool exitedDueToError = true; try { // In the single threaded mode we want to avoid looping all the way back to the // engine because there is no need for to be interruptable to address // other build requests. Instead we loop inside this function untill the target is // fully built. do { // Transition the state machine appropriatly if (inProgressBuildState == InProgressBuildState.RunningTasks) { ContinueRunningTasks(buildContext, taskExecutionContext, false); } else if (inProgressBuildState == InProgressBuildState.BuildingDependencies) { ContinueBuildingDependencies(buildContext); } else if (inProgressBuildState == InProgressBuildState.StartingBuild) { initiatingBuildContext = buildContext; inProgressBuildState = InProgressBuildState.BuildingDependencies; currentDependentTarget = 0; ExecuteDependentTarget(buildContext); } else if (inProgressBuildState == InProgressBuildState.BuildingErrorClause) { ContinueBuildingErrorClause(buildContext); } // In the single threaded mode we need to pull up the outputs of the previous // step if (parentEngine.Router.SingleThreadedMode && inProgressBuildState == InProgressBuildState.RunningTasks) { taskExecutionContext = parentEngine.GetTaskOutputUpdates(); } } while (parentEngine.Router.SingleThreadedMode && inProgressBuildState == InProgressBuildState.RunningTasks); // Indicate that we exited successfully exitedDueToError = false; } finally { if (exitedDueToError) { inProgressBuildState = InProgressBuildState.NotInProgress; NotifyBuildCompletion(Target.BuildState.CompletedUnsuccessfully, buildContext); } } }