/// <summary> /// Creates and caches a built result. /// </summary> private BuildResult CacheBuildResult(BuildRequest request, string target, WorkUnitResult workUnitResult) { BuildResult result = CreateBuildResult(request, target, workUnitResult); IResultsCache resultsCache = _host.GetComponent(BuildComponentType.ResultsCache) as IResultsCache; resultsCache.AddResult(result); return(result); }
internal void SetResultsToReturn(BuildResult result) { _cache.AddResult(result); }
/// <summary> /// Thread to process the build request /// </summary> private void BuilderThreadProc() { bool completeSuccess = true; WaitHandle[] handles = new WaitHandle[2] { _cancelEvent, _continueEvent }; _threadStarted.Set(); // Add a request for each of the referenced projects. All we need to do is to make sure that the new project definition for the referenced // project has been added to the host collection FullyQualifiedBuildRequest[] fq = new FullyQualifiedBuildRequest[_currentProjectDefinition.ChildDefinitions.Count]; int fqCount = 0; foreach (RequestDefinition childDefinition in _currentProjectDefinition.ChildDefinitions) { BuildRequestConfiguration unresolvedConfig = childDefinition.UnresolvedConfiguration; fq[fqCount++] = new FullyQualifiedBuildRequest(unresolvedConfig, childDefinition.TargetsToBuild, true); } try { // Check to see if there was a cancel before we do anything if (_cancelEvent.WaitOne(1, false)) { HandleCancel(); return; } // Submit the build request for the references if we have any if (fqCount > 0) { OnNewBuildRequests(_requestedEntry, fq); // Wait for all of them to complete till our entry is marked ready int evt = WaitHandle.WaitAny(handles); // If a cancel occurs then we are done. Set the result to an exception if (evt == 0) { HandleCancel(); return; } // If we get a continue then one of the reference has complete. Set the result in the cache only in case of success. // Even though there may have been error - we cannot abandone the loop as there are already // requests in progress which may call back to this thread else if (evt == 1) { IDictionary <int, BuildResult> results = _requestedEntry.Continue(); foreach (BuildResult configResult in results.Values) { if (configResult.OverallResult == BuildResultCode.Failure) { completeSuccess = false; } else { _resultsCache.AddResult(configResult); } } } } // Check to see if there was a cancel we process the final result if (_cancelEvent.WaitOne(1, false)) { HandleCancel(); return; } // Simulate execution time for the actual entry if one was specified and if the entry built successfully if (_currentProjectDefinition.ExecutionTime > 0 && completeSuccess == true) { Thread.Sleep(_currentProjectDefinition.ExecutionTime); } // Create and send the result BuildResult result = new BuildResult(_requestedEntry.Request); // No specific target was asked to build. Return the default result if (_requestedEntry.Request.Targets.Count == 0) { result.AddResultsForTarget(RequestDefinition.defaultTargetName, new TargetResult(new TaskItem[1], completeSuccess ? TestUtilities.GetSuccessResult() : TestUtilities.GetStopWithErrorResult())); } else { foreach (string target in _requestedEntry.Request.Targets) { result.AddResultsForTarget(target, new TargetResult(new TaskItem[1], completeSuccess ? TestUtilities.GetSuccessResult() : TestUtilities.GetStopWithErrorResult())); } } _resultsCache.AddResult(result); _requestedEntry.Complete(result); RaiseRequestComplete(_requestedEntry); return; } catch (Exception e) { if (_requestedEntry != null) { string message = String.Format("Test: Unhandeled exception occured: \nMessage: {0} \nStack:\n{1}", e.Message, e.StackTrace); BuildResult errorResult = new BuildResult(_requestedEntry.Request, new InvalidOperationException(message)); _requestedEntry.Complete(errorResult); RaiseRequestComplete(_requestedEntry); } } }
/// <summary> /// Builds the specified targets. /// </summary> /// <param name="loggingContext">The logging context for the project.</param> /// <param name="entry">The BuildRequestEntry for which we are building targets.</param> /// <param name="callback">The callback to be used to handle new project build requests.</param> /// <param name="targetNames">The names of the targets to build.</param> /// <param name="baseLookup">The Lookup containing all current items and properties for this target.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> to use when building the targets.</param> /// <returns>The target's outputs and result codes</returns> public async Task <BuildResult> BuildTargets(ProjectLoggingContext loggingContext, BuildRequestEntry entry, IRequestBuilderCallback callback, string[] targetNames, Lookup baseLookup, CancellationToken cancellationToken) { ErrorUtilities.VerifyThrowArgumentNull(loggingContext, "projectLoggingContext"); ErrorUtilities.VerifyThrowArgumentNull(entry, nameof(entry)); ErrorUtilities.VerifyThrowArgumentNull(callback, "requestBuilderCallback"); ErrorUtilities.VerifyThrowArgumentNull(targetNames, nameof(targetNames)); ErrorUtilities.VerifyThrowArgumentNull(baseLookup, nameof(baseLookup)); ErrorUtilities.VerifyThrow(targetNames.Length > 0, "List of targets must be non-empty"); ErrorUtilities.VerifyThrow(_componentHost != null, "InitializeComponent must be called before building targets."); _requestEntry = entry; _requestBuilderCallback = callback; _projectLoggingContext = loggingContext; _cancellationToken = cancellationToken; // Clone the base lookup so that if we are re-entered by another request while this one in blocked, we don't have visibility to // their state, and they have no visibility into ours. _baseLookup = baseLookup.Clone(); _targetsToBuild = new ConcurrentStack <TargetEntry>(); // Get the actual target objects from the names BuildRequestConfiguration configuration = _requestEntry.RequestConfiguration; bool previousCacheableStatus = configuration.IsCacheable; configuration.IsCacheable = false; configuration.RetrieveFromCache(); _projectInstance = configuration.Project; // Now get the current results cache entry. IResultsCache resultsCache = (IResultsCache)_componentHost.GetComponent(BuildComponentType.ResultsCache); BuildResult existingBuildResult = resultsCache.GetResultsForConfiguration(_requestEntry.Request.ConfigurationId); _buildResult = new BuildResult(entry.Request, existingBuildResult, null); if (existingBuildResult == null) { // Add this result so that if our project gets re-entered we won't rebuild any targets we have already built. resultsCache.AddResult(_buildResult); } List <TargetSpecification> targets = new List <TargetSpecification>(targetNames.Length); foreach (string targetName in targetNames) { var targetExists = _projectInstance.Targets.ContainsKey(targetName); if (!targetExists && entry.Request.BuildRequestDataFlags.HasFlag(BuildRequestDataFlags.SkipNonexistentTargets)) { _projectLoggingContext.LogComment(Framework.MessageImportance.Low, "TargetSkippedWhenSkipNonexistentTargets", targetName); continue; } targets.Add(new TargetSpecification(targetName, targetExists ? _projectInstance.Targets[targetName].Location : _projectInstance.ProjectFileLocation)); } // Push targets onto the stack. This method will reverse their push order so that they // get built in the same order specified in the array. await PushTargets(targets, null, baseLookup, false, false, TargetBuiltReason.None); // Now process the targets ITaskBuilder taskBuilder = _componentHost.GetComponent(BuildComponentType.TaskBuilder) as ITaskBuilder; try { await ProcessTargetStack(taskBuilder); } finally { // If there are still targets left on the stack, they need to be removed from the 'active targets' list foreach (TargetEntry target in _targetsToBuild) { configuration.ActivelyBuildingTargets.Remove(target.Name); } ((IBuildComponent)taskBuilder).ShutdownComponent(); } if (_cancellationToken.IsCancellationRequested) { throw new BuildAbortedException(); } // Gather up outputs for the requested targets and return those. All of our information should be in the base lookup now. ComputeAfterTargetFailures(targetNames); BuildResult resultsToReport = new BuildResult(_buildResult, targetNames); // Return after-build project state if requested. if (_requestEntry.Request.BuildRequestDataFlags.HasFlag(BuildRequestDataFlags.ProvideProjectStateAfterBuild)) { resultsToReport.ProjectStateAfterBuild = _projectInstance; } if (_requestEntry.Request.RequestedProjectState != null) { resultsToReport.ProjectStateAfterBuild = _projectInstance.FilteredCopy(_requestEntry.Request.RequestedProjectState); } configuration.IsCacheable = previousCacheableStatus; return(resultsToReport); }
/// <summary> /// Call the actual implementation /// </summary> /// <param name="result">The result to add.</param> public void AddResult(BuildResult result) { _addCount++; _resultCache.AddResult(result); }