From 3438ee5255421dfb3cbdb00a2e655b524f1d2ade Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Mon, 5 May 2025 12:24:25 +0200 Subject: [PATCH 1/7] Test toolset package --- .../RoslynBuildTaskTests.cs | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs b/test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs index a665a7e8c697..984e5b65a723 100644 --- a/test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs +++ b/test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Reflection; using System.Runtime.CompilerServices; using Basic.CompilerLog.Util; using Microsoft.Build.Logging.StructuredLogger; +using Microsoft.CodeAnalysis; namespace Microsoft.NET.Build.Tests; @@ -51,6 +53,14 @@ public void FullMSBuild_NonSdkStyle(bool useSharedCompilation, Language language VerifyCompiler(buildCommand, FxCompilerFileName(language), useSharedCompilation); } + [FullMSBuildOnlyTheory, CombinatorialData] + public void FullMSBuild_SdkStyle_ToolsetPackage(bool useSharedCompilation, Language language) + { + var testAsset = CreateProject(useSharedCompilation, language, AddCompilersToolsetPackage); + var buildCommand = BuildAndRunUsingMSBuild(testAsset); + VerifyCompiler(buildCommand, CoreCompilerFileName(language), useSharedCompilation, toolsetPackage: true); + } + [Theory, CombinatorialData] public void DotNet(bool useSharedCompilation, Language language) { @@ -59,6 +69,14 @@ public void DotNet(bool useSharedCompilation, Language language) VerifyCompiler(buildCommand, CoreCompilerFileName(language), useSharedCompilation); } + [Theory, CombinatorialData] + public void DotNet_ToolsetPackage(bool useSharedCompilation, Language language) + { + var testAsset = CreateProject(useSharedCompilation, language, AddCompilersToolsetPackage); + var buildCommand = BuildAndRunUsingDotNet(testAsset); + VerifyCompiler(buildCommand, CoreCompilerFileName(language), useSharedCompilation, toolsetPackage: true); + } + private TestAsset CreateProject(bool useSharedCompilation, Language language, Action? configure = null, [CallerMemberName] string callingMethod = "") { var (projExtension, sourceName, sourceText) = language switch @@ -102,6 +120,13 @@ End Module return _testAssetsManager.CreateTestProject(project, callingMethod: callingMethod, targetExtension: projExtension); } + private static void AddCompilersToolsetPackage(TestProject project) + { + string roslynVersion = typeof(Compilation).Assembly.GetCustomAttribute()!.InformationalVersion.Split('+')[0]; + Assert.False(string.IsNullOrEmpty(roslynVersion)); + project.PackageReferences.Add(new TestPackageReference("Microsoft.Net.Compilers.Toolset", roslynVersion)); + } + private TestCommand BuildAndRunUsingMSBuild(TestAsset testAsset) { var buildCommand = new MSBuildCommand(testAsset, "Build"); @@ -130,13 +155,23 @@ private void Run(FileInfo outputFile) .And.HaveStdOut("42"); } - private static void VerifyCompiler(TestCommand buildCommand, string compilerFileName, bool usedCompilerServer) + private static void VerifyCompiler(TestCommand buildCommand, string compilerFileName, bool usedCompilerServer, bool toolsetPackage = false) { var binaryLogPath = Path.Join(buildCommand.WorkingDirectory, "msbuild.binlog"); using (var reader = BinaryLogReader.Create(binaryLogPath)) { var call = reader.ReadAllCompilerCalls().Should().ContainSingle().Subject; Path.GetFileName(call.CompilerFilePath).Should().Be(compilerFileName); + + const string toolsetPackageName = "Microsoft.Net.Compilers.Toolset"; + if (toolsetPackage) + { + call.CompilerFilePath.Should().Contain(toolsetPackageName); + } + else + { + call.CompilerFilePath.Should().NotContain(toolsetPackageName); + } } // Verify compiler server message. From 392aaac3ef8c06c068e1921991890a77d9b9fc9c Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Mon, 5 May 2025 12:24:47 +0200 Subject: [PATCH 2/7] Make sure toolset package is preferred --- .../targets/Microsoft.NET.Sdk.BeforeCommon.targets | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets index 6f90f3514f0b..44a0d46ebbf1 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets @@ -333,7 +333,9 @@ Copyright (c) .NET Foundation. All rights reserved. - + + $(MSBuildThisFileDirectory)..\..\..\Roslyn $(MSBuildThisFileDirectory)..\..\..\Roslyn\binfx $(MSBuildThisFileDirectory)..\..\..\Roslyn\Microsoft.CSharp.Core.targets From 38118acbc106e70dfa2f91f3146402c685a59d84 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Wed, 7 May 2025 10:53:46 +0200 Subject: [PATCH 3/7] Fix casing --- test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs b/test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs index 984e5b65a723..1fd1a09fb950 100644 --- a/test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs +++ b/test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs @@ -163,7 +163,7 @@ private static void VerifyCompiler(TestCommand buildCommand, string compilerFile var call = reader.ReadAllCompilerCalls().Should().ContainSingle().Subject; Path.GetFileName(call.CompilerFilePath).Should().Be(compilerFileName); - const string toolsetPackageName = "Microsoft.Net.Compilers.Toolset"; + const string toolsetPackageName = "microsoft.net.compilers.toolset"; if (toolsetPackage) { call.CompilerFilePath.Should().Contain(toolsetPackageName); From 22a480f41ffa655e1021114d3ecdfbeb858c4cdd Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Mon, 12 May 2025 13:43:20 +0200 Subject: [PATCH 4/7] Fix test --- test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs b/test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs index 1fd1a09fb950..4ee32f04fb5d 100644 --- a/test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs +++ b/test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs @@ -58,7 +58,7 @@ public void FullMSBuild_SdkStyle_ToolsetPackage(bool useSharedCompilation, Langu { var testAsset = CreateProject(useSharedCompilation, language, AddCompilersToolsetPackage); var buildCommand = BuildAndRunUsingMSBuild(testAsset); - VerifyCompiler(buildCommand, CoreCompilerFileName(language), useSharedCompilation, toolsetPackage: true); + VerifyCompiler(buildCommand, FxCompilerFileName(language), useSharedCompilation, toolsetPackage: true); } [Theory, CombinatorialData] From 5bb20f8eef59d2479b3973ba8d8289e1c3a59512 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Thu, 19 Jun 2025 11:33:27 +0200 Subject: [PATCH 5/7] Handle RoslynCompilerType=Custom --- .../general/decouple-vs-and-net-sdk.md | 18 ++++++++++++------ .../Microsoft.NET.Sdk.BeforeCommon.targets | 4 +--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/documentation/general/decouple-vs-and-net-sdk.md b/documentation/general/decouple-vs-and-net-sdk.md index 3391718ced75..b35340930cad 100644 --- a/documentation/general/decouple-vs-and-net-sdk.md +++ b/documentation/general/decouple-vs-and-net-sdk.md @@ -119,12 +119,6 @@ Solutions that mix .NET SDK and Visual Studio projects will end up with multiple The compiler will offer a property that allows SDK projects to use the MSBuild version of the compiler when being built with `msbuild`: `Framework`. This can be added to a `Directory.Build.props` file to impact the entire solution. This is not expected to be a common scenario but is available for customers who need it. This property will be ignored when using `dotnet build` as there is no way to fall back to the Visual Studio compiler in that scenario. -> [!NOTE] -> These values are recognized for property `RoslynCompilerType`: -> - `Core`: use the compiler that comes with the .NET SDK -> - `Framework`: use the compiler that comes with .NET Framework MSBuild -> - `FrameworkPackage`: download the Microsoft.Net.Sdk.Compilers.Toolset package which contains the .NET Framework compiler corresponding to the .NET SDK version - ### .NET Framework based analyzers There are a few analyzers which are built against .NET Framework TFMs. That means when loaded in a .NET Core compiler it could lead to compatibility issues. This is not expected to be a significant issue as our processes have been pushing customers to target `netstandard` in analyzers for 5+ years. However it is possible that some customers will run into issues here. @@ -137,6 +131,17 @@ Today there is not a 100% reliable way to shutdown the VBCSCompiler process. The To mitigate this we will be fixing the `build-server shutdown` command to be reliable across all the scenarios we care about. The details of this are captured in [issue 45956](https://github.com/dotnet/sdk/issues/45956). +## RoslynCompilerType + +Based on the value of the `RoslynCompilerType` property, the SDK sets property `RoslynTasksAssembly` to a full path to a [Roslyn build task DLL][roslyn-build-task], +and the SDK targets use `$(RoslynTasksAssembly)` to load the build task. + +These values are recognized for property `RoslynCompilerType`: +- `Core`: use the compiler that comes with the .NET SDK +- `Framework`: use the compiler that comes with .NET Framework MSBuild +- `FrameworkPackage`: download the Microsoft.Net.Sdk.Compilers.Toolset package which contains the .NET Framework compiler corresponding to the .NET SDK version +- `Custom`: the SDK will not override `RoslynTasksAssembly` - used for example by Microsoft.Net.Compilers.Toolset package which injects its own version of the build task + ## Alternative ### Make the compiler in Visual Studio pluggable @@ -189,6 +194,7 @@ There is only one version of the DevKit extension. It is released using the late [matrix-of-paine]: https://aka.ms/dotnet/matrixofpaine [sdk-lifecycle]: https://learn.microsoft.com/en-us/dotnet/core/porting/versioning-sdk-msbuild-vs#lifecycle [code-razor-vs-load]: https://github.com/dotnet/roslyn/blob/9aea80927e3d4e5a2846efaa710438c0d8d2bfa2/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProject.cs#L1009 +[roslyn-build-task]: https://github.com/dotnet/roslyn/blob/ccb05769e5298ac23c01b33a180a0b3715f53a18/src/Compilers/Core/MSBuildTask/README.md [setup-dotnet]: https://github.com/actions/setup-dotnet [pr-detect-torn-state]: https://github.com/dotnet/installer/pull/19144 [issue-analyzer-mt]: https://github.com/dotnet/sdk/issues/20355 diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets index 44a0d46ebbf1..6f90f3514f0b 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets @@ -333,9 +333,7 @@ Copyright (c) .NET Foundation. All rights reserved. - - + $(MSBuildThisFileDirectory)..\..\..\Roslyn $(MSBuildThisFileDirectory)..\..\..\Roslyn\binfx $(MSBuildThisFileDirectory)..\..\..\Roslyn\Microsoft.CSharp.Core.targets From f0caed8c45fa5204a110dfd72d2c2ce576cb6c99 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Thu, 19 Jun 2025 11:40:51 +0200 Subject: [PATCH 6/7] Fixup an outdated comment --- .../Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets index 18f5dbf30a99..64787353cf57 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets @@ -222,7 +222,7 @@ Copyright (c) .NET Foundation. All rights reserved. - From 812d3a64cf20e826744cdd8ff05376e054875235 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Fri, 20 Jun 2025 11:44:52 +0200 Subject: [PATCH 7/7] Mention RoslynTargetsPath --- documentation/general/decouple-vs-and-net-sdk.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/documentation/general/decouple-vs-and-net-sdk.md b/documentation/general/decouple-vs-and-net-sdk.md index b35340930cad..7a2964fd48e6 100644 --- a/documentation/general/decouple-vs-and-net-sdk.md +++ b/documentation/general/decouple-vs-and-net-sdk.md @@ -136,6 +136,9 @@ To mitigate this we will be fixing the `build-server shutdown` command to be rel Based on the value of the `RoslynCompilerType` property, the SDK sets property `RoslynTasksAssembly` to a full path to a [Roslyn build task DLL][roslyn-build-task], and the SDK targets use `$(RoslynTasksAssembly)` to load the build task. +The SDK also sets `RoslynTargetsPath` to the directory path of the roslyn tasks assembly. This property is used by some targets +but it should be avoided if possible because the tasks assembly name can change as well, not just the directory path. + These values are recognized for property `RoslynCompilerType`: - `Core`: use the compiler that comes with the .NET SDK - `Framework`: use the compiler that comes with .NET Framework MSBuild