public void Initialize() { // Create some items and place them in a dictionary // Add some include information so that when we check the final // item spec we can verify that the item was recreated properly BuildItem buildItem1 = new BuildItem("BuildItem1", "Item1"); buildItem1.Include = "TestInclude1"; BuildItem[] buildItems = new BuildItem[1]; buildItems[0] = buildItem1; Dictionary<object, object> dictionary = new Dictionary<object, object>(); dictionary.Add("TaskItems", buildItems); Hashtable resultByTargetSuccess = new Hashtable(StringComparer.OrdinalIgnoreCase); resultByTargetSuccess.Add("TaskItems", Target.BuildState.CompletedSuccessfully); Hashtable resultByTargetFailure = new Hashtable(StringComparer.OrdinalIgnoreCase); resultByTargetFailure.Add("TaskItems", Target.BuildState.CompletedUnsuccessfully); Hashtable resultByTargetSkipped = new Hashtable(StringComparer.OrdinalIgnoreCase); resultByTargetSkipped.Add("TaskItems", Target.BuildState.Skipped); resultWithOutputs = new BuildResult(dictionary, resultByTargetSuccess, true, 1, 1, 3, true, string.Empty, string.Empty, 0, 0, 0); failedResult = new BuildResult(dictionary, resultByTargetFailure, false, 1, 1, 3, true, string.Empty, string.Empty, 0, 0, 0); uncacheableResult = new BuildResult(dictionary, resultByTargetSkipped, true, 1, 1, 3, true, string.Empty, string.Empty, 0, 0, 0); cacheScope = new CacheScope("temp.proj", new BuildPropertyGroup(), "3.5"); }
public void Initialize() { // Create some items and place them in a dictionary // Add some include information so that when we check the final // item spec we can verify that the item was recreated properly BuildItem[] buildItems = new BuildItem[1]; buildItems[0] = new BuildItem("BuildItem1", "Item1"); Dictionary<object, object> dictionary1 = new Dictionary<object, object>(); dictionary1.Add("Target1", buildItems); Hashtable resultsByTarget1 = new Hashtable(StringComparer.OrdinalIgnoreCase); resultsByTarget1.Add("Target1", Target.BuildState.CompletedSuccessfully); Dictionary<object, object> dictionary2 = new Dictionary<object, object>(); dictionary2.Add("Target2", buildItems); dictionary2.Add("Target3", null); Hashtable resultsByTarget2 = new Hashtable(StringComparer.OrdinalIgnoreCase); resultsByTarget2.Add("Target2", Target.BuildState.CompletedSuccessfully); resultsByTarget2.Add("Target3", Target.BuildState.CompletedSuccessfully); Dictionary<object, object> dictionary3 = new Dictionary<object, object>(); dictionary3.Add("Target4", buildItems); Hashtable resultsByTarget3 = new Hashtable(StringComparer.OrdinalIgnoreCase); resultsByTarget3.Add("Target4", Target.BuildState.Skipped); resultWith0Outputs = new BuildResult(new Hashtable(), new Hashtable(StringComparer.OrdinalIgnoreCase), true, 1, 1, 2, true, string.Empty, string.Empty, 0, 0, 0); resultWith1Outputs = new BuildResult(dictionary1, resultsByTarget1, true, 1, 1, 2, true, string.Empty, string.Empty, 0, 0, 0); resultWith2Outputs = new BuildResult(dictionary2, resultsByTarget2, true, 1, 1, 2, true, string.Empty, string.Empty, 0, 0, 0); uncacheableResult = new BuildResult(dictionary3, resultsByTarget3, true, 1, 1, 2, true, string.Empty, string.Empty, 0, 0, 0); }
public void TestConstructorsAndProperties() { BuildResult resultWithOutputsFromBuildResult = new BuildResult(resultWithOutputs, false /* shallow copy */); Assert.IsNotNull(resultWithOutputsFromBuildResult.OutputsByTarget, "Exepcted resultWithOutputsFromBuildResult.OutputsByTarget to not be null"); Assert.IsTrue(resultWithOutputsFromBuildResult.EvaluationResult, "Expected resultWithOutputsFromBuildResult.EvaluationResult to be true"); Assert.AreEqual(0, resultWithOutputsFromBuildResult.HandleId, "Expected resultWithOutputsFromBuildResult.NodeProxyId to be 0"); Assert.AreEqual(1, resultWithOutputsFromBuildResult.RequestId, "Expected resultWithOutputsFromBuildResult.RequestId to be 1"); Assert.AreEqual(2, resultWithOutputsFromBuildResult.ProjectId, "Expected resultWithOutputsFromBuildResult.ProjectId to be 1"); // Test some setters which are not set otherwise during the tests resultWithOutputsFromBuildResult.HandleId = 3; resultWithOutputsFromBuildResult.RequestId = 4; Assert.AreEqual(3, resultWithOutputsFromBuildResult.HandleId, "Expected resultWithOutputsFromBuildResult.NodeProxyId to be 3"); Assert.AreEqual(4, resultWithOutputsFromBuildResult.RequestId, "Expected resultWithOutputsFromBuildResult.RequestId to be 4"); resultWithOutputsFromBuildResult = new BuildResult(resultWithOutputs, true /* deep copy */); Assert.IsNotNull(resultWithOutputsFromBuildResult.OutputsByTarget, "Exepcted resultWithOutputsFromBuildResult.OutputsByTarget to not be null"); Assert.IsTrue(resultWithOutputsFromBuildResult.EvaluationResult, "Expected resultWithOutputsFromBuildResult.EvaluationResult to be true"); Assert.AreEqual(0, resultWithOutputsFromBuildResult.HandleId, "Expected resultWithOutputsFromBuildResult.NodeProxyId to be 0"); Assert.AreEqual(1, resultWithOutputsFromBuildResult.RequestId, "Expected resultWithOutputsFromBuildResult.RequestId to be 1"); Assert.AreEqual(2, resultWithOutputsFromBuildResult.ProjectId, "Expected resultWithOutputsFromBuildResult.ProjectId to be 1"); // Test some setters which are not set otherwise during the tests resultWithOutputsFromBuildResult.HandleId = 3; resultWithOutputsFromBuildResult.RequestId = 4; Assert.AreEqual(3, resultWithOutputsFromBuildResult.HandleId, "Expected resultWithOutputsFromBuildResult.NodeProxyId to be 3"); Assert.AreEqual(4, resultWithOutputsFromBuildResult.RequestId, "Expected resultWithOutputsFromBuildResult.RequestId to be 4"); // Test the setting of RequestId resultWithOutputsFromBuildResult.RequestId = 4; Assert.AreEqual(4, resultWithOutputsFromBuildResult.RequestId, "Expected resultWithOutputsFromBuildResult.RequestId to be 4"); }
/// <summary> /// Copy constructor /// </summary> internal BuildResult (BuildResult buildResultToCopy, bool deepCopy) { ErrorUtilities.VerifyThrowArgumentNull(buildResultToCopy, "Cannot have a null build result passed in"); this.flags = buildResultToCopy.flags; this.handleId = buildResultToCopy.handleId; this.requestId = buildResultToCopy.requestId; this.projectId = buildResultToCopy.projectId; this.outputsByTarget = new Hashtable(); this.defaultTargets = buildResultToCopy.defaultTargets; this.initialTargets = buildResultToCopy.initialTargets; this.resultByTarget = new Hashtable(buildResultToCopy.resultByTarget, StringComparer.OrdinalIgnoreCase); if (buildResultToCopy.outputsByTarget == null) { return; } if (deepCopy) { // Copy all the old data foreach (DictionaryEntry entry in buildResultToCopy.outputsByTarget) { // Make deep copies of all the target outputs before // passing them back BuildItem[] originalArray = (BuildItem[])entry.Value; BuildItem[] itemArray = new BuildItem[originalArray.Length]; for (int i = 0; i < originalArray.Length; i++) { if (!originalArray[i].IsUninitializedItem) { itemArray[i] = originalArray[i].Clone(); itemArray[i].CloneVirtualMetadata(); } else { itemArray[i] = new BuildItem(null, originalArray[i].FinalItemSpecEscaped); } } this.outputsByTarget.Add(entry.Key, itemArray); } } else { // Create a new hashtable but point at the same data foreach (DictionaryEntry entry in buildResultToCopy.outputsByTarget) { this.outputsByTarget.Add(entry.Key, entry.Value); } } }
public void Initialize() { // Create some items and place them in a dictionary // Add some include information so that when we check the final // item spec we can verify that the item was recreated properly buildItem1.Include = "TestInclude1"; buildItem2.Include = "TestInclude2"; BuildItem[] taskItems = new BuildItem[2]; taskItems[0] = buildItem1; taskItems[1] = buildItem2; Dictionary<object, object> dictionary = new Dictionary<object, object>(); dictionary.Add("TaskItems", taskItems); resultNoOutputs = new BuildResult(null, new Hashtable(StringComparer.OrdinalIgnoreCase), true, 0, 1, 2, true, string.Empty, string.Empty, 0, 0, 0); resultWithOutputs = new BuildResult(dictionary, new Hashtable(StringComparer.OrdinalIgnoreCase), true, 0, 1, 2, true, string.Empty, string.Empty, 0, 0, 0); }
/// <summary> /// Pretend we're actually building a project when really we're just retrieving the results from the cache. /// </summary> /// <param name="buildRequest"></param> /// <param name="projectFileInfo"></param> /// <param name="actuallyBuiltTargets"></param> /// <param name="cachedResult"></param> private void ProcessCachedResult ( BuildRequest buildRequest, FileInfo projectFileInfo, ArrayList actuallyBuiltTargets, BuildResult cachedResult ) { buildRequest.InitializeFromCachedResult(cachedResult); if (Engine.debugMode) { Console.WriteLine("===Reusing cached result for " + buildRequest.GetTargetNamesList() + " in " + buildRequest.ProjectFileName + " result is " + buildRequest.BuildSucceeded + " EngineNodeID: " + this.nodeId); } BuildEventContext requestContext = buildRequest.ParentBuildEventContext; BuildEventContext currentContext = new BuildEventContext(this.nodeId, BuildEventContext.InvalidTargetId, GetNextProjectId(), BuildEventContext.InvalidTaskId); primaryLoggingServices.LogProjectStarted(cachedResult.ProjectId, requestContext, currentContext, projectFileInfo.FullName, buildRequest.GetTargetNamesList(), new BuildPropertyGroupProxy(new BuildPropertyGroup()), new BuildItemGroupProxy(new BuildItemGroup())); primaryLoggingServices.LogComment(currentContext, MessageImportance.Low, "ToolsVersionInEffectForBuild", buildRequest.ToolsetVersion); for (int i = 0; i < actuallyBuiltTargets.Count; i++) { string builtTargetName = EscapingUtilities.UnescapeAll((string)actuallyBuiltTargets[i]); Target.BuildState buildState = (Target.BuildState)cachedResult.ResultByTarget[builtTargetName]; buildRequest.ResultByTarget[builtTargetName] = buildState; primaryLoggingServices.LogComment(currentContext, ((buildState == Target.BuildState.CompletedSuccessfully) ? "TargetAlreadyCompleteSuccess" : "TargetAlreadyCompleteFailure"), builtTargetName); if (buildState == Target.BuildState.CompletedUnsuccessfully) { break; } } primaryLoggingServices.LogProjectFinished(currentContext, projectFileInfo.FullName, cachedResult.EvaluationResult); if (!buildRequest.IsGeneratedRequest) { CheckForBuildCompletion(); } else { Router.PostDoneNotice(buildRequest); } }
/// <summary> /// This method lets the engine provide node with results of an evaluation it was waiting on. /// </summary> internal void PostBuildResult(BuildResult buildResult) { ErrorUtilities.VerifyThrow(localEngine != null, "Local engine should be initialized"); // Figure out the local handle id NodeRequestMapping nodeRequestMapping = null; try { lock (requestToLocalIdMapping) { nodeRequestMapping = (NodeRequestMapping)requestToLocalIdMapping[buildResult.RequestId]; requestToLocalIdMapping.Remove(buildResult.RequestId); } if (Engine.debugMode) { Console.WriteLine(nodeId + ": Got result for Request Id " + buildResult.RequestId); Console.WriteLine(nodeId + ": Received result for HandleId " + buildResult.HandleId + ":" + buildResult.RequestId + " mapped to " + nodeRequestMapping.HandleId + ":" + nodeRequestMapping.RequestId); } buildResult.HandleId = nodeRequestMapping.HandleId; buildResult.RequestId = nodeRequestMapping.RequestId; nodeRequestMapping.AddResultToCache(buildResult); // posts the result to the inproc node localEngine.Router.PostDoneNotice(0, buildResult); } catch (Exception ex) { ReportUnhandledError(ex); } }
private static void CompareBuildResult(BuildResult result1, BuildResult result2) { Assert.AreEqual(result1.HandleId, result2.HandleId, "Expected HandleId to Match"); Assert.AreEqual(result1.RequestId, result2.RequestId, "Expected RequestId to Match"); Assert.AreEqual(result1.ProjectId, result2.ProjectId, "Expected ProjectId to Match"); Assert.AreEqual(result1.UseResultCache, result2.UseResultCache, "Expected UseResultCache to Match"); Assert.IsTrue(string.Compare(result1.InitialTargets, result2.InitialTargets, StringComparison.OrdinalIgnoreCase) == 0, "Expected InitialTargets to Match"); Assert.IsTrue(string.Compare(result1.DefaultTargets, result2.DefaultTargets, StringComparison.OrdinalIgnoreCase) == 0, "Expected DefaultTargets to Match"); }
public void TestUncacheableProperty() { BuildResult resultCacheable = new BuildResult(null, new Hashtable(StringComparer.OrdinalIgnoreCase), true, 0, 1, 2, false, string.Empty, string.Empty, 0, 0, 0); Assert.IsFalse(resultCacheable.UseResultCache, "Expected resultCacheable.UseResultCache to be false"); BuildResult resultUncacheable = new BuildResult(null, new Hashtable(StringComparer.OrdinalIgnoreCase), true, 0, 1, 2, true, string.Empty, string.Empty, 0, 0, 0); Assert.IsTrue(resultUncacheable.UseResultCache, "Expected resultUncacheable.UseResultCache to be true"); }
/// <summary> /// This method is used by the child node to post results of a build request back to the /// parent node. The parent node then decides if need to re-route the results to another node /// that requested the evaluation or if it will consume the result locally /// </summary> /// <param name="buildResult"></param> public void PostBuildResultToHost(BuildResult buildResult) { RequestRoutingContext routingContext = GetRoutingContextFromHandleId(buildResult.HandleId); ErrorUtilities.VerifyThrow(routingContext.CacheScope != null, "Cache scope should be created for this context"); // Cache the results routingContext.CacheScope.AddCacheEntryForBuildResults(buildResult); if (Engine.debugMode) { Console.WriteLine("Received result for HandleId " + buildResult.HandleId + ":" + buildResult.RequestId + " mapped to " + routingContext.ParentHandleId + ":" + routingContext.ParentRequestId); } // Update the results with the original handle id and request id, so that buildResult.HandleId = routingContext.ParentHandleId; // If the build result is created from a generated build request a done notice should be posted as other targets could be waiting for this target to finish if (buildResult.HandleId != invalidEngineHandle) { buildResult.RequestId = routingContext.ParentRequestId; parentEngine.Router.PostDoneNotice(routingContext.ParentNodeIndex, buildResult); } else // The build results need to be stored into the build request so they can be sent back to the host that requested the build { routingContext.TriggeringBuildRequest.OutputsByTarget = buildResult.OutputsByTarget; routingContext.TriggeringBuildRequest.BuildSucceeded = buildResult.EvaluationResult; routingContext.TriggeringBuildRequest.BuildCompleted = true; parentEngine.PostEngineCommand(new HostBuildRequestCompletionEngineCommand()); } // At this point the execution context we created for the execution of this build request can be deleted lock (freedContexts) { freedContexts.Add(routingContext); } }
internal LocalCallDescriptorForPostBuildResult(BuildResult buildResult) : base(LocalCallType.PostBuildResult) { this.buildResult = buildResult; }
internal virtual ReferenceNode CreateReferenceNode(string referenceType, ProjectElement element, BuildResult buildResult) { ReferenceNode node = null; if (referenceType == ProjectFileConstants.COMReference) { node = this.CreateComReferenceNode(element); } else if (referenceType == ProjectFileConstants.Reference) { node = this.CreateAssemblyReferenceNode(element, buildResult); } else if (referenceType == ProjectFileConstants.ProjectReference) { node = this.CreateProjectReferenceNode(element); EnableCachingForProjectReferencesInBatchUpdate(node); } return node; }
internal void AddResultToCache(BuildResult buildResult) { resultsCache.AddCacheEntryForBuildResults(buildResult); }
internal static BuildResult CreateFromStream(BinaryReader reader) { BuildResult buildResult = new BuildResult(); #region OutputsByTarget if (reader.ReadByte() == 0) { buildResult.outputsByTarget = null; } else { int numberOfElements = reader.ReadInt32(); buildResult.outputsByTarget = new Hashtable(numberOfElements, StringComparer.OrdinalIgnoreCase); for (int i = 0; i < numberOfElements; i++) { string key = reader.ReadString(); BuildItem[] value = null; if (reader.ReadByte() != 0) { int sizeOfArray = reader.ReadInt32(); value = new BuildItem[sizeOfArray]; for (int j = 0; j < sizeOfArray; j++) { BuildItem itemToAdd = null; if (reader.ReadByte() != 0) { itemToAdd = new BuildItem(null, string.Empty); itemToAdd.CreateFromStream(reader); } value[j] = itemToAdd; } } buildResult.outputsByTarget.Add(key, value); } } #endregion #region ResultsByTarget //Write Number of HashItems int numberOfHashKeyValuePairs = reader.ReadInt32(); buildResult.resultByTarget = new Hashtable(numberOfHashKeyValuePairs, StringComparer.OrdinalIgnoreCase); for (int i = 0; i < numberOfHashKeyValuePairs; i++) { string key = reader.ReadString(); int value = reader.ReadInt32(); buildResult.resultByTarget.Add(key, (Target.BuildState)value); } #endregion buildResult.flags = reader.ReadByte(); buildResult.handleId = reader.ReadInt32(); buildResult.requestId = reader.ReadInt32(); buildResult.projectId = reader.ReadInt32(); #region DefaultTargets if (reader.ReadByte() == 0) { buildResult.defaultTargets = null; } else { buildResult.defaultTargets = reader.ReadString(); } #endregion #region InitialTargets if (reader.ReadByte() == 0) { buildResult.initialTargets = null; } else { buildResult.initialTargets = reader.ReadString(); } #endregion #region Timing data buildResult.totalTime = reader.ReadInt32(); buildResult.engineTime = reader.ReadInt32(); buildResult.taskTime = reader.ReadInt32(); #endregion return buildResult; }
/// <summary> /// Initialize this build request with a cached build result /// </summary> /// <param name="cachedResult"></param> internal void InitializeFromCachedResult(BuildResult cachedResult) { this.OutputsByTarget = cachedResult.OutputsByTarget; this.BuildSucceeded = cachedResult.EvaluationResult; this.BuildCompleted = true; this.DefaultTargets = cachedResult.DefaultTargets; this.InitialTargets = cachedResult.InitialTargets; this.projectId = cachedResult.ProjectId; this.restoredFromCache = true; }
/// <summary> /// This method adds cached results for each target results for which are contained inside /// the build result. This method is thread safe. /// </summary> internal void AddCacheEntryForBuildResults(BuildResult buildResult) { ErrorUtilities.VerifyThrow(buildResult != null, "Expect a non-null build result"); // Don't cache results if they are marked as uncacheable if (!buildResult.UseResultCache) { return; } cacheScopeReaderWriterLock.AcquireWriterLock(Timeout.Infinite); try { if (!ContainsCacheEntry(Constants.defaultTargetCacheName)) { // If the project file is malformed the build may fail without initializing the initialtargets or // the default targests fields. The retrieval code expects non-null values // so it is necessary to replace null with empty string ErrorUtilities.VerifyThrow(buildResult.EvaluationResult == false || buildResult.InitialTargets != null && buildResult.DefaultTargets != null, "Expect initial targets to be non-null for successful builds"); string defaultTargets = buildResult.DefaultTargets == null ? String.Empty : buildResult.DefaultTargets; PropertyCacheEntry defaultTargetsCacheEntry = new PropertyCacheEntry(Constants.defaultTargetCacheName, defaultTargets); AddCacheEntryInternal(defaultTargetsCacheEntry); string initialTargets = buildResult.InitialTargets == null ? String.Empty : buildResult.InitialTargets; PropertyCacheEntry initialTargetsCacheEntry = new PropertyCacheEntry(Constants.initialTargetCacheName, initialTargets); AddCacheEntryInternal(initialTargetsCacheEntry); } if (!ContainsCacheEntry(Constants.projectIdCacheName)) { PropertyCacheEntry projectIdCacheEntry = new PropertyCacheEntry(Constants.projectIdCacheName, buildResult.ProjectId.ToString(CultureInfo.InvariantCulture)); AddCacheEntryInternal(projectIdCacheEntry); } IDictionary outputsByTargetName = buildResult.OutputsByTarget; //Create single entry for each target in the request foreach (DictionaryEntry entry in buildResult.ResultByTarget) { Target.BuildState buildState = (Target.BuildState)entry.Value; // Only cache successful and failed targets if ((buildState == Target.BuildState.CompletedSuccessfully) || (buildState == Target.BuildState.CompletedUnsuccessfully)) { BuildItem[] targetOutputs = null; // Only cache output items for successful targets if (buildState == Target.BuildState.CompletedSuccessfully) { ErrorUtilities.VerifyThrow(buildResult.OutputsByTarget.Contains(entry.Key), "We must have build results for successful targets"); BuildItem[] outputItems = (BuildItem[])buildResult.OutputsByTarget[entry.Key]; // It's essential that we clear out any pointers to the project from the BuildItem; // otherwise the cache will hold onto the project, and not save any memory. if (outputItems != null) { for (int i = 0; i < outputItems.Length; i++) { outputItems[i] = outputItems[i].VirtualClone(true /* remove references to minimise transitive size */); } } targetOutputs = (BuildItem[])buildResult.OutputsByTarget[entry.Key]; } BuildResultCacheEntry cacheEntry = new BuildResultCacheEntry((string)entry.Key, targetOutputs, (buildState == Target.BuildState.CompletedSuccessfully)); if (Engine.debugMode) { Console.WriteLine("+++Adding cache entry for " + (string)entry.Key + " in " + this.ScopeName + " result: " + (buildState == Target.BuildState.CompletedSuccessfully)); } AddCacheEntryInternal(cacheEntry); } } } finally { cacheScopeReaderWriterLock.ReleaseWriterLock(); } }
public virtual void Refresh() { // Let MSBuild know which configuration we are working with project.SetConfiguration(projectCfg.ConfigCanonicalName); var result = new BuildResult(MSBuildResult.Failed, null); if (project.ProjectMgr.BuildProject.Targets.ContainsKey(ProjectFileConstants.AllProjectOutputGroups)) { result = project.InvokeMsBuild(ProjectFileConstants.AllProjectOutputGroups, false /*isBeingCalledByComputeSourcesAndFlags*/); if (!result.IsSuccessful) { // we could not compute it, probably because there is a real build going on right now project.SetCurrentConfiguration(); return; } } // Rebuild the content of our list of output string outputType = this.targetName + "Output"; this.outputs.Clear(); foreach (Microsoft.Build.Execution.ProjectItemInstance assembly in result.ProjectInstance.GetItems(outputType)) { Output output = new Output(project, assembly); this.outputs.Add(output); // See if it is our key output if (String.Compare(MSBuildItem.GetMetadataValue(assembly, "IsKeyOutput"), true.ToString(), StringComparison.OrdinalIgnoreCase) == 0) keyOutput = output; } project.SetCurrentConfiguration(); // Now that the group is built we have to check if it is invalidated by a property // change on the project. project.OnProjectPropertyChanged += new EventHandler<ProjectPropertyChangedArgs>(OnProjectPropertyChanged); }
protected override BuildResult OnBuild (IProgressMonitor monitor, ConfigurationSelector configuration) { DotNetProject project = Project; bool hasBuildableFiles = false; foreach (ProjectFile pf in project.Files) { if (pf.BuildAction == BuildAction.Compile || pf.BuildAction == BuildAction.EmbeddedResource) { hasBuildableFiles = true; break; } } if (!hasBuildableFiles) return new BuildResult (); if (project.LanguageBinding == null) { BuildResult langres = new BuildResult (); string msg = GettextCatalog.GetString ("Unknown language '{0}'. You may need to install an additional add-in to support this language.", project.LanguageName); langres.AddError (msg); monitor.ReportError (msg, null); return langres; } BuildResult refres = null; HashSet<ProjectItem> itemsToExclude = new HashSet<ProjectItem> (); foreach (ProjectReference pr in project.References) { if (pr.ReferenceType == ReferenceType.Project) { // Ignore non-dotnet projects Project p = project.ParentSolution != null ? project.ParentSolution.FindProjectByName (pr.Reference) : null; if (p != null && !(p is DotNetProject)) continue; if (p == null || pr.GetReferencedFileNames (configuration).Length == 0) { if (refres == null) refres = new BuildResult (); string msg = GettextCatalog.GetString ("Referenced project '{0}' not found in the solution.", pr.Reference); monitor.ReportWarning (msg); refres.AddWarning (msg); } } if (!pr.IsValid) { if (refres == null) refres = new BuildResult (); string msg; if (!pr.IsExactVersion && pr.SpecificVersion) { msg = GettextCatalog.GetString ("Reference '{0}' not found on system. Using '{1}' instead.", pr.StoredReference, pr.Reference); monitor.ReportWarning (msg); refres.AddWarning (msg); } else { bool errorsFound = false; foreach (string asm in pr.GetReferencedFileNames (configuration)) { if (!File.Exists (asm)) { msg = GettextCatalog.GetString ("Assembly '{0}' not found. Make sure that the assembly exists in disk. If the reference is required to build the project you may get compilation errors.", Path.GetFileName (asm)); refres.AddWarning (msg); monitor.ReportWarning (msg); errorsFound = true; itemsToExclude.Add (pr); } } msg = null; if (!errorsFound) { msg = GettextCatalog.GetString ("The reference '{0}' is not valid for the target framework of the project.", pr.StoredReference, pr.Reference); monitor.ReportWarning (msg); refres.AddWarning (msg); itemsToExclude.Add (pr); } } } } DotNetProjectConfiguration conf = (DotNetProjectConfiguration) project.GetConfiguration (configuration); // Create a copy of the data needed to compile the project. // This data can be modified by extensions. // Also filter out items whose condition evaluates to false BuildData buildData = new BuildData (); ProjectParserContext ctx = new ProjectParserContext (project, conf); buildData.Items = new ProjectItemCollection (); foreach (ProjectItem item in project.Items) { if (!itemsToExclude.Contains (item) && (string.IsNullOrEmpty (item.Condition) || ConditionParser.ParseAndEvaluate (item.Condition, ctx))) buildData.Items.Add (item); } buildData.Configuration = (DotNetProjectConfiguration) conf.Clone (); buildData.Configuration.SetParentItem (project); buildData.ConfigurationSelector = configuration; return ProjectExtensionUtil.Compile (monitor, project, buildData, delegate { ProjectItemCollection items = buildData.Items; BuildResult res = BuildResources (buildData.Configuration, ref items, monitor); if (res != null) return res; res = project.LanguageBinding.Compile (items, buildData.Configuration, buildData.ConfigurationSelector, monitor); if (refres != null) { refres.Append (res); return refres; } else return res; }); }
/// <summary> /// Creates an assembly refernce node from a project element. /// </summary> internal virtual AssemblyReferenceNode CreateAssemblyReferenceNode(ProjectElement element, BuildResult buildResult) { AssemblyReferenceNode node = null; try { node = AssemblyReferenceNode.CreateFromProjectFile(this.ProjectMgr, element, buildResult); } catch (ArgumentNullException e) { Trace.WriteLine("Exception : " + e.Message); } catch (FileNotFoundException e) { Trace.WriteLine("Exception : " + e.Message); } catch (BadImageFormatException e) { Trace.WriteLine("Exception : " + e.Message); } catch (FileLoadException e) { Trace.WriteLine("Exception : " + e.Message); } catch (System.Security.SecurityException e) { Trace.WriteLine("Exception : " + e.Message); } return node; }
internal override void CreateFromStream(BinaryReader reader) { base.CreateFromStream(reader); buildResult = BuildResult.CreateFromStream(reader); }
private static BuildResult CreateBuildResult() { BuildItem buildItem1 = new BuildItem(null, "Item1"); BuildItem buildItem2 = new BuildItem("BuildItem2", "Item2"); BuildItem buildItem3 = BuildItem_Tests.GetXmlBackedItemWithDefinitionLibrary(); // default metadata m=m1 and o=o1 buildItem1.Include = "TestInclude1"; buildItem2.Include = "TestInclude2"; buildItem1.SetMetadata("m", "m1"); buildItem1.SetMetadata("n", "n1"); buildItem3.SetMetadata("n", "n1"); buildItem3.SetMetadata("o", "o2"); BuildItem[] taskItems = new BuildItem[3]; taskItems[0] = buildItem1; taskItems[1] = buildItem2; taskItems[2] = buildItem3; Dictionary<object, object> dictionary = new Dictionary<object, object>(); dictionary.Add("TaskItems", taskItems); BuildResult resultWithOutputs = new BuildResult(dictionary, new Hashtable(StringComparer.OrdinalIgnoreCase), true, 0, 1, 2, true, "Foo", "Fighter", 1, 2, 3); resultWithOutputs.ResultByTarget.Add("ONE", Target.BuildState.CompletedSuccessfully); resultWithOutputs.HandleId = 0; resultWithOutputs.RequestId = 1; return resultWithOutputs; }
public void TestNullParameterInConstructor() { BuildResult shouldFail = new BuildResult(null, false /* shallow copy */); }
/// <summary> /// This function implements the callback via the IBuildEngine interface /// </summary> /// <returns>result of call to engine</returns> virtual internal bool BuildProjectFile ( int handleId, string[] projectFileNames, string[] targetNames, IDictionary[] globalPropertiesPerProject, IDictionary[] targetOutputsPerProject, EngineLoggingServices loggingServices, string [] toolsVersions, bool useResultsCache, bool unloadProjectsOnCompletion, BuildEventContext taskContext ) { if (projectFileNames.Length == 0) { // Nothing to do, just return success return true; } string currentDir = FileUtilities.GetCurrentDirectoryStaticBuffer(currentDirectoryBuffer); if (Engine.debugMode) { string targetName = targetNames == null ? "null" : targetNames[0]; bool remoteNode = false; for (int r = 0; r < projectFileNames.Length; r++) { string fullProjectName = projectFileNames[r] != null ? projectFileNames[r] : "null"; Console.WriteLine("RemoteNode: " + remoteNode + " Project " + fullProjectName + " T:" + targetName + " NodeProdyId# " + handleId + " Time " + DateTime.Now.ToLongTimeString()); if (globalPropertiesPerProject[r] != null) { foreach (DictionaryEntry entry in globalPropertiesPerProject[r]) { Console.WriteLine(currentDir + " :GLOBAL " + entry.Key + "=" + entry.Value.ToString()); } } } } BuildRequest[] buildRequests = new BuildRequest[projectFileNames.Length]; for (int i = 0; i < buildRequests.Length; i++) { // We need to get the full path to the project before we call back // into the engine which has no control over current path string fullProjectName = projectFileNames[i] != null ? Path.GetFullPath(projectFileNames[i]) : null; buildRequests[i] = new BuildRequest(handleId, fullProjectName, targetNames, globalPropertiesPerProject[i], toolsVersions[i], i, useResultsCache, unloadProjectsOnCompletion); ErrorUtilities.VerifyThrow(buildRequests[i].IsGeneratedRequest == true, "Should not be sending non generated requests from TEM to engine"); buildRequests[i].ParentBuildEventContext = taskContext; } BuildResult[] buildResultsLocal = new BuildResult[projectFileNames.Length]; if (moduleMode == TaskExecutionModuleMode.SingleProcMode) { for (int i = 0; i < projectFileNames.Length; i++) { // If we are running in a single threaded mode we need to // re-enter the main build loop on the current thread in order // to build the requested project, because the main build is below // us on the stack engineCallback.PostBuildRequestsToHost(new BuildRequest[] { buildRequests[i] }); buildResultsLocal[i] = engineCallback.GetParentEngine().EngineBuildLoop(buildRequests[i]); buildResultsLocal[i].ConvertToTaskItems(); } } else { WaitForBuildResults(handleId, buildResultsLocal, buildRequests); } // Store the outputs in the hashtables provided by the caller bool overallResult = true; for (int i = 0; i < buildResultsLocal.Length; i++) { // Users of the Object Model can pass in null targetOutputs for projects they do not want outputs for // therefore we need to make sure that there are targetoutputs and the users want the results if (buildResultsLocal[i] != null) { if (buildResultsLocal[i].OutputsByTarget != null && targetOutputsPerProject[i] != null) { foreach (DictionaryEntry entry in buildResultsLocal[i].OutputsByTarget) { targetOutputsPerProject[i].Add(entry.Key, entry.Value); } overallResult = overallResult && buildResultsLocal[i].EvaluationResult; } } else { // The calculation was terminated prior to receiving the result overallResult = false; } } // We're now returning from an IBuildEngine callback; // set the current directory back to what the tasks expect if (Directory.GetCurrentDirectory() != currentDir) { Directory.SetCurrentDirectory(currentDir); } if (Engine.debugMode) { bool remoteNode = false; string targetName = targetNames == null ? "null" : targetNames[0]; Console.WriteLine("RemoteNode: " + remoteNode + " T:" + targetName + " HandleId# " + handleId + " Result " + overallResult); } return overallResult; }
public void CustomSerialization() { MemoryStream stream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stream); BinaryReader reader = new BinaryReader(stream); try { stream.Position = 0; BuildResult result1 = new BuildResult(resultWithOutputs, false /* shallow copy */); result1.HandleId = 2; result1.RequestId = 3; result1.WriteToStream(writer); BuildResult result2 = new BuildResult(resultWithOutputs, true /* deep copy */); result2.HandleId = 2; result2.RequestId = 3; result2.WriteToStream(writer); BuildResult result3 = new BuildResult(null, new Hashtable(StringComparer.OrdinalIgnoreCase), true, 0, 1, 2, true, null, null, 0, 0, 0); result3.HandleId = 2; result3.RequestId = 3; result3.WriteToStream(writer); BuildResult result4 = new BuildResult(null, new Hashtable(StringComparer.OrdinalIgnoreCase), true, 0, 1, 2, true, "DefaultTarget", "InitialTarget", 0, 0, 0); result4.HandleId = 2; result4.RequestId = 3; result4.ResultByTarget.Add("ONE", Target.BuildState.CompletedSuccessfully); result4.WriteToStream(writer); long streamWriteEndPosition = stream.Position; stream.Position = 0; BuildResult result5 = BuildResult.CreateFromStream(reader); BuildResult result6 = BuildResult.CreateFromStream(reader); BuildResult result7 = BuildResult.CreateFromStream(reader); BuildResult result8 = BuildResult.CreateFromStream(reader); long streamReadEndPosition = stream.Position; Assert.IsTrue(streamWriteEndPosition == streamReadEndPosition, "Stream end positions should be equal"); CompareBuildResult(result1, result5); CompareBuildResult(result2, result6); CompareBuildResult(result3, result7); CompareBuildResult(result4, result8); Assert.IsTrue(result8.ResultByTarget.Count == 1); Assert.IsTrue(((Target.BuildState)result8.ResultByTarget["ONE"]) == Target.BuildState.CompletedSuccessfully); BuildItem[] buildItemArray = ((BuildItem[])result1.OutputsByTarget["TaskItems"]); Assert.IsTrue(buildItemArray.Length == 2); Assert.IsTrue(string.Compare(buildItemArray[0].Include, buildItem1.Include, StringComparison.OrdinalIgnoreCase)==0); Assert.IsTrue(string.Compare(buildItemArray[1].Include, buildItem2.Include, StringComparison.OrdinalIgnoreCase) == 0); Assert.IsTrue(string.Compare(buildItemArray[1].Name, buildItem2.Name, StringComparison.OrdinalIgnoreCase) == 0); } finally { reader.Close(); writer = null; stream = null; } }
/// <summary> /// Once the buildRequests from the EngineCallback have been created they are sent to this method which will /// post the build requests to the parent engine and then wait on the results to come back. /// This method uses either a breadthFirst or depthFirst traversal strategy when sending buildRequests to the parent engine. /// This method will start in breadthFirst traversal. It will continue to use this strategy until one of two events occur: /// 1. The parent node sents a message indicating the TEM should switch to depthFirst traversal. /// 2. The number of buildRequests is larger than the batchRequestSize. /// In both of these cases the system will go from a breadthFirstTraversal to a depthFirst Traversal. In the second case /// a message will be sent to the parent engine to switch the system to depthFirst traversal as the system is starting to /// be overloaded with work. /// In a depth first strategy the buildRequests will be sent to the parent engine one at a time and waiting for results for /// each buildRequest sent. In a breadthFirst traversal strategy some number of the buildrequests will be sent to the parent engine /// in a batch of requests. The system will then wait on the results of ALL the build requests sent before continuing /// to send more build requests. /// </summary> private void WaitForBuildResults(int handleId, BuildResult[] buildResultsLocal, BuildRequest[] buildRequests) { // If the traversal strategy is breadth first and the number of requests is less than the batchRequestSize // or if there is only 1 build request then send ALL build requests to the parent engine and wait on the results. if ((breadthFirstTraversal == true && buildRequests.Length < batchRequestSize) || buildRequests.Length == 1) { engineCallback.PostBuildRequestsToHost(buildRequests); workerThread.WaitForResults(handleId, buildResultsLocal, buildRequests); } else { int currentRequestIndex = 0; // Which build request is being processed int numberOfRequestsToSend = 0; // How many buildRequests are going to be sent based on the number of buildRequests remaining and the build request batch size. // Arrays that will be used to partion the buildRequests array when sending batches of builds requests at a time. BuildRequest[] wrapperArrayBreadthFirst = new BuildRequest[batchRequestSize]; BuildResult[] resultsArrayBreadthFirst = new BuildResult[batchRequestSize]; // Pre allocate these arrays as they will always be only one element in size. They are assigned to and filled when doing a depth first traversal. BuildRequest[] wrapperArrayDepthFirst = new BuildRequest[1]; BuildResult[] resultsArrayDepthFirst = new BuildResult[1]; // While there are still requests to send while (currentRequestIndex < buildRequests.Length) { // If there is a breadth first traversal and there are more than batchRequestSize build requests, send the first batchRequestSize, then do the rest depth first if (breadthFirstTraversal == true) { // Figure out how many requests to send, either the full batch size or only part of a batch numberOfRequestsToSend = (buildRequests.Length - currentRequestIndex) <batchRequestSize ? (buildRequests.Length - currentRequestIndex) : batchRequestSize; // Initialize the wrapper array to how many requests are going to be sent if (numberOfRequestsToSend != wrapperArrayBreadthFirst.Length) { wrapperArrayBreadthFirst = new BuildRequest[numberOfRequestsToSend]; resultsArrayBreadthFirst = new BuildResult[numberOfRequestsToSend]; } // Fill the wrapper array with one batch of build requests for (int i = 0; i < numberOfRequestsToSend; i++) { wrapperArrayBreadthFirst[i] = buildRequests[currentRequestIndex + i]; wrapperArrayBreadthFirst[i].RequestId = i; resultsArrayBreadthFirst[i] = null; } engineCallback.PostBuildRequestsToHost(wrapperArrayBreadthFirst); // Only switch from breadth to depth if there are more thanbatchRequestSize items if ((buildRequests.Length - currentRequestIndex) > batchRequestSize) { engineCallback.PostStatus(nodeId, new NodeStatus(false /* use depth first traversal*/), false /* don't block waiting on the send */); breadthFirstTraversal = false; } workerThread.WaitForResults(handleId, resultsArrayBreadthFirst, wrapperArrayBreadthFirst); Array.Copy(resultsArrayBreadthFirst, 0, buildResultsLocal, currentRequestIndex, numberOfRequestsToSend); currentRequestIndex += numberOfRequestsToSend; } // Proceed with depth first traversal while ((currentRequestIndex < buildRequests.Length) && !breadthFirstTraversal) { wrapperArrayDepthFirst[0] = buildRequests[currentRequestIndex]; buildRequests[currentRequestIndex].RequestId = 0; resultsArrayDepthFirst[0] = null; engineCallback.PostBuildRequestsToHost(wrapperArrayDepthFirst); workerThread.WaitForResults(handleId, resultsArrayDepthFirst, wrapperArrayDepthFirst); //Copy the result from an intermediate array to the full array buildResultsLocal[currentRequestIndex] = resultsArrayDepthFirst[0]; //Check if the call failed (null result was returned) if (buildResultsLocal[currentRequestIndex] == null) { return; } //Move to the next request currentRequestIndex++; } } } }
/// <summary> /// This method lets the engine provide node with results of an evaluation it was waiting on. /// </summary> /// <param name="buildResult"></param> internal void PostBuildResults(BuildResult buildResult) { // Do nothing in the single proc mode if (moduleMode == TaskExecutionModuleMode.SingleProcMode) { return; } buildResult.ConvertToTaskItems(); workerThread.PostBuildResult(buildResult); }
private void BuildCoda(BuildResult result, IVsOutputWindowPane output, bool shouldRepaintReferences) { try { // Now repaint references if that is needed. // We hardly rely here on the fact the ResolveAssemblyReferences target has been run as part of the build. // One scenario to think at is when an assembly reference is renamed on disk thus becomming unresolvable, // but msbuild can actually resolve it. // Another one if the project was opened only for browsing and now the user chooses to build or rebuild. if (shouldRepaintReferences && (result.IsSuccessful)) { this.RefreshReferences(result); } } finally { try { ErrorHandler.ThrowOnFailure(output.FlushToTaskList()); } finally { NotifyBuildEnd(result.IsSuccessful); } } }
void INodeProvider.PostBuildResultToNode(int nodeIndex, BuildResult buildResultToPost) { if (nodeIndex > nodeDescriptions.Count) { throw new ArgumentException("Node index is out of range"); } buildResultsSubmittedToProvider.Add(buildResultToPost); }
/// <summary> /// This method posts outputs of a build to the node that made the request /// </summary> /// <param name="buildResult"></param> internal void PostBuildResultToHost(BuildResult buildResult) { try { outProcLoggingService.ProcessPostedLoggingEvents(); parentCallback.PostBuildResultToHost(buildResult); } catch (Exception e) { ReportUnhandledError(e); } }
/// <summary> /// Post a build result to a node, the node index is an index into the list of nodes provided by all node providers /// registered to the node manager, the 0 in index is a local call to taskexecutionmodule /// </summary> /// <param name="nodeIndex"></param> /// <param name="buildResult"></param> internal void PostBuildResultToNode(int nodeIndex, BuildResult buildResult) { ErrorUtilities.VerifyThrow(nodeIndex <= nodeList.Count, "Should not pass a node index higher then the number of nodes in nodeManager"); if (nodeIndex != 0) { nodeList[nodeIndex-1].NodeProvider.PostBuildResultToNode(nodeList[nodeIndex-1].NodeIndex, buildResult); } else { taskExecutionModule.PostBuildResults(buildResult); } }
/// <summary> /// Refreshes references and redraws them correctly. /// </summary> private void RefreshReferences(BuildResult buildResult) { // Refresh the reference container node for assemblies that could be resolved. IReferenceContainer referenceContainer = this.config.ProjectMgr.GetReferenceContainer(); foreach (ReferenceNode referenceNode in referenceContainer.EnumReferences()) { referenceNode.RefreshReference(buildResult); } }
/// <summary> /// This is the loop for all active threads. Depending on the current execution mode the thread /// will listen to different events. There is only one thread at the time that owns the workitem /// queue and listens for tasks to be executed. There is also only one thread at a time that is /// execution a task. That thread owns the current directory and the environment block. /// </summary> /// <param name="executionMode"></param> /// <param name="nodeProxyId"></param> /// <param name="requestResults"></param> private void NodeActionLoop(NodeLoopExecutionMode executionMode, int nodeProxyId, BuildResult [] requestResults) { // Create an array of event to the node thread responds WaitHandle[] waitHandles = GetHandlesArray(executionMode); int resultCount = 0; // A thread that is waiting for a done notification is no longer // actively executing a task so the active cound needs to be decreased if (executionMode != NodeLoopExecutionMode.BaseActiveThread) { Interlocked.Decrement(ref activeThreadCount); threadCountEvent.Set(); } bool continueExecution = true; while (continueExecution) { int eventType = WaitHandle.WaitAny(waitHandles); if (Environment.GetEnvironmentVariable("MSBUILDDEBUG") == "1") { Console.WriteLine("NodeProxy :" + nodeProxyId + " waking up due " + eventType); } // Node exit event - all threads need to exit if (eventType == 0) { continueExecution = false; } // New work item has appeared in the queue else if (eventType == 1 && executionMode != NodeLoopExecutionMode.WaitingPassiveThread) { ErrorUtilities.VerifyThrow( executionMode == NodeLoopExecutionMode.WaitingActiveThread || executionMode == NodeLoopExecutionMode.BaseActiveThread, "Only active threads should receive work item events"); if (executionMode == NodeLoopExecutionMode.BaseActiveThread) { TaskExecutionState taskToExecute = null; lock (workItemQueue) { taskToExecute = workItemQueue.Dequeue(); // We may get a single event for multiple messages so only reset the event // if the queue is empty if (workItemQueue.Count == 0) { workItemInsertionEvent.Reset(); } } // Execute the task either directly or on a child thread ErrorUtilities.VerifyThrow(taskToExecute != null, "Expected a workitem"); // Wait until all there are no other active threads, we // always transition from 0 to 1 atomically before executing the task while (Interlocked.CompareExchange(ref activeThreadCount, 1, 0) != 0) { threadCountEvent.WaitOne(); threadCountEvent.Reset(); } proxyIdToWorkerThread[taskToExecute.NodeProxyId] = this; // Actually execute the task taskToExecute.ExecuteTask(); proxyIdToWorkerThread.Remove(taskToExecute.NodeProxyId); // Indicate that this thread is no longer active Interlocked.Decrement(ref activeThreadCount); threadCountEvent.Set(); } else { // Change the thread execution mode since it will no longer be // listening to the work item queue executionMode = NodeLoopExecutionMode.WaitingPassiveThread; threadActive = false; waitHandles = GetHandlesArray(executionMode); TaskWorkerThread workerThread = null; lock (workerThreadQueue) { if (workerThreadQueue.Count != 0) { //Console.WriteLine("REUSING a thread"); workerThread = workerThreadQueue.Dequeue(); } } if (workerThread == null) { //Console.WriteLine("CREATING a thread"); workerThread = new TaskWorkerThread(); } workerThread.ActivateThread(); } } else if (eventType == 1 && executionMode == NodeLoopExecutionMode.WaitingPassiveThread || eventType == 2 && executionMode == NodeLoopExecutionMode.WaitingActiveThread) { // There maybe multiple results in the list so we need to loop over it // and store the results int originalResultCount = resultCount; lock (targetEvaluationResults) { //Console.WriteLine("Worker thread for: " + nodeProxyId + " Got results"); LinkedListNode <BuildResult> currentNode = targetEvaluationResults.First; while (currentNode != null) { BuildResult buildResult = currentNode.Value; ErrorUtilities.VerifyThrow( buildResult.RequestId < requestResults.Length, "The request ids should be inside the array"); requestResults[buildResult.RequestId] = buildResult; // Increment the result count to indicate that we got another result resultCount++; // Go to the next entry in the list (most of the time there will be just one entry) currentNode = currentNode.Next; } targetEvaluationResults.Clear(); // Reset the handle now that we done with the events int handleIndex = executionMode == NodeLoopExecutionMode.WaitingPassiveThread ? 1 : 2; ((ManualResetEvent)waitHandles[handleIndex]).Reset(); } ErrorUtilities.VerifyThrow(originalResultCount < resultCount, "We should have found at least 1 result"); // If we received results for all the requests we need to exit if (resultCount == requestResults.Length) { continueExecution = false; } } // Check if we need to update the state if (executionMode == NodeLoopExecutionMode.BaseActiveThread && !threadActive) { continueExecution = false; } } ErrorUtilities.VerifyThrow (resultCount == 0 || executionMode != NodeLoopExecutionMode.BaseActiveThread, "The base thread should never return a value"); // If a thread exits this loop it is back to actively executing the task, // so the active thread count has to be increased if (executionMode != NodeLoopExecutionMode.BaseActiveThread) { while (Interlocked.CompareExchange(ref activeThreadCount, 1, 0) != 0) { threadCountEvent.WaitOne(); threadCountEvent.Reset(); } } }