diff --git a/Public/Src/FrontEnd/MsBuild.Serialization/ProjectGraphWithPredictionsResult.cs b/Public/Src/FrontEnd/MsBuild.Serialization/ProjectGraphWithPredictionsResult.cs index 685a640c9a..9136b9092d 100644 --- a/Public/Src/FrontEnd/MsBuild.Serialization/ProjectGraphWithPredictionsResult.cs +++ b/Public/Src/FrontEnd/MsBuild.Serialization/ProjectGraphWithPredictionsResult.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; using System.Collections.Generic; using System.Diagnostics.ContractsLight; using Newtonsoft.Json; @@ -48,12 +49,17 @@ public readonly struct ProjectGraphWithPredictionsResult /// public bool Succeeded { get; } + /// + /// A list of the names of environment variables that could affect the build. + /// + public IEnumerable EnvironmentVariablesAffectingBuild { get; } + /// - public static ProjectGraphWithPredictionsResult CreateSuccessfulGraph(ProjectGraphWithPredictions projectGraphWithPredictions, IReadOnlyDictionary assemblyPathsToLoad, TPathType pathToMsBuild) + public static ProjectGraphWithPredictionsResult CreateSuccessfulGraph(ProjectGraphWithPredictions projectGraphWithPredictions, IReadOnlyDictionary assemblyPathsToLoad, TPathType pathToMsBuild, IEnumerable environmentVariablesAffectingBuild) { Contract.Requires(projectGraphWithPredictions != null); Contract.Requires(assemblyPathsToLoad != null); - return new ProjectGraphWithPredictionsResult(projectGraphWithPredictions, failure: default, msBuildAssemblyPaths: assemblyPathsToLoad, pathToMsBuild: pathToMsBuild, pathToDotNetExe: default(TPathType), succeeded: true); + return new ProjectGraphWithPredictionsResult(projectGraphWithPredictions, failure: default, msBuildAssemblyPaths: assemblyPathsToLoad, pathToMsBuild: pathToMsBuild, pathToDotNetExe: default(TPathType), succeeded: true, environmentVariablesAffectingBuild); } /// @@ -61,7 +67,7 @@ public static ProjectGraphWithPredictionsResult CreateFailure(GraphCo { Contract.Requires(failure != null); Contract.Requires(assemblyPathsToLoad != null); - return new ProjectGraphWithPredictionsResult(default, failure, assemblyPathsToLoad, pathToMsBuild, pathToDotNetExe: default(TPathType), succeeded: false); + return new ProjectGraphWithPredictionsResult(default, failure, assemblyPathsToLoad, pathToMsBuild, pathToDotNetExe: default(TPathType), succeeded: false, environmentVariablesAffectingBuild: null); } /// @@ -69,11 +75,11 @@ public static ProjectGraphWithPredictionsResult CreateFailure(GraphCo /// public ProjectGraphWithPredictionsResult WithPathToDotNetExe(TPathType pathToDotNetExe) { - return new ProjectGraphWithPredictionsResult(Result, Failure, MsBuildAssemblyPaths, PathToMsBuild, pathToDotNetExe, Succeeded); + return new ProjectGraphWithPredictionsResult(Result, Failure, MsBuildAssemblyPaths, PathToMsBuild, pathToDotNetExe, Succeeded, EnvironmentVariablesAffectingBuild); } [JsonConstructor] - private ProjectGraphWithPredictionsResult(ProjectGraphWithPredictions result, GraphConstructionError failure, IReadOnlyDictionary msBuildAssemblyPaths, TPathType pathToMsBuild, TPathType pathToDotNetExe, bool succeeded) + private ProjectGraphWithPredictionsResult(ProjectGraphWithPredictions result, GraphConstructionError failure, IReadOnlyDictionary msBuildAssemblyPaths, TPathType pathToMsBuild, TPathType pathToDotNetExe, bool succeeded, IEnumerable environmentVariablesAffectingBuild) { Result = result; Failure = failure; @@ -81,6 +87,7 @@ private ProjectGraphWithPredictionsResult(ProjectGraphWithPredictions PathToMsBuild = pathToMsBuild; PathToDotNetExe = pathToDotNetExe; MsBuildAssemblyPaths = msBuildAssemblyPaths; + EnvironmentVariablesAffectingBuild = environmentVariablesAffectingBuild; } } } diff --git a/Public/Src/FrontEnd/MsBuild/MsBuildResolver.cs b/Public/Src/FrontEnd/MsBuild/MsBuildResolver.cs index faae1489b3..f0f81edaca 100644 --- a/Public/Src/FrontEnd/MsBuild/MsBuildResolver.cs +++ b/Public/Src/FrontEnd/MsBuild/MsBuildResolver.cs @@ -156,6 +156,16 @@ private Task EvaluateAllFilesAsync(IReadOnlySet evaluationGo .Where(project => ProjectMatchesQualifier(project, qualifier)) .ToReadOnlySet(); + IEnumerable> pipEnvironment = m_msBuildWorkspaceResolver.UserDefinedEnvironment; + + // If a unique environment wasn't specified and the project graph determined the environment variables affecting the build, + // we're going to give the subset of those environment variables to the Pip. + if (m_msBuildResolverSettings.Environment == null && result.EnvironmentVariablesAffectingBuild != null) + { + var graphedEnvVars = result.EnvironmentVariablesAffectingBuild.ToHashSet(); + pipEnvironment = m_msBuildWorkspaceResolver.UserDefinedEnvironment.Where(kvp => graphedEnvVars.Contains(kvp.Key)); + } + var graphConstructor = new PipGraphConstructor( m_context, m_host, @@ -163,8 +173,8 @@ private Task EvaluateAllFilesAsync(IReadOnlySet evaluationGo m_msBuildResolverSettings, result.MsBuildLocation, result.DotNetExeLocation, - m_frontEndName, - m_msBuildWorkspaceResolver.UserDefinedEnvironment, + m_frontEndName, + pipEnvironment, m_msBuildWorkspaceResolver.UserDefinedPassthroughVariables); return graphConstructor.TrySchedulePipsForFilesAsync(filteredBuildFiles, qualifierId); diff --git a/Public/Src/FrontEnd/MsBuild/MsBuildWorkspaceResolver.cs b/Public/Src/FrontEnd/MsBuild/MsBuildWorkspaceResolver.cs index 0dd9f191bd..c2564ba22d 100644 --- a/Public/Src/FrontEnd/MsBuild/MsBuildWorkspaceResolver.cs +++ b/Public/Src/FrontEnd/MsBuild/MsBuildWorkspaceResolver.cs @@ -424,7 +424,7 @@ private async Task> TryComputeBuildGraphAsync(IEnum allowedModuleDependencies: null, // no module policies cyclicalFriendModules: null); // no whitelist of cycles - return new ProjectGraphResult(projectGraph, moduleDefinition, projectGraphResult.PathToMsBuild, projectGraphResult.PathToDotNetExe); + return new ProjectGraphResult(projectGraph, moduleDefinition, projectGraphResult.PathToMsBuild, projectGraphResult.PathToDotNetExe, projectGraphResult.EnvironmentVariablesAffectingBuild); } private void DeleteGraphBuilderRelatedFiles(AbsolutePath outputFile, AbsolutePath responseFile) @@ -538,8 +538,6 @@ private async Task>> Co standardError); } - TrackFilesAndEnvironment(result.AllUnexpectedFileAccesses, outputFile.GetParent(m_context.PathTable)); - var serializer = JsonSerializer.Create(ProjectGraphSerializationSettings.Settings); serializer.Converters.Add(new AbsolutePathJsonConverter(m_context.PathTable)); serializer.Converters.Add(new ValidAbsolutePathEnumerationJsonConverter()); @@ -549,6 +547,8 @@ private async Task>> Co { var projectGraphWithPredictionsResult = serializer.Deserialize>(reader); + TrackFilesAndEnvironment(result.AllUnexpectedFileAccesses, outputFile.GetParent(m_context.PathTable), projectGraphWithPredictionsResult.EnvironmentVariablesAffectingBuild); + // A successfully constructed graph should always have a valid path to MsBuild Contract.Assert(!projectGraphWithPredictionsResult.Succeeded || projectGraphWithPredictionsResult.PathToMsBuild.IsValid); // A successfully constructed graph should always have at least one project node @@ -586,15 +586,27 @@ private bool TryFindDotNetExe(IEnumerable dotnetSearchLocations, o return false; } - private void TrackFilesAndEnvironment(ISet fileAccesses, AbsolutePath frontEndFolder) + private void TrackFilesAndEnvironment(ISet fileAccesses, AbsolutePath frontEndFolder, IEnumerable environmentVariablesAffectingBuild) { // Register all build parameters passed to the graph construction process // Observe passthrough variables are explicitly skipped: we don't want the engine to track them - // TODO: we actually need the build parameters *used* by the graph construction process, but for now this is a compromise to keep - // graph caching sound. We need to modify this when MsBuild static graph API starts providing used env vars. - foreach (string key in m_userDefinedEnvironment.Keys) + + // If a specific environment wasn't passed in AND if the graph's env vars parameter is NOT null + // (meaning we successfully retrieved the list of environment variables that affect + // the build during evaluation), then tell the engine to track them. + if (m_resolverSettings.Environment == null && environmentVariablesAffectingBuild != null) + { + foreach (string environmentVariable in environmentVariablesAffectingBuild) + { + m_host.Engine.TryGetBuildParameter(environmentVariable, MsBuildFrontEnd.Name, out _); + } + } + else { - m_host.Engine.TryGetBuildParameter(key, MsBuildFrontEnd.Name, out _); + foreach (string key in m_userDefinedEnvironment.Keys) + { + m_host.Engine.TryGetBuildParameter(key, MsBuildFrontEnd.Name, out _); + } } FrontEndUtilities.TrackToolFileAccesses(m_host.Engine, m_context, MsBuildFrontEnd.Name, fileAccesses, frontEndFolder); diff --git a/Public/Src/FrontEnd/MsBuild/ProjectGraphResult.cs b/Public/Src/FrontEnd/MsBuild/ProjectGraphResult.cs index 1739af0962..33c44955c8 100644 --- a/Public/Src/FrontEnd/MsBuild/ProjectGraphResult.cs +++ b/Public/Src/FrontEnd/MsBuild/ProjectGraphResult.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Collections.Generic; using System.Diagnostics.ContractsLight; using BuildXL.FrontEnd.MsBuild.Serialization; using BuildXL.FrontEnd.Workspaces.Core; @@ -27,7 +28,10 @@ public readonly struct ProjectGraphResult public AbsolutePath DotNetExeLocation { get; } /// - public ProjectGraphResult(ProjectGraphWithPredictions projectGraphWithPredictions, ModuleDefinition moduleDefinition, AbsolutePath msBuildLocation, AbsolutePath dotnetExeLocation) + public IEnumerable EnvironmentVariablesAffectingBuild { get; } + + /// + public ProjectGraphResult(ProjectGraphWithPredictions projectGraphWithPredictions, ModuleDefinition moduleDefinition, AbsolutePath msBuildLocation, AbsolutePath dotnetExeLocation, IEnumerable environmentVariablesAffectingBuild) { Contract.Requires(projectGraphWithPredictions != null); Contract.Requires(moduleDefinition != null); @@ -37,6 +41,7 @@ public ProjectGraphResult(ProjectGraphWithPredictions projectGraph ModuleDefinition = moduleDefinition; MsBuildLocation = msBuildLocation; DotNetExeLocation = dotnetExeLocation; + EnvironmentVariablesAffectingBuild = environmentVariablesAffectingBuild; } } } diff --git a/Public/Src/Tools/Tool.MsBuildGraphBuilder/MsBuildGraphBuilder.cs b/Public/Src/Tools/Tool.MsBuildGraphBuilder/MsBuildGraphBuilder.cs index da29364146..394eda5ff3 100644 --- a/Public/Src/Tools/Tool.MsBuildGraphBuilder/MsBuildGraphBuilder.cs +++ b/Public/Src/Tools/Tool.MsBuildGraphBuilder/MsBuildGraphBuilder.cs @@ -12,6 +12,7 @@ using System.Reflection; using System.Threading.Tasks; using BuildXL.FrontEnd.MsBuild.Serialization; +using BuildXL.Utilities; using BuildXL.Utilities.Instrumentation.Common; using Microsoft.Build.Definition; using Microsoft.Build.Evaluation; @@ -24,6 +25,8 @@ using ProjectGraphWithPredictions = BuildXL.FrontEnd.MsBuild.Serialization.ProjectGraphWithPredictions; using ProjectWithPredictions = BuildXL.FrontEnd.MsBuild.Serialization.ProjectWithPredictions; using BuildXL.Utilities.Collections; +using Microsoft.Build.Framework; +using ProjectGraphBuilder; namespace MsBuildGraphBuilderTool { @@ -144,10 +147,12 @@ private static ProjectGraphWithPredictionsResult BuildGraphInternal( locatedMsBuildPath); } + var environmentVariablesLogger = new PropertyTrackingLogger(); + var projectGraph = new ProjectGraph( entryPoints, // The project collection doesn't need any specific global properties, since entry points already contain all the ones that are needed, and the project graph will merge them - new ProjectCollection(), + new ProjectCollection(globalProperties: null, loggers: new ILogger[]{ environmentVariablesLogger }, ToolsetDefinitionLocations.Default), (projectPath, globalProps, projectCollection) => ProjectInstanceFactory(projectPath, globalProps, projectCollection, projectInstanceToProjectCache)); // This is a defensive check to make sure the assembly loader actually honored the search locations provided by the user. The path of the assembly where ProjectGraph @@ -182,7 +187,21 @@ private static ProjectGraphWithPredictionsResult BuildGraphInternal( locatedMsBuildPath); } - return ProjectGraphWithPredictionsResult.CreateSuccessfulGraph(projectGraphWithPredictions, assemblyPathsToLoad, locatedMsBuildPath); + // Get the possible environment variable reads from the logger. + // If there was a failure, report the failure message. + var envVarResult = environmentVariablesLogger.PotentialEnvironmentVariableReads; + var reads = envVarResult.Succeeded ? envVarResult.Result : (IReadOnlyCollection)null; + + if (!envVarResult.Succeeded) + { + reporter.ReportMessage(envVarResult.Failure.Describe()); + } + + return ProjectGraphWithPredictionsResult.CreateSuccessfulGraph( + projectGraphWithPredictions, + assemblyPathsToLoad, + locatedMsBuildPath, + reads); } catch (InvalidProjectFileException e) { diff --git a/Public/Src/Tools/Tool.MsBuildGraphBuilder/PropertyTrackingLogger.cs b/Public/Src/Tools/Tool.MsBuildGraphBuilder/PropertyTrackingLogger.cs new file mode 100644 index 0000000000..12e9a38c24 --- /dev/null +++ b/Public/Src/Tools/Tool.MsBuildGraphBuilder/PropertyTrackingLogger.cs @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using BuildXL.Utilities; +using BuildXL.Utilities.Collections; +using Microsoft.Build.Framework; + +namespace ProjectGraphBuilder +{ + /// + /// Logger that handles property tracking events. + /// + internal sealed class PropertyTrackingLogger : ILogger + { + private readonly ConcurrentDictionary m_variablesRead = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private readonly ConcurrentDictionary m_sdkResolversNotTrackingEnvVars = new ConcurrentDictionary(); + + public PropertyTrackingLogger() + { + // This environment variable enable property tracking in MsBuild. + // Without it, no events would be logged or received. + // A value of "12" tells MsBuild to log events "Environment Variable Read" and "Uninitialized Property Read". + Environment.SetEnvironmentVariable("MsBuildLogPropertyTracking", "12"); + } + + public void Initialize(IEventSource eventSource) + { + eventSource.AnyEventRaised += (sender, args) => + { + if (args is EnvironmentVariableReadEventArgs evrArgs) + { + m_variablesRead[evrArgs.EnvironmentVariableName] = null; + } + else if (args is UninitializedPropertyReadEventArgs upArgs) + { + m_variablesRead[upArgs.PropertyName] = null; + } + // This is for future work being done. + //else if (args is SdkResolverDoesNotTrackEnvironmentVariablesEventArgs trackArgs) + //{ + // m_sdkResolversNotTrackingEnvVars[trackArgs.SdkResolverName] = null; + //} + }; + } + + public void Shutdown() + { + } + + public LoggerVerbosity Verbosity { get; set; } + + public string Parameters { get; set; } + + /// + /// The list of environment variables that would be read by the build system if present. + /// + public Possible> PotentialEnvironmentVariableReads + { + get + { + if (m_sdkResolversNotTrackingEnvVars.Count == 0) + { + return new Possible>(m_variablesRead.Keys.ToArray()); + } + + string errorMessage = null; + + lock (m_sdkResolversNotTrackingEnvVars) + { + errorMessage = $"Unreliable environment variable tracking due to SdkResolvers not participating in tracking. Offenders: {string.Join(",", m_sdkResolversNotTrackingEnvVars)}"; + } + + return new Failure(errorMessage); + } + } + } +} diff --git a/Public/Src/Tools/Tool.MsBuildGraphBuilder/Tool.MsBuildGraphBuilder.dsc b/Public/Src/Tools/Tool.MsBuildGraphBuilder/Tool.MsBuildGraphBuilder.dsc index ff0120a13f..f1f489c6c7 100644 --- a/Public/Src/Tools/Tool.MsBuildGraphBuilder/Tool.MsBuildGraphBuilder.dsc +++ b/Public/Src/Tools/Tool.MsBuildGraphBuilder/Tool.MsBuildGraphBuilder.dsc @@ -23,6 +23,7 @@ namespace MsBuildGraphBuilder { importFrom("BuildXL.FrontEnd").MsBuild.Serialization.dll, importFrom("BuildXL.Utilities").Collections.dll, importFrom("BuildXL.Utilities").Native.dll, + importFrom("BuildXL.Utilities").dll, importFrom("BuildXL.Utilities.Instrumentation").Common.dll, ...addIf(BuildXLSdk.isFullFramework, importFrom("System.Collections.Immutable").pkg), ...addIf(BuildXLSdk.isFullFramework, importFrom("System.Threading.Tasks.Dataflow").pkg), diff --git a/Public/Src/Tools/UnitTests/MsBuildGraphBuilder/App.config b/Public/Src/Tools/UnitTests/MsBuildGraphBuilder/App.config new file mode 100644 index 0000000000..d5a4ff5b8f --- /dev/null +++ b/Public/Src/Tools/UnitTests/MsBuildGraphBuilder/App.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Public/Src/Tools/UnitTests/MsBuildGraphBuilder/MsBuildGraphProjectPredictionTests.cs b/Public/Src/Tools/UnitTests/MsBuildGraphBuilder/MsBuildGraphProjectPredictionTests.cs index 7d3845d228..86a77037c2 100644 --- a/Public/Src/Tools/UnitTests/MsBuildGraphBuilder/MsBuildGraphProjectPredictionTests.cs +++ b/Public/Src/Tools/UnitTests/MsBuildGraphBuilder/MsBuildGraphProjectPredictionTests.cs @@ -92,5 +92,38 @@ public void ProblematicPredictorsAreHandled() Assert.False(result.Succeeded); Assert.True(result.Failure.Message != null); } + + [Fact] + public void PropertyTrackingIsEnabledAndWorks() + { + string outputFile = Path.Combine(TemporaryDirectory, Guid.NewGuid().ToString()); + string entryPoint = Path.Combine(TemporaryDirectory, Guid.NewGuid().ToString()); + + // Create an environment variable with a unique name. + string envVarName = Guid.NewGuid().ToString().Replace("-", string.Empty); + Environment.SetEnvironmentVariable(envVarName, "value not important"); + + File.WriteAllText(entryPoint, + "$(" + envVarName + ")"); + + MsBuildGraphBuilder.BuildGraphAndSerialize( + GetStandardBuilderArguments( + new[] { entryPoint }, + outputFile, + globalProperties: GlobalProperties.Empty, + entryPointTargets: new string[0], + requestedQualifiers: new GlobalProperties[] { GlobalProperties.Empty }, + allowProjectsWithoutTargetProtocol: false)); + + // Remove the environment variables. + Environment.SetEnvironmentVariable(envVarName, string.Empty); + + var result = SimpleDeserializer.Instance.DeserializeGraph(outputFile); + Assert.True(result.Succeeded); + + // Tracking should have reported the set (and read) env var. + Assert.NotNull(result.EnvironmentVariablesAffectingBuild); + Assert.True(result.EnvironmentVariablesAffectingBuild.Contains(envVarName)); + } } } \ No newline at end of file diff --git a/Public/Src/Tools/UnitTests/MsBuildGraphBuilder/MsBuildPropertyTrackingLoggerTests.cs b/Public/Src/Tools/UnitTests/MsBuildGraphBuilder/MsBuildPropertyTrackingLoggerTests.cs new file mode 100644 index 0000000000..60bcffbd56 --- /dev/null +++ b/Public/Src/Tools/UnitTests/MsBuildGraphBuilder/MsBuildPropertyTrackingLoggerTests.cs @@ -0,0 +1,87 @@ +using System; +using System.Linq; +using Microsoft.Build.Framework; +using ProjectGraphBuilder; +using Test.BuildXL.TestUtilities.Xunit; +using Xunit; +using Xunit.Abstractions; + +namespace Test.Tool.ProjectGraphBuilder +{ + public class MsBuildPropertyTrackingLoggerTests : XunitBuildXLTest + { + public MsBuildPropertyTrackingLoggerTests(ITestOutputHelper output) : base(output) { } + + [Fact] + public void TracksEnvironmentVariableReads() + { + var eventSource = new TestEventSource(); + var logger = new PropertyTrackingLogger(); + logger.Initialize(eventSource); + + string envVarName = Guid.NewGuid().ToString(); + string message = "unused"; + eventSource.FireAnyEvent(new EnvironmentVariableReadEventArgs(envVarName, message)); + + Assert.NotNull(logger.PotentialEnvironmentVariableReads); + Assert.True(logger.PotentialEnvironmentVariableReads.Succeeded); + Assert.NotNull(logger.PotentialEnvironmentVariableReads.Result); + Assert.True(logger.PotentialEnvironmentVariableReads.Result.Contains(envVarName)); + Assert.Equal(1, logger.PotentialEnvironmentVariableReads.Result.Count); + } + + [Fact] + public void TracksUninitializedPropertyReads() + { + var eventSource = new TestEventSource(); + var logger = new PropertyTrackingLogger(); + logger.Initialize(eventSource); + + string propertyName = Guid.NewGuid().ToString(); + string message = "unused"; + eventSource.FireAnyEvent(new UninitializedPropertyReadEventArgs(propertyName, message)); + + Assert.NotNull(logger.PotentialEnvironmentVariableReads); + Assert.True(logger.PotentialEnvironmentVariableReads.Succeeded); + Assert.NotNull(logger.PotentialEnvironmentVariableReads.Result); + Assert.True(logger.PotentialEnvironmentVariableReads.Result.Contains(propertyName)); + Assert.Equal(1, logger.PotentialEnvironmentVariableReads.Result.Count); + } + + private class TestEventSource : IEventSource + { + public void FireAnyEvent(BuildEventArgs e) + { + this.AnyEventRaised?.Invoke(this, e); + } + + public event BuildMessageEventHandler MessageRaised; + + public event BuildErrorEventHandler ErrorRaised; + + public event BuildWarningEventHandler WarningRaised; + + public event BuildStartedEventHandler BuildStarted; + + public event BuildFinishedEventHandler BuildFinished; + + public event ProjectStartedEventHandler ProjectStarted; + + public event ProjectFinishedEventHandler ProjectFinished; + + public event TargetStartedEventHandler TargetStarted; + + public event TargetFinishedEventHandler TargetFinished; + + public event TaskStartedEventHandler TaskStarted; + + public event TaskFinishedEventHandler TaskFinished; + + public event CustomBuildEventHandler CustomEventRaised; + + public event BuildStatusEventHandler StatusEventRaised; + + public event AnyEventHandler AnyEventRaised; + } + } +} diff --git a/Public/Src/Tools/UnitTests/MsBuildGraphBuilder/Test.Tool.MsBuildGraphBuilder.dsc b/Public/Src/Tools/UnitTests/MsBuildGraphBuilder/Test.Tool.MsBuildGraphBuilder.dsc index 6395788c55..dea32418c0 100644 --- a/Public/Src/Tools/UnitTests/MsBuildGraphBuilder/Test.Tool.MsBuildGraphBuilder.dsc +++ b/Public/Src/Tools/UnitTests/MsBuildGraphBuilder/Test.Tool.MsBuildGraphBuilder.dsc @@ -12,9 +12,11 @@ namespace Test.Tool.MsBuildGraphBuilder { export const dll = BuildXLSdk.test({ assemblyName: "Test.Tool.ProjectGraphBuilder", sources: globR(d`.`, "*.cs"), + appConfig: f`App.Config`, testFramework: importFrom("Sdk.Managed.Testing.XUnit").framework, references:[ importFrom("BuildXL.Tools").MsBuildGraphBuilder.exe, + importFrom("BuildXL.Utilities").dll, importFrom("Microsoft.Build.Prediction").pkg, importFrom("Newtonsoft.Json").pkg, importFrom("BuildXL.FrontEnd").MsBuild.Serialization.dll, @@ -22,7 +24,6 @@ namespace Test.Tool.MsBuildGraphBuilder { ], runtimeContent: [ ...MSBuild.msbuildRuntimeContent, - ...MSBuild.msbuildReferences, ], runtimeContentToSkip: [ importFrom("System.Threading.Tasks.Dataflow").pkg diff --git a/config.dsc b/config.dsc index c4e08a18a2..13b35b121a 100644 --- a/config.dsc +++ b/config.dsc @@ -48,6 +48,7 @@ config({ "BuildXL.Selfhost": "https://pkgs.dev.azure.com/cloudbuild/_packaging/BuildXL.Selfhost/nuget/v3/index.json", // Note: From a compliance point of view it is important that MicrosoftInternal has a single feed. // If you need to consume packages make sure they are upstreamed in that feed. + "msbuild-local" : "file://D:/src/msbuild/artifacts/packages/Debug/Shipping", } : { "buildxl-selfhost" : "https://pkgs.dev.azure.com/ms/BuildXL/_packaging/BuildXL.Selfhost/nuget/v3/index.json", @@ -678,6 +679,14 @@ config({ trackSourceFileChanges: true, isWritable: false, isReadable: true + }, + { + name: a`LocalMsBuildNupkgs`, + path: p`D:/src/msbuild/artifacts/packages/Debug/Shipping`, + trackSourceFileChanges: true, + isWritable: true, + isReadable: true, + isScrubbable: true } ],