Conversation
|
@copilot could you please move all $(LatestDotNetCoreForMSBuild) related changes to a separate PR? |
|
@YuliiaKovalova I've opened a new pull request, #13189, to work on those changes. Once the pull request is ready, I'll request review from you. |
90e06c7 to
95f4da2
Compare
…otnet/msbuild into dev/ykovalova/app_host_support
| exeName += msbuildExtn; | ||
| } | ||
|
|
||
| fullCommandLine = $"'{string.Join(" ", commandLineArgs)}'"; |
There was a problem hiding this comment.
it looks like it's needed with app host support, because for NET now it attaches:
MSBuild.exe.dll
7e349a2 to
fd3905f
Compare
15673a9 to
3641a4b
Compare
|
|
||
| <Target Name="CopyDllConfigToAppHostConfig" AfterTargets="_CopyAppConfigFile" Condition="'$(TargetFrameworkIdentifier)' != '.NETFramework'"> | ||
| <Copy SourceFiles="$(OutputPath)$(AssemblyName).dll.config" DestinationFiles="$(OutputPath)$(AssemblyName)$(_AppHostExtension).config" SkipUnchangedFiles="true" Condition="Exists('$(OutputPath)$(AssemblyName).dll.config')" /> | ||
| <Copy SourceFiles="$(OutputPath)$(AssemblyName).dll.config" DestinationFiles="$(ArtifactsDir)bin\Microsoft.Build.Engine.UnitTests\$(Configuration)\$(TargetFramework)\$(AssemblyName)$(_AppHostExtension).config" SkipUnchangedFiles="true" Condition="Exists('$(OutputPath)$(AssemblyName).dll.config')" /> |
| using TestEnvironment env = TestEnvironment.Create(_output, setupDotnetHostPath: true); | ||
| var coreDirectory = Path.Combine(RunnerUtilities.BootstrapRootPath, "core"); | ||
| env.SetEnvironmentVariable("PATH", $"{coreDirectory}{Path.PathSeparator}{Environment.GetEnvironmentVariable("PATH")}"); | ||
| env.SetEnvironmentVariable("DOTNET_ROOT", coreDirectory); |
b351ea2 to
b9d8d49
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds initial “app host” support so MSBuild can run as a native executable (MSBuild[.exe]) and ensures spawned nodes/task hosts can locate the .NET runtime by applying scoped DOTNET_ROOT* environment overrides (and clearing bootstrap-only variables afterward).
Changes:
- Introduces
DotnetHostEnvironmentHelperand threads environment overrides through node/task-host launching (newNodeLaunchDatapath). - Updates build environment detection and test infrastructure to prefer/use the MSBuild app host where available.
- Expands/adjusts test coverage for app host behavior and updates resources/packaging to include app-host config where needed.
Reviewed changes
Copilot reviewed 63 out of 64 changed files in this pull request and generated 27 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Utilities.UnitTests/ToolLocationHelper_Tests.cs | Updates tests to use Constants.MSBuildExecutableName instead of hardcoded names. |
| src/UnitTests.Shared/TestEnvironment.cs | Adds setupDotnetHostPath option to configure DOTNET_HOST_PATH for app-host-related tests. |
| src/UnitTests.Shared/RunnerUtilities.cs | Simplifies MSBuild invocation to run the resolved MSBuild entrypoint directly; updates bootstrap execution path. |
| src/UnitTests.Shared/BootstrapLocationAttribute.cs | Clarifies docs about resolving MSBuild entrypoint across OS/runtime. |
| src/Tasks.UnitTests/RoslynCodeTaskFactory_Tests.cs | Ensures tests set up DOTNET_HOST_PATH when out-of-proc is used. |
| src/Tasks.UnitTests/CreateItem_Tests.cs | Enables setupDotnetHostPath for out-of-proc TaskHost tests. |
| src/Shared/UnitTests/TestAssemblyInfo.cs | Uses constants for DOTNET_HOST_PATH env var name. |
| src/Shared/INodePacket.cs | Bumps packet version to 3 to account for new app-host-related behavior. |
| src/Shared/FrameworkLocationHelper.cs | Uses Constants.MSBuildExecutableName when validating framework install contents. |
| src/Shared/EnvironmentUtilities.cs | Tweaks ProcessPath caching implementation (and related comment). |
| src/Shared/BuildEnvironmentHelper.cs | Updates environment discovery and “running in MSBuild.exe” detection for app host scenarios. |
| src/MSBuildTaskHost/MSBuildTaskHost.csproj | Links Constants.cs to keep TaskHost consistent with new constants usage. |
| src/MSBuild/XMake.cs | Adjusts args handling to use native process path on .NET. |
| src/MSBuild/OutOfProcTaskHostNode.cs | Clears bootstrap-only DOTNET_ROOT* variables after applying build environment in task host. |
| src/MSBuild/MSBuild.csproj | Adds copying of .dll.config to apphost .config; conditions XSD inclusion for .NET Framework only. |
| src/MSBuild/CommandLine/CommandLineParser.cs | Removes extension-appending logic; relies on CurrentMSBuildExePath directly. |
| src/MSBuild.UnitTests/XMake_Tests.cs | Updates tests to run MSBuild directly and use Constants.MSBuildExecutableName. |
| src/Framework/TaskHostParameters.cs | Renames MSBuild path property to reflect executable/apphost usage and updates merge logic. |
| src/Framework/DotnetHostEnvironmentHelper.cs | New helper to create/apply env overrides and clear bootstrap-only DOTNET_ROOT*. |
| src/Framework/BinaryTranslator.cs | Updates serialization variable naming for TaskHostParameters MSBuild path. |
| src/Build/Resources/xlf/Strings.zh-Hant.xlf | Adds new resource id; updates some existing targets’ state/content. |
| src/Build/Resources/xlf/Strings.zh-Hans.xlf | Adds new resource id; updates some existing targets’ state/content. |
| src/Build/Resources/xlf/Strings.tr.xlf | Adds new resource id; updates some existing targets’ state/content. |
| src/Build/Resources/xlf/Strings.ru.xlf | Adds new resource id; updates some existing targets’ state/content. |
| src/Build/Resources/xlf/Strings.pt-BR.xlf | Adds new resource id; updates some existing targets’ state/content. |
| src/Build/Resources/xlf/Strings.pl.xlf | Adds new resource id; updates some existing targets’ state/content. |
| src/Build/Resources/xlf/Strings.ko.xlf | Adds new resource id; updates some existing targets’ state/content. |
| src/Build/Resources/xlf/Strings.ja.xlf | Adds new resource id; updates some existing targets’ state/content. |
| src/Build/Resources/xlf/Strings.it.xlf | Adds new resource id; updates some existing targets’ state/content. |
| src/Build/Resources/xlf/Strings.fr.xlf | Adds new resource id; updates some existing targets’ state/content. |
| src/Build/Resources/xlf/Strings.es.xlf | Adds new resource id; updates some existing targets’ state/content. |
| src/Build/Resources/xlf/Strings.de.xlf | Adds new resource id; updates some existing targets’ state/content. |
| src/Build/Resources/xlf/Strings.cs.xlf | Adds new resource id; updates some existing targets’ state/content. |
| src/Build/Resources/Strings.resx | Adds DotnetHostPathNotSet resource. |
| src/Build/Instance/TaskFactories/TaskHostTask.cs | Improves error reporting on abort and generalizes exception handling. |
| src/Build/Instance/TaskFactories/AssemblyTaskFactory.cs | Uses updated TaskHostParameters MSBuild path property. |
| src/Build/Evaluation/IntrinsicFunctions.cs | Uses updated TaskHostParameters MSBuild path property. |
| src/Build/BackEnd/Node/OutOfProcNode.cs | Clears bootstrap-only DOTNET_ROOT* after applying build environment in worker node. |
| src/Build/BackEnd/Node/NativeMethods.cs | Adds CREATE_UNICODE_ENVIRONMENT constant for Windows process creation. |
| src/Build/BackEnd/Components/SdkResolution/SdkResolverLoader.cs | Refines fallback logic based on whether running in MSBuild app host. |
| src/Build/BackEnd/Components/Communications/RarNodeLauncher.cs | Uses NodeLaunchData overload to launch RAR node. |
| src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcTaskHost.cs | Adds app-host-or-dotnet fallback and environment override support for task hosts. |
| src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcBase.cs | Threads NodeLaunchData through node acquisition; updates error details and doc comment. |
| src/Build/BackEnd/Components/Communications/NodeProviderOutOfProc.cs | Uses NodeLaunchData and applies DOTNET_ROOT overrides when launching worker nodes. |
| src/Build/BackEnd/Components/Communications/NodeLauncher.cs | Adds Windows environment-block construction and per-process environment overrides. |
| src/Build/BackEnd/Components/Communications/INodeLauncher.cs | Introduces NodeLaunchData record struct and updates launcher API. |
| src/Build/BackEnd/Components/Communications/DetouredNodeLauncher.cs | Adapts detoured launching to NodeLaunchData and applies environment overrides. |
| src/Build/BackEnd/Client/MSBuildClient.cs | Updates server launch to use NodeLaunchData. |
| src/Build.UnitTests/TestComparers/TaskRegistryComparers.cs | Updates comparer to use new TaskHostParameters MSBuild path property. |
| src/Build.UnitTests/TaskHostFactoryLifecycle_E2E_Tests.cs | Enables setupDotnetHostPath when exercising TaskHostFactory flows. |
| src/Build.UnitTests/ProjectCache/ProjectCacheTests.cs | Removes now-unneeded internal using. |
| src/Build.UnitTests/NetTaskHost_E2E_Tests.cs | Adds explicit tests for app-host usage and fallback behavior. |
| src/Build.UnitTests/Instance/TaskItem_Tests.cs | Ensures DOTNET_HOST_PATH is set for TaskHostFactory-related escaping tests. |
| src/Build.UnitTests/EscapingInProjects_Tests.cs | Ensures DOTNET_HOST_PATH is set for task-host scenarios. |
| src/Build.UnitTests/Definition/ToolsetRegistryReader_Tests.cs | Adds Microsoft.Build.Framework using for constants. |
| src/Build.UnitTests/Definition/ToolsetReader_Tests.cs | Adds Microsoft.Build.Framework using for constants. |
| src/Build.UnitTests/BuildEnvironmentHelper_Tests.cs | Updates tests to expect Constants.MSBuildExecutableName. |
| src/Build.UnitTests/BackEnd/TaskRouter_IntegrationTests.cs | Enables setupDotnetHostPath for integration tests that spawn nodes. |
| src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs | Enables setupDotnetHostPath for TaskHostFactory tests. |
| src/Build.UnitTests/BackEnd/SdkResolverLoader_Tests.cs | Updates commentary to match new app-host-based fallback criteria. |
| src/Build.UnitTests/BackEnd/BuildManager_Tests.cs | Wraps one test in TestEnvironment setup for app-host correctness. |
| src/Build.UnitTests/BackEnd/AppHostSupport_Tests.cs | New unit tests for DOTNET_ROOT override/clearing behavior. |
| eng/MicrobuildTest.ps1 | Removes legacy Microbuild validation script. |
| azure-pipelines/.vsts-dotnet-build-jobs.yml | Trims whitespace in a script block (format-only change). |
src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcBase.cs
Show resolved
Hide resolved
src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcBase.cs
Show resolved
Hide resolved
src/Build/BackEnd/Components/Communications/NodeProviderOutOfProcBase.cs
Show resolved
Hide resolved
44df75a to
cada425
Compare
2e0df7c to
7433663
Compare
| /// </param> | ||
| /// <param name="setupDotnetHostPath"> | ||
| /// When true, configures .NET environment variable DOTNET_HOST_PATH to point to the bootstrap core directory. | ||
| /// It's necessary for the tests that rely on app host execution and need to find the correct .NET runtime. |
There was a problem hiding this comment.
Does the mainline support stuff (using the .NET SDK and getting the pointer that way) not work in our tests? Should it?
There was a problem hiding this comment.
nope, it doesn't work when we point to bootstrapped app host during the test execution :(
| public void InlineTaskWithAssemblyPlatformAgnostic(bool forceOutOfProc) | ||
| { | ||
| using (TestEnvironment env = TestEnvironment.Create()) | ||
| using (TestEnvironment env = TestEnvironment.Create(setupDotnetHostPath: true)) |
There was a problem hiding this comment.
I don't think I understand why we need the setupDotnetHostPath: true here. That feels wrong and bad; can we avoid it?
There was a problem hiding this comment.
should that method learn to pass the necessary environment, instead?
| /// </summary> | ||
| /// <param name="dotnetHostPath">Path to the dotnet executable.</param> | ||
| /// <returns>Dictionary of environment variable overrides, or null if dotnetHostPath is empty.</returns> | ||
| internal static IDictionary<string, string>? CreateDotnetRootEnvironmentOverrides(string? dotnetHostPath = null) |
There was a problem hiding this comment.
How often is this called? Worth stashing the last value so we don't create a bunch of transient dictionaries?
| msbuildLocation = Constants.MSBuildExecutableName; | ||
| } | ||
|
|
||
| var expectedProcessName = Path.GetFileNameWithoutExtension(CurrentHost.GetCurrentHost() ?? msbuildLocation); |
There was a problem hiding this comment.
This needs to be updated. As is right now, node reuse isn't working. To test, build a multi-project solution with -m -nr:true and watch the MSBuild.exe process accumulate.

Part 1 of: #12995
Context
This PR implements App Host support for MSBuild, enabling MSBuild to run as a native executable (MSBuild.exe or MSBuild on Unix) instead of dotnet + MSBuild.dll
Changes Made
Added DotnetHostEnvironmentHelper class to manage DOTNET_ROOT environment variables
When MSBuild runs as an app host, child processes (worker nodes and task hosts) need DOTNET_ROOT set to locate the .NET runtime
These variables are cleared after startup so they don't leak to tools executed by child processes
Only clears DOTNET_ROOT variants if they weren't present in the original build process environment
Node Launcher Updates
Updated NodeLauncher to pass environment overrides when launching worker nodes
NodeLaunchData record struct with EnvironmentOverrides support
Implemented BuildEnvironmentBlock for Windows process creation with custom environment
NodeProviderOutOfProc and NodeProviderOutOfProcTaskHost now provide DOTNET_ROOT overrides
Notes
Backward compatible: Falls back to dotnet MSBuild.dll if app host doesn't exist (older SDKs)
Uses ProcessStartInfo.Environment for thread-safe, scoped environment overrides
The SDK can continue using dotnet MSBuild.dll or opt to use the new app host—this is not a forced change