Example #1
0
        /// <summary>
        /// Find all the build contexts that connects child to parent. The only time multiple contexts are possible
        /// is if the connection is formed by an IBuildEngine callback which requests the same target in the
        /// same project to be build in parallel multiple times.
        /// </summary>
        internal List <ProjectBuildState> FindConnectingContexts
        (
            TargetInProgessState child,
            TargetInProgessState parent,
            Target childTarget,
            List <ProjectBuildState> waitingStates,
            ProjectBuildState initiatingBuildContext
        )
        {
            List <ProjectBuildState> connectingContexts = new List <ProjectBuildState>();

            // Since the there is a cycle formed at the child there must be at least two requests
            // since the edge between the parent and the child is a backward edge
            ErrorUtilities.VerifyThrow(waitingStates != null, "There must be a at least two requests at the child");


            for (int i = 0; i < waitingStates.Count; i++)
            {
                if (child.CheckBuildContextForParentMatch(parentEngine.EngineCallback, parent.TargetId, childTarget, waitingStates[i]))
                {
                    connectingContexts.Add(waitingStates[i]);
                }
            }


            if (child.CheckBuildContextForParentMatch(parentEngine.EngineCallback, parent.TargetId, childTarget, initiatingBuildContext))
            {
                connectingContexts.Add(initiatingBuildContext);
            }

            return(connectingContexts);
        }
Example #2
0
        internal TargetInProgessState
        (
            EngineCallback engineCallback,
            Target target,
            List <ProjectBuildState> waitingBuildStates,
            ProjectBuildState initiatingRequest,
            BuildRequest [] outstandingBuildRequests,
            string projectName
        )
        {
            this.targetId = new TargetIdWrapper(target);
            this.outstandingBuildRequests = outstandingBuildRequests;
            // For each waiting build context try to find the parent target
            this.parentBuildRequests = new List <BuildRequest>();
            this.parentTargets       = new List <TargetIdWrapper>();
            this.projectName         = projectName;

            // Process the waiting contexts if there are any
            if (waitingBuildStates != null)
            {
                for (int i = 0; i < waitingBuildStates.Count; i++)
                {
                    ProcessBuildContext(engineCallback, waitingBuildStates[i], target);
                }
            }
            // Process the initiating context
            ProcessBuildContext(engineCallback, initiatingRequest, target);
        }
Example #3
0
        /// <summary>
        /// Given a build state try to find the parent target that caused this build state to
        /// come into being either via dependent, on error relationship or via IBuildEngine call
        /// </summary>
        internal TargetIdWrapper FindParentTarget
        (
            EngineCallback engineCallback,
            ProjectBuildState buildContext,
            Target target,
            out BuildRequest parentRequest
        )
        {
            // We need to find the parent target
            parentRequest = null;

            // Skip build states that have already been filled
            if (buildContext.CurrentBuildContextState == ProjectBuildState.BuildContextState.RequestFilled)
            {
                return(null);
            }

            // Check if the target was called due to a onerror or depends on call
            if (buildContext.ContainsBlockingTarget(target.Name))
            {
                // Figure out the record for the parent target
                Project containingProject = target.ParentProject;
                Target  parentTarget      = containingProject.Targets[buildContext.GetParentTarget(target.Name)];
                return(new TargetIdWrapper(parentTarget));
            }
            else
            {
                // The build context must have formed due to IBuildEngine call
                ErrorUtilities.VerifyThrow(
                    String.Compare(EscapingUtilities.UnescapeAll(buildContext.NameOfTargetInProgress), target.Name, StringComparison.OrdinalIgnoreCase) == 0,
                    "The target should be the in progress target for the context");
                // This target is called due to IBuildEngine or host request
                return(FindParentTargetForBuildRequest(engineCallback, buildContext.BuildRequest, out parentRequest));
            }
        }
Example #4
0
        /// <summary>
        /// Figure out the parent target or the parent build request for the given context
        /// </summary>
        private void ProcessBuildContext(EngineCallback engineCallback, ProjectBuildState buildContext, Target target)
        {
            BuildRequest    parentRequest = null;
            TargetIdWrapper parentName    = FindParentTarget(engineCallback, buildContext, target, out parentRequest);

            if (parentName != null)
            {
                parentTargets.Add(parentName);
            }
            if (parentRequest != null)
            {
                parentBuildRequests.Add(parentRequest);
            }
        }
