예제 #1
0
        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);
                }
            }
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
                }
            }
        }