From a61619fc31042c4e87173d645e4ae4b07fa6168b Mon Sep 17 00:00:00 2001 From: SimaTian Date: Tue, 2 Sep 2025 12:41:14 +0200 Subject: [PATCH 1/8] MSBuild sever dogfood --- build.cmd | 1 + build.sh | 1 + eng/dotnet-format/dotnet-format-integration.yml | 10 ++++++++++ eng/pipelines/templates/jobs/sdk-build.yml | 2 ++ eng/pipelines/templates/variables/sdk-defaults.yml | 3 +++ 5 files changed, 17 insertions(+) diff --git a/build.cmd b/build.cmd index 3d0115980b65..1a660d48aa95 100644 --- a/build.cmd +++ b/build.cmd @@ -10,5 +10,6 @@ if %errorlevel%==0 ( set skipFlags="/p:SkipUsingCrossgen=true /p:SkipBuildingInstallers=true" ) set DOTNET_SYSTEM_NET_SECURITY_NOREVOCATIONCHECKBYDEFAULT=true +set DOTNET_CLI_USE_MSBUILD_SERVER=1 powershell -NoLogo -NoProfile -ExecutionPolicy ByPass -command "& """%~dp0eng\common\build.ps1""" -restore -build -msbuildEngine dotnet %skipFlags% /tlp:summary %*" exit /b %ErrorLevel% diff --git a/build.sh b/build.sh index 49b1e0e55773..4e6b3878f4b6 100755 --- a/build.sh +++ b/build.sh @@ -14,4 +14,5 @@ if [[ "$@" != *"-pack"* ]]; then fi export DOTNET_SYSTEM_NET_SECURITY_NOREVOCATIONCHECKBYDEFAULT="true" +export DOTNET_CLI_USE_MSBUILD_SERVER=1 . "$ScriptRoot/eng/common/build.sh" --build --restore $skipFlags /tlp:summary "$@" diff --git a/eng/dotnet-format/dotnet-format-integration.yml b/eng/dotnet-format/dotnet-format-integration.yml index 1fa8bbb8ad9f..b087d07214c0 100644 --- a/eng/dotnet-format/dotnet-format-integration.yml +++ b/eng/dotnet-format/dotnet-format-integration.yml @@ -81,10 +81,14 @@ jobs: - template: /eng/common/templates/steps/enable-internal-sources.yml - script: .\restore.cmd ${{ parameters.runtimeSourceProperties }} displayName: 🟣 Restore dependencies + env: + DOTNET_CLI_USE_MSBUILD_SERVER: 1 - script: | .\artifacts\sdk-build-env.bat dotnet run --project .\src\BuiltInTools\dotnet-format\dotnet-format.csproj -c Release -- @eng\dotnet-format\validate.rsp displayName: 🟣 Run dotnet-format + env: + DOTNET_CLI_USE_MSBUILD_SERVER: 1 - task: ${{ parameters.oneESCompat.publishTaskPrefix }}PublishBuildArtifacts@1 displayName: 🟣 Publish Logs inputs: @@ -110,9 +114,15 @@ jobs: - template: /eng/common/templates/steps/enable-internal-sources.yml - script: eng\dotnet-format\integration-test.cmd -repo '${{ testArgs._repo }}' -branchName '${{ testArgs._branchName }}' -sha '${{ testArgs._sha }}' -targetSolution '${{ testArgs._targetSolution }}' -useParentSdk ${{ testArgs._useParentSdk }} -testPath '$(Agent.TempDirectory)\temp' -stage 'prepare' -runtimeSourceProperties '${{ parameters.runtimeSourceProperties }}' displayName: 🟣 Prepare ${{ testArgs._repoName }} for formatting + env: + DOTNET_CLI_USE_MSBUILD_SERVER: 1 - script: eng\dotnet-format\integration-test.cmd -repo '${{ testArgs._repo }}' -branchName '${{ testArgs._branchName }}' -sha '${{ testArgs._sha }}' -targetSolution '${{ testArgs._targetSolution }}' -useParentSdk ${{ testArgs._useParentSdk }} -testPath '$(Agent.TempDirectory)\temp' -stage 'format-workspace' displayName: 🟣 Run dotnet-format on ${{ testArgs._repoName }} ${{ testArgs._targetSolution }} + env: + DOTNET_CLI_USE_MSBUILD_SERVER: 1 - script: eng\dotnet-format\integration-test.cmd -repo '${{ testArgs._repo }}' -branchName '${{ testArgs._branchName }}' -sha '${{ testArgs._sha }}' -targetSolution '${{ testArgs._targetSolution }}' -useParentSdk ${{ testArgs._useParentSdk }} -testPath '$(Agent.TempDirectory)\temp' -stage 'format-folder' displayName: 🟣 Run dotnet-format on ${{ testArgs._repoName }} repo folder + env: + DOTNET_CLI_USE_MSBUILD_SERVER: 1 diff --git a/eng/pipelines/templates/jobs/sdk-build.yml b/eng/pipelines/templates/jobs/sdk-build.yml index 67d02032d6b3..c7be3be8accd 100644 --- a/eng/pipelines/templates/jobs/sdk-build.yml +++ b/eng/pipelines/templates/jobs/sdk-build.yml @@ -104,6 +104,7 @@ jobs: env: BuildConfig: $(buildConfiguration) TestFullMSBuild: ${{ parameters.testFullMSBuild }} + DOTNET_CLI_USE_MSBUILD_SERVER: 1 - powershell: build/RunTestTemplateTests.ps1 displayName: 🟣 Run Test Templates Tests @@ -131,6 +132,7 @@ jobs: displayName: 🟣 Build env: BuildConfig: $(buildConfiguration) + DOTNET_CLI_USE_MSBUILD_SERVER: 1 ############### TESTING ############### - ${{ if eq(parameters.runTests, true) }}: diff --git a/eng/pipelines/templates/variables/sdk-defaults.yml b/eng/pipelines/templates/variables/sdk-defaults.yml index 9c5e07f2ad18..e576f5fe34eb 100644 --- a/eng/pipelines/templates/variables/sdk-defaults.yml +++ b/eng/pipelines/templates/variables/sdk-defaults.yml @@ -4,6 +4,9 @@ variables: linuxOsglibcProperties: /p:OSName=linux helixTargetContainerPrefix: '@mcr.microsoft.com/dotnet-buildtools/prereqs:' + # Use MSBuild server globally + DOTNET_CLI_USE_MSBUILD_SERVER: 1 + ############### ARCADE ############### # "Post-build signing" means that this build will NOT sign itself. PostBuildSign: true From 0d1f82a3f0fef8766db8b1398f4252660a8ce4c5 Mon Sep 17 00:00:00 2001 From: SimaTian Date: Thu, 4 Sep 2025 14:32:31 +0200 Subject: [PATCH 2/8] some more places for dogfooding --- build/RunTestsOnHelix.cmd | 3 +++ build/RunTestsOnHelix.sh | 3 ++- eng/dogfood.ps1 | 4 ++++ eng/dogfood.sh | 4 ++++ eng/restore-toolset.ps1 | 2 ++ eng/restore-toolset.sh | 3 ++- 6 files changed, 17 insertions(+), 2 deletions(-) diff --git a/build/RunTestsOnHelix.cmd b/build/RunTestsOnHelix.cmd index f55fcf1ead42..808aeea6b679 100644 --- a/build/RunTestsOnHelix.cmd +++ b/build/RunTestsOnHelix.cmd @@ -27,6 +27,9 @@ set DOTNET_SDK_TEST_EXECUTION_DIRECTORY=%TestExecutionDirectory% set DOTNET_SDK_TEST_MSBUILDSDKRESOLVER_FOLDER=%HELIX_CORRELATION_PAYLOAD%\r set DOTNET_SDK_TEST_ASSETS_DIRECTORY=%TestExecutionDirectory%\TestAssets +set DOTNET_CLI_USE_MSBUILD_SERVER=1 +set MSBUILDUSESERVER=1 + REM call dotnet new so the first run message doesn't interfere with the first test dotnet new --debug:ephemeral-hive diff --git a/build/RunTestsOnHelix.sh b/build/RunTestsOnHelix.sh index 640138d7d8f7..610ad0286359 100644 --- a/build/RunTestsOnHelix.sh +++ b/build/RunTestsOnHelix.sh @@ -16,7 +16,8 @@ cp -a $HELIX_CORRELATION_PAYLOAD/t/TestExecutionDirectoryFiles/. $TestExecutionD export DOTNET_SDK_TEST_EXECUTION_DIRECTORY=$TestExecutionDirectory export DOTNET_SDK_TEST_MSBUILDSDKRESOLVER_FOLDER=$HELIX_CORRELATION_PAYLOAD/r export DOTNET_SDK_TEST_ASSETS_DIRECTORY=$TestExecutionDirectory/TestAssets - +export DOTNET_CLI_USE_MSBUILD_SERVER=1 +export MSBUILDUSESERVER=1 # call dotnet new so the first run message doesn't interfere with the first test dotnet new --debug:ephemeral-hive diff --git a/eng/dogfood.ps1 b/eng/dogfood.ps1 index e7f97d313192..7acda16fe151 100644 --- a/eng/dogfood.ps1 +++ b/eng/dogfood.ps1 @@ -49,6 +49,10 @@ try { $env:DOTNET_ROOT = $TestDotnetRoot $env:DOTNET_ADD_GLOBAL_TOOLS_TO_PATH="0" + # MSBuild dogfood + $env:DOTNET_CLI_USE_MSBUILD_SERVER=1 + $env:MSBUILDUSESERVER=1 + # Avoid downloading Microsoft.Net.Sdk.Compilers.Toolset from feed # Locally built SDK package version is Major.Minor.0-dev, which won't be available. $env:BuildWithNetFrameworkHostedCompiler = $false diff --git a/eng/dogfood.sh b/eng/dogfood.sh index 4aca25a7c757..ef11e74350cb 100755 --- a/eng/dogfood.sh +++ b/eng/dogfood.sh @@ -24,6 +24,10 @@ export DOTNET_MSBUILD_SDK_RESOLVER_SDKS_DIR="$testDotnetRoot/sdk/$testDotnetVers export MicrosoftNETBuildExtensionsTargets="$artifacts_dir/bin/$configuration/Sdks/Microsoft.NET.Build.Extensions/msbuildExtensions/Microsoft/Microsoft.NET.Build.Extensions/Microsoft.NET.Build.Extensions.targets" export PATH=$testDotnetRoot:$PATH + +export DOTNET_CLI_USE_MSBUILD_SERVER=1 +export MSBUILDUSESERVER=1 + export DOTNET_ROOT=$testDotnetRoot export DOTNET_ADD_GLOBAL_TOOLS_TO_PATH=0 export PS1="(dogfood) $PS1" diff --git a/eng/restore-toolset.ps1 b/eng/restore-toolset.ps1 index 5b3fb632f218..94f0bf6475d3 100644 --- a/eng/restore-toolset.ps1 +++ b/eng/restore-toolset.ps1 @@ -42,6 +42,8 @@ function CreateBuildEnvScripts() $scriptContents = @" @echo off title SDK Build ($RepoRoot) +set DOTNET_CLI_USE_MSBUILD_SERVER=1 +set MSBUILDUSESERVER=1 set DOTNET_MULTILEVEL_LOOKUP=0 REM https://aka.ms/vs/unsigned-dotnet-debugger-lib set VSDebugger_ValidateDotnetDebugLibSignatures=0 diff --git a/eng/restore-toolset.sh b/eng/restore-toolset.sh index f7ba940aa92f..345596767a1f 100755 --- a/eng/restore-toolset.sh +++ b/eng/restore-toolset.sh @@ -55,7 +55,8 @@ function CreateBuildEnvScript { scriptContents=" #!/usr/bin/env bash export DOTNET_MULTILEVEL_LOOKUP=0 - +export DOTNET_CLI_USE_MSBUILD_SERVER=1 +export MSBUILDUSESERVER=1 export DOTNET_ROOT=$DOTNET_INSTALL_DIR export DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR=$DOTNET_INSTALL_DIR From 31792b1c02bd2ec9758d1868c6bbf536c6e074de Mon Sep 17 00:00:00 2001 From: SimaTian Date: Mon, 22 Sep 2025 13:00:43 +0200 Subject: [PATCH 3/8] disable interactive mode --- test/dotnet-watch.Tests/Build/EvaluationTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dotnet-watch.Tests/Build/EvaluationTests.cs b/test/dotnet-watch.Tests/Build/EvaluationTests.cs index 5a6786875334..3a6ca35417aa 100644 --- a/test/dotnet-watch.Tests/Build/EvaluationTests.cs +++ b/test/dotnet-watch.Tests/Build/EvaluationTests.cs @@ -490,7 +490,7 @@ public async Task MsbuildOutput() var processRunner = new ProcessRunner(processCleanupTimeout: TimeSpan.Zero); var buildReporter = new BuildReporter(_logger, new GlobalOptions(), options); - var factory = new MSBuildFileSetFactory(project1Path, buildArguments: [], processRunner, buildReporter); + var factory = new MSBuildFileSetFactory(project1Path, buildArguments: ["/interactive:False"], processRunner, buildReporter); var result = await factory.TryCreateAsync(requireProjectGraph: null, CancellationToken.None); Assert.Null(result); From 34f0f662dd390fe28769a452f86882aea6bde4eb Mon Sep 17 00:00:00 2001 From: SimaTian Date: Mon, 22 Sep 2025 14:53:30 +0200 Subject: [PATCH 4/8] test work --- .../GivenThatWeWantToPublishIncrementally.cs | 5 ++++- test/dotnet-watch.Tests/Build/EvaluationTests.cs | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs index c47c60089692..f95f0b1c1498 100644 --- a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs +++ b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs @@ -3,12 +3,16 @@ #nullable disable +using System.Diagnostics; + namespace Microsoft.NET.Publish.Tests { public class GivenThatWeWantToPublishIncrementally : SdkTest { public GivenThatWeWantToPublishIncrementally(ITestOutputHelper log) : base(log) { + // During the dogfood, we want the MSBuild server on for build of the pipeline. Not for the tests - it breaks outputs. + Environment.SetEnvironmentVariable("DOTNET_CLI_USE_MSBUILD_SERVER", "0"); } [Fact] @@ -151,7 +155,6 @@ public void It_cleans_before_trimmed_single_file_publish() // Publish trimmed var publishCommand = new PublishCommand(testAsset); - publishCommand .Execute() .Should() diff --git a/test/dotnet-watch.Tests/Build/EvaluationTests.cs b/test/dotnet-watch.Tests/Build/EvaluationTests.cs index 3a6ca35417aa..5d09172b8f86 100644 --- a/test/dotnet-watch.Tests/Build/EvaluationTests.cs +++ b/test/dotnet-watch.Tests/Build/EvaluationTests.cs @@ -1,14 +1,24 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Text.RegularExpressions; namespace Microsoft.DotNet.Watch.UnitTests { - public class EvaluationTests(ITestOutputHelper output) + public class EvaluationTests { - private readonly TestLogger _logger = new(output); - private readonly TestAssetsManager _testAssets = new(output); + private readonly TestLogger _logger; + private readonly TestAssetsManager _testAssets; + + public EvaluationTests(ITestOutputHelper output) + { + _logger = new TestLogger(output); + _testAssets = new TestAssetsManager(output); + + // During the dogfood, we want the MSBuild server on for build of the pipeline. Not for the tests - it breaks outputs. + Environment.SetEnvironmentVariable("DOTNET_CLI_USE_MSBUILD_SERVER", "0"); + } private static string MuxerPath => TestContext.Current.ToolsetUnderTest.DotNetHostPath; From bd81fb154b8c89cb501c6dd47310931ad393d97a Mon Sep 17 00:00:00 2001 From: SimaTian Date: Mon, 22 Sep 2025 14:55:44 +0200 Subject: [PATCH 5/8] fix --- .../GivenThatWeWantToPublishIncrementally.cs | 2 -- test/dotnet-watch.Tests/Build/EvaluationTests.cs | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs index f95f0b1c1498..a874abd2848a 100644 --- a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs +++ b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs @@ -3,8 +3,6 @@ #nullable disable -using System.Diagnostics; - namespace Microsoft.NET.Publish.Tests { public class GivenThatWeWantToPublishIncrementally : SdkTest diff --git a/test/dotnet-watch.Tests/Build/EvaluationTests.cs b/test/dotnet-watch.Tests/Build/EvaluationTests.cs index 5d09172b8f86..ab1bf7f833fc 100644 --- a/test/dotnet-watch.Tests/Build/EvaluationTests.cs +++ b/test/dotnet-watch.Tests/Build/EvaluationTests.cs @@ -10,11 +10,13 @@ public class EvaluationTests { private readonly TestLogger _logger; private readonly TestAssetsManager _testAssets; + private readonly ITestOutputHelper output; public EvaluationTests(ITestOutputHelper output) { _logger = new TestLogger(output); _testAssets = new TestAssetsManager(output); + this.output = output; // During the dogfood, we want the MSBuild server on for build of the pipeline. Not for the tests - it breaks outputs. Environment.SetEnvironmentVariable("DOTNET_CLI_USE_MSBUILD_SERVER", "0"); From b22554db4fde743e43c1689960013ebeb027ec02 Mon Sep 17 00:00:00 2001 From: SimaTian Date: Mon, 22 Sep 2025 16:03:52 +0200 Subject: [PATCH 6/8] fix --- .../GivenThatWeWantToPublishIncrementally.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs index a874abd2848a..8a74d30bc363 100644 --- a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs +++ b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs @@ -11,6 +11,7 @@ public GivenThatWeWantToPublishIncrementally(ITestOutputHelper log) : base(log) { // During the dogfood, we want the MSBuild server on for build of the pipeline. Not for the tests - it breaks outputs. Environment.SetEnvironmentVariable("DOTNET_CLI_USE_MSBUILD_SERVER", "0"); + Environment.SetEnvironmentVariable("MSBUILDUSESERVER", "0"); } [Fact] From 3dc49cf3d4b538afd93f0858160d1a5385e0753b Mon Sep 17 00:00:00 2001 From: Tomas Bartonek Date: Mon, 22 Sep 2025 17:44:47 +0200 Subject: [PATCH 7/8] Remove MSBUILDUSESERVER variable in constructor --- .../GivenThatWeWantToPublishIncrementally.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs index 8a74d30bc363..a874abd2848a 100644 --- a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs +++ b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishIncrementally.cs @@ -11,7 +11,6 @@ public GivenThatWeWantToPublishIncrementally(ITestOutputHelper log) : base(log) { // During the dogfood, we want the MSBuild server on for build of the pipeline. Not for the tests - it breaks outputs. Environment.SetEnvironmentVariable("DOTNET_CLI_USE_MSBUILD_SERVER", "0"); - Environment.SetEnvironmentVariable("MSBUILDUSESERVER", "0"); } [Fact] From 5af53ff8598810b3c7aa634238e8dfbf1fd5c155 Mon Sep 17 00:00:00 2001 From: SimaTian Date: Mon, 22 Sep 2025 18:30:33 +0200 Subject: [PATCH 8/8] disable tl, enable server for Evaluation Tests --- .../Build/EvaluationTests.cs | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/test/dotnet-watch.Tests/Build/EvaluationTests.cs b/test/dotnet-watch.Tests/Build/EvaluationTests.cs index ab1bf7f833fc..649723625ca8 100644 --- a/test/dotnet-watch.Tests/Build/EvaluationTests.cs +++ b/test/dotnet-watch.Tests/Build/EvaluationTests.cs @@ -3,24 +3,14 @@ using System.Diagnostics; using System.Text.RegularExpressions; +using Microsoft.VisualStudio.TestPlatform.Utilities; namespace Microsoft.DotNet.Watch.UnitTests { - public class EvaluationTests + public class EvaluationTests(ITestOutputHelper output) { - private readonly TestLogger _logger; - private readonly TestAssetsManager _testAssets; - private readonly ITestOutputHelper output; - - public EvaluationTests(ITestOutputHelper output) - { - _logger = new TestLogger(output); - _testAssets = new TestAssetsManager(output); - this.output = output; - - // During the dogfood, we want the MSBuild server on for build of the pipeline. Not for the tests - it breaks outputs. - Environment.SetEnvironmentVariable("DOTNET_CLI_USE_MSBUILD_SERVER", "0"); - } + private readonly TestLogger _logger = new TestLogger(output); + private readonly TestAssetsManager _testAssets = new TestAssetsManager(output); private static string MuxerPath => TestContext.Current.ToolsetUnderTest.DotNetHostPath; @@ -442,11 +432,10 @@ public async Task ProjectReferences_Graph() var processRunner = new ProcessRunner(processCleanupTimeout: TimeSpan.Zero); var buildReporter = new BuildReporter(_logger, new GlobalOptions(), options); - var filesetFactory = new MSBuildFileSetFactory(projectA, buildArguments: ["/p:_DotNetWatchTraceOutput=true"], processRunner, buildReporter); + var filesetFactory = new MSBuildFileSetFactory(projectA, buildArguments: ["/p:_DotNetWatchTraceOutput=true", "/tl:Off"], processRunner, buildReporter); var result = await filesetFactory.TryCreateAsync(requireProjectGraph: null, CancellationToken.None); Assert.NotNull(result); - AssertEx.SequenceEqual( [ "A/A.cs: [A/A.csproj]", @@ -502,10 +491,9 @@ public async Task MsbuildOutput() var processRunner = new ProcessRunner(processCleanupTimeout: TimeSpan.Zero); var buildReporter = new BuildReporter(_logger, new GlobalOptions(), options); - var factory = new MSBuildFileSetFactory(project1Path, buildArguments: ["/interactive:False"], processRunner, buildReporter); + var factory = new MSBuildFileSetFactory(project1Path, buildArguments: ["/tl:Off"], processRunner, buildReporter); var result = await factory.TryCreateAsync(requireProjectGraph: null, CancellationToken.None); Assert.Null(result); - // note: msbuild prints errors to stdout, we match the pattern and report as error: AssertEx.Equal( $"[Error] {project1Path} : error NU1201: Project Project2 is not compatible with net462 (.NETFramework,Version=v4.6.2). Project Project2 supports: netstandard2.1 (.NETStandard,Version=v2.1)",