Example #5
0
 /// <summary>
 /// Default constructor for creation of task execution wrapper
 /// </summary>
 internal TaskExecutionContext
 (
     Project parentProject,
     Target parentTarget,
     XmlElement taskNode,
     ProjectBuildState buildContext,
     int handleId,
     int nodeIndex,
     BuildEventContext taskBuildEventContext
 )
     : base(handleId, nodeIndex, taskBuildEventContext)
 {
     this.parentProject   = parentProject;
     this.parentTarget    = parentTarget;
     this.taskNode        = taskNode;
     this.buildContext    = buildContext;
     this.thrownException = null;
 }
Example #6
0
        /// <summary>
        /// This method creates a new TaskExecutionContext and return a integer token that maps to it.
        /// This method is not thread safe and must be called only from the engine thread.
        /// </summary>
        internal int CreateTaskContext
        (
            Project parentProject,
            Target parentTarget,
            ProjectBuildState buildContext,
            XmlElement taskNode,
            int nodeIndex,
            BuildEventContext taskContext
        )
        {
            int handleId = nextContextId;

            nextContextId = nextContextId + 1;

            TaskExecutionContext executionContext =
                new TaskExecutionContext(parentProject, parentTarget, taskNode, buildContext, handleId, nodeIndex, taskContext);

            executionContexts.Add(handleId, executionContext);

            return(handleId);
        }
Example #7
0
        /// <summary>
        /// This function checks if the given ProjectBuildState is caused by a given parent target (via
        /// a dependency, onerror or IBuildEngine relationship)
        /// </summary>
        internal bool CheckBuildContextForParentMatch
        (
            EngineCallback engineCallback,
            TargetIdWrapper parentId,
            Target target,
            ProjectBuildState projectBuildState
        )
        {
            BuildRequest parentRequest = null;

            TargetInProgessState.TargetIdWrapper parentName =
                FindParentTarget(engineCallback, projectBuildState, target, out parentRequest);

            if (parentName != null && parentName.Equals(parentId))
            {
                return(true);
            }

            if (parentRequest != null)
            {
                for (int j = 0; j < parentBuildRequests.Count; j++)
                {
                    if (parentRequest.HandleId == parentBuildRequests[j].HandleId &&
                        parentRequest.RequestId == parentBuildRequests[j].RequestId)
                    {
                        if (parentTargetsForBuildRequests[j].Equals(parentId))
                        {
                            return(true);
                        }
                        else
                        {
                            return(false);
                        }
                    }
                }
            }
            return(false);
        }
Example #8
0
File: Target.cs Project: 3F/IeXod
 /// <summary>
 /// This method is called repeatedly to execute the target in multi-threaded mode. In single
 /// threaded mode it is called once and it loops internally until the execution is finished.
 /// </summary>
 /// <param name="buildContext">Context within which the target is being executed</param>
 /// <param name="taskExecutionContext">Result of last execution (multi-threaded only)</param>
 internal void ContinueBuild(ProjectBuildState buildContext, TaskExecutionContext taskExecutionContext)
 {
     executionState.ContinueBuild(buildContext, taskExecutionContext);
 }
Example #9
0
File: Target.cs Project: 3F/IeXod
        /// <summary>
        /// Builds this target if it has not already been built as part of its parent project. Before we actually execute the
        /// tasks for this target, though, we first call on all the dependent targets to build themselves.
        /// This function may throw InvalidProjectFileException
        /// </summary>
        internal void Build
        (
            ProjectBuildState buildContext
        )
        {
            // Depending on the build state, we may do different things.
            switch (buildState)
            {
            case BuildState.InProgress:
                // In single proc mode if the build state was already "in progress"
                // and somebody just told us to build ourselves, it means that there is
                // a loop (circular dependency) in the target dependency graph. In multi
                // proc mode we need to analyze the dependency graph before we can
                // tell if there a circular dependency or if two independent chains
                // of targets happen to need the result of this target.
                if (parentEngine.Router.SingleThreadedMode || buildContext.ContainsCycle(this.Name))
                {
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, TargetElement, "CircularDependency", targetName);
                }
                else
                {
                    buildContext.CurrentBuildContextState = ProjectBuildState.BuildContextState.WaitingForTarget;
                    this.executionState.AddWaitingBuildContext(buildContext);
                }
                break;

            case BuildState.CompletedSuccessfully:
            case BuildState.CompletedUnsuccessfully:
                // If this target has already been built as part of this project,
                // we're not going to build it again.  Just return the result
                // from when it was built previously.  Note:  This condition
                // could really only ever hold true if the user specifically
                // requested us to build multiple targets and there existed
                // a direct or indirect dependency relationship between two or
                // more of those top-level targets.
                // Note: we aren't really entering the target in question here, so don't use the target
                // event context. Using the target ID for skipped messages would force us to
                // cache the individual target IDs for unloaded projects and it's not really worth the trouble.
                // Just use the parent event context.
                parentEngine.LoggingServices.LogComment(buildContext.ProjectBuildEventContext,
                                                        ((buildState == BuildState.CompletedSuccessfully) ? "TargetAlreadyCompleteSuccess" : "TargetAlreadyCompleteFailure"),
                                                        this.targetName);

                // Only contexts which are generated from an MSBuild task could need
                // the outputs of this target, such contexts have a non-null evaluation
                // request
                if ((buildState == BuildState.CompletedSuccessfully) &&
                    (buildContext.BuildRequest.OutputsByTarget != null &&
                     buildContext.NameOfBlockingTarget == null))
                {
                    error.VerifyThrow(
                        String.Compare(EscapingUtilities.UnescapeAll(buildContext.NameOfTargetInProgress), this.Name, StringComparison.OrdinalIgnoreCase) == 0,
                        "The name of the target in progress is inconsistent with the target being built");

                    error.VerifyThrow(targetOutputItems != null,
                                      "If the target built successfully, we must have its outputs.");

                    buildContext.BuildRequest.OutputsByTarget[Name] = targetOutputItems.ToArray();
                }

                if (buildContext.NameOfBlockingTarget == null)
                {
                    buildContext.BuildRequest.ResultByTarget[Name] = buildState;
                }
                break;

            case BuildState.NotStarted:
            case BuildState.Skipped:
            {
                // Always have to create a new context in build as other projects or targets may try and build this target
                BuildEventContext targetBuildEventContext = new BuildEventContext
                                                            (
                    buildContext.ProjectBuildEventContext.NodeId,
                    this.id,
                    buildContext.ProjectBuildEventContext.ProjectContextId,
                    buildContext.ProjectBuildEventContext.TaskId
                                                            );

                Expander expander = new Expander(this.parentProject.evaluatedProperties, this.parentProject.evaluatedItemsByName);

                // We first make sure no batching was attempted with the target's condition.
                if (!conditionCheckedForInvalidMetadataReferences)
                {
                    if (ExpressionShredder.ContainsMetadataExpressionOutsideTransform(this.Condition))
                    {
                        ProjectErrorUtilities.ThrowInvalidProject(this.conditionAttribute, "TargetConditionHasInvalidMetadataReference", targetName, this.Condition);
                    }
                    conditionCheckedForInvalidMetadataReferences = true;
                }

                // If condition is false (based on propertyBag), set this target's state to
                // "Skipped" since we won't actually build it.
                if (!Utilities.EvaluateCondition(this.Condition, this.conditionAttribute,
                                                 expander, null, ParserOptions.AllowProperties | ParserOptions.AllowItemLists,
                                                 parentEngine.LoggingServices, targetBuildEventContext))
                {
                    buildState = BuildState.Skipped;

                    if (buildContext.NameOfBlockingTarget == null)
                    {
                        buildContext.BuildRequest.ResultByTarget[Name] = buildState;
                    }

                    if (!parentEngine.LoggingServices.OnlyLogCriticalEvents)
                    {
                        // Expand the expression for the Log.
                        string expanded = expander.ExpandAllIntoString(this.Condition, this.conditionAttribute);
                        // By design: Not building dependencies. This is what NAnt does too.
                        parentEngine.LoggingServices.LogComment(targetBuildEventContext, "TargetSkippedFalseCondition",
                                                                this.targetName, this.Condition, expanded);
                    }
                }
                else
                {
                    // This target has not been built yet.  So build it!
                    // Change our state to "in progress". TargetParameters will need to be re-calculated if Inputs and Outputs attribute has changed.
                    buildState = BuildState.InProgress;
                    List <string> batchableTargetParameters = GetBatchableTargetParameters();
                    executionState = new TargetExecutionWrapper(this, taskElementList, batchableTargetParameters, targetElement, expander, targetBuildEventContext);
                    ContinueBuild(buildContext, null);
                }
            }
            break;

            default:
                error.VerifyThrow(false, "Build state {0} not handled in Target.Build method", buildState);
                break;
            }
        }