From f68b96105781740cd4769c94da2ddbad11a2529e Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Fri, 22 Aug 2025 12:16:43 +0200 Subject: [PATCH 1/6] Set RoslynAssemblies --- .../general/decouple-vs-and-net-sdk.md | 6 ++-- .../Microsoft.NET.Sdk.BeforeCommon.targets | 4 +++ .../ValidatePackageTargetIntegrationTests.cs | 30 +++++++++---------- .../PackageValidationTestProject.csproj | 15 ---------- .../PackageValidationTestProject/Program.cs | 4 +-- 5 files changed, 25 insertions(+), 34 deletions(-) diff --git a/documentation/general/decouple-vs-and-net-sdk.md b/documentation/general/decouple-vs-and-net-sdk.md index 7a2964fd48e6..b96d34951610 100644 --- a/documentation/general/decouple-vs-and-net-sdk.md +++ b/documentation/general/decouple-vs-and-net-sdk.md @@ -136,8 +136,10 @@ 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. +The SDK also sets the following properties: +- `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. +- `RoslynAssemblies` to the directory path of other roslyn assemblies (like `Microsoft.CodeAnalysis.dll`). These values are recognized for property `RoslynCompilerType`: - `Core`: use the compiler that comes with the .NET SDK 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 0b94c1b0cbb5..3341b3e0d8e9 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 @@ -337,8 +337,12 @@ Copyright (c) .NET Foundation. All rights reserved. + + $(RoslynTargetsPath) + $(MSBuildThisFileDirectory)..\..\..\Roslyn $(MSBuildThisFileDirectory)..\..\..\Roslyn\Microsoft.Build.Tasks.CodeAnalysis.dll + $(MSBuildThisFileDirectory)..\..\..\Roslyn\bincore $(MSBuildThisFileDirectory)..\..\..\Roslyn\binfx $(MSBuildThisFileDirectory)..\..\..\Roslyn\binfx\Microsoft.Build.Tasks.CodeAnalysis.Sdk.dll $(MSBuildThisFileDirectory)..\..\..\Roslyn\Microsoft.CSharp.Core.targets diff --git a/test/Microsoft.DotNet.ApiCompat.IntegrationTests/Task/ValidatePackageTargetIntegrationTests.cs b/test/Microsoft.DotNet.ApiCompat.IntegrationTests/Task/ValidatePackageTargetIntegrationTests.cs index c7e8afadb6ba..7459ba14f702 100644 --- a/test/Microsoft.DotNet.ApiCompat.IntegrationTests/Task/ValidatePackageTargetIntegrationTests.cs +++ b/test/Microsoft.DotNet.ApiCompat.IntegrationTests/Task/ValidatePackageTargetIntegrationTests.cs @@ -34,7 +34,7 @@ public ValidatePackageTargetIntegrationTests(ITestOutputHelper log) : base(log) return (log, validator); } - [RequiresMSBuildVersionFact("17.0.0.32901", Skip = "https://github.com/dotnet/sdk/issues/23533")] + [RequiresMSBuildVersionFact("17.0.0.32901")] public void InvalidPackage() { var testAsset = _testAssetsManager @@ -46,10 +46,10 @@ public void InvalidPackage() // No failures while running the package validation on a simple assembly. Assert.Equal(1, result.ExitCode); - Assert.Contains("error CP0002: Member 'PackageValidationTestProject.Program.SomeAPINotIn6_0()' exists on lib/netstandard2.0/PackageValidationTestProject.dll but not on lib/net6.0/PackageValidationTestProject.dll", result.StdOut); + Assert.Contains("error CP0002: Member 'void PackageValidationTestProject.Program.SomeAPINotInCore()' exists on lib/netstandard2.0/PackageValidationTestProject.dll but not on lib/net8.0/PackageValidationTestProject.dll", result.StdOut); } - [RequiresMSBuildVersionFact("17.0.0.32901", Skip = "https://github.com/dotnet/sdk/issues/23533")] + [RequiresMSBuildVersionFact("17.0.0.32901")] public void ValidatePackageTargetRunsSuccessfully() { var testAsset = _testAssetsManager @@ -63,7 +63,7 @@ public void ValidatePackageTargetRunsSuccessfully() Assert.Equal(0, result.ExitCode); } - [RequiresMSBuildVersionFact("17.0.0.32901", Skip = "https://github.com/dotnet/sdk/issues/23533")] + [RequiresMSBuildVersionFact("17.0.0.32901")] public void ValidatePackageTargetRunsSuccessfullyWithBaselineCheck() { var testAsset = _testAssetsManager @@ -83,7 +83,7 @@ public void ValidatePackageTargetRunsSuccessfullyWithBaselineCheck() Assert.Equal(0, result.ExitCode); } - [RequiresMSBuildVersionFact("17.0.0.32901", Skip = "https://github.com/dotnet/sdk/issues/23533")] + [RequiresMSBuildVersionFact("17.0.0.32901")] public void ValidatePackageTargetRunsSuccessfullyWithBaselineVersion() { var testAsset = _testAssetsManager @@ -102,7 +102,7 @@ public void ValidatePackageTargetRunsSuccessfullyWithBaselineVersion() Assert.Equal(0, result.ExitCode); } - [RequiresMSBuildVersionFact("17.0.0.32901", Skip = "https://github.com/dotnet/sdk/issues/23533")] + [RequiresMSBuildVersionFact("17.0.0.32901")] public void ValidatePackageTargetFailsWithBaselineVersion() { var testAsset = _testAssetsManager @@ -119,11 +119,11 @@ public void ValidatePackageTargetFailsWithBaselineVersion() .Execute($"-p:PackageVersion=2.0.0;AddBreakingChange=true;PackageValidationBaselinePath={packageValidationBaselinePath}"); Assert.Equal(1, result.ExitCode); - Assert.Contains("error CP0002: Member 'PackageValidationTestProject.Program.SomeApiNotInLatestVersion()' exists on [Baseline] lib/net6.0/PackageValidationTestProject.dll but not on lib/net6.0/PackageValidationTestProject.dll", result.StdOut); - Assert.Contains("error CP0002: Member 'PackageValidationTestProject.Program.SomeApiNotInLatestVersion()' exists on [Baseline] lib/netstandard2.0/PackageValidationTestProject.dll but not on lib/netstandard2.0/PackageValidationTestProject.dll", result.StdOut); + Assert.Contains("error CP0002: Member 'void PackageValidationTestProject.Program.SomeApiNotInLatestVersion()' exists on [Baseline] lib/net8.0/PackageValidationTestProject.dll but not on lib/net8.0/PackageValidationTestProject.dll", result.StdOut); + Assert.Contains("error CP0002: Member 'void PackageValidationTestProject.Program.SomeApiNotInLatestVersion()' exists on [Baseline] lib/netstandard2.0/PackageValidationTestProject.dll but not on lib/netstandard2.0/PackageValidationTestProject.dll", result.StdOut); } - [RequiresMSBuildVersionFact("17.0.0.32901", Skip = "https://github.com/dotnet/sdk/issues/23533")] + [RequiresMSBuildVersionFact("17.0.0.32901")] public void ValidatePackageTargetWithIncorrectBaselinePackagePath() { var testAsset = _testAssetsManager @@ -291,7 +291,7 @@ public void ValidateMissingReferencesIsOnlyLoggedWhenRunningWithReferences(bool Assert.Contains(log.warnings, e => e.Contains("CP1003")); } - [RequiresMSBuildVersionFact("17.0.0.32901", Skip = "https://github.com/dotnet/sdk/issues/23533")] + [RequiresMSBuildVersionFact("17.0.0.32901")] public void ValidateReferencesAreRespectedForPlatformSpecificTFMs() { TestProject testProject = CreateTestProject("public class MyType { }", $"netstandard2.0;{ToolsetInfo.CurrentTargetFramework}-windows"); @@ -310,10 +310,10 @@ public void ValidateReferencesAreRespectedForPlatformSpecificTFMs() validator.Validate(new PackageValidatorOption(package)); - Assert.Contains(log.warnings, e => e.Contains("CP1003")); + Assert.DoesNotContain(log.warnings, e => e.Contains("CP1003")); } - [RequiresMSBuildVersionFact("17.0.0.32901", Skip = "https://github.com/dotnet/sdk/issues/23533")] + [RequiresMSBuildVersionFact("17.0.0.32901")] public void ValidatePackageTargetFailsWithBaselineVersionInStrictMode() { var testAsset = _testAssetsManager @@ -330,11 +330,11 @@ public void ValidatePackageTargetFailsWithBaselineVersionInStrictMode() .Execute($"-p:PackageVersion=2.0.0;ForceStrictModeBaselineValidationProblem=true;EnableStrictModeForBaselineValidation=true;PackageValidationBaselinePath={packageValidationBaselinePath}"); Assert.Equal(1, result.ExitCode); - Assert.Contains("error CP0002: Member 'PackageValidationTestProject.Program.SomeApiOnlyInLatestVersion()' exists on lib/net6.0/PackageValidationTestProject.dll but not on [Baseline] lib/net6.0/PackageValidationTestProject.dll", result.StdOut); - Assert.Contains("error CP0002: Member 'PackageValidationTestProject.Program.SomeApiOnlyInLatestVersion()' exists on lib/netstandard2.0/PackageValidationTestProject.dll but not on [Baseline] lib/netstandard2.0/PackageValidationTestProject.dll", result.StdOut); + Assert.Contains("error CP0002: Member 'void PackageValidationTestProject.Program.SomeApiOnlyInLatestVersion()' exists on lib/net8.0/PackageValidationTestProject.dll but not on [Baseline] lib/net8.0/PackageValidationTestProject.dll", result.StdOut); + Assert.Contains("error CP0002: Member 'void PackageValidationTestProject.Program.SomeApiOnlyInLatestVersion()' exists on lib/netstandard2.0/PackageValidationTestProject.dll but not on [Baseline] lib/netstandard2.0/PackageValidationTestProject.dll", result.StdOut); } - [RequiresMSBuildVersionFact("17.0.0.32901", Skip = "https://github.com/dotnet/sdk/issues/23533")] + [RequiresMSBuildVersionFact("17.0.0.32901")] public void ValidatePackageTargetSucceedsWithBaselineVersionNotInStrictMode() { var testAsset = _testAssetsManager diff --git a/test/TestAssets/TestProjects/PackageValidationTestProject/PackageValidationTestProject.csproj b/test/TestAssets/TestProjects/PackageValidationTestProject/PackageValidationTestProject.csproj index 4f9495839fb5..279dd07c1ff1 100644 --- a/test/TestAssets/TestProjects/PackageValidationTestProject/PackageValidationTestProject.csproj +++ b/test/TestAssets/TestProjects/PackageValidationTestProject/PackageValidationTestProject.csproj @@ -9,19 +9,4 @@ true - - - - - - - - - - - - $(MSBuildThisFileDirectory)\bin\$(Configuration)\net472\Microsoft.DotNet.ApiCompat.Task.dll - $(MSBuildThisFileDirectory)\bin\$(Configuration)\net8.0\Microsoft.DotNet.ApiCompat.Task.dll - - diff --git a/test/TestAssets/TestProjects/PackageValidationTestProject/Program.cs b/test/TestAssets/TestProjects/PackageValidationTestProject/Program.cs index 3806ca1e6cd6..6280820fbd15 100644 --- a/test/TestAssets/TestProjects/PackageValidationTestProject/Program.cs +++ b/test/TestAssets/TestProjects/PackageValidationTestProject/Program.cs @@ -7,8 +7,8 @@ namespace PackageValidationTestProject { public class Program { -#if ForceValidationProblem && !NET6_0 - public void SomeAPINotIn6_0() +#if ForceValidationProblem && !NET + public void SomeAPINotInCore() { } #endif From 3ff3e766836244907c599f269dd752b566dee8b2 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Fri, 22 Aug 2025 13:12:31 +0200 Subject: [PATCH 2/6] Clarify docs --- documentation/general/decouple-vs-and-net-sdk.md | 1 + 1 file changed, 1 insertion(+) diff --git a/documentation/general/decouple-vs-and-net-sdk.md b/documentation/general/decouple-vs-and-net-sdk.md index b96d34951610..b4343ed17473 100644 --- a/documentation/general/decouple-vs-and-net-sdk.md +++ b/documentation/general/decouple-vs-and-net-sdk.md @@ -140,6 +140,7 @@ The SDK also sets the following properties: - `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. - `RoslynAssemblies` to the directory path of other roslyn assemblies (like `Microsoft.CodeAnalysis.dll`). + In builds using .NET Framework MSBuild, the path is set to the Roslyn directory that ships with MSBuild (no .NET Framework Roslyn assemblies ship with the .NET SDK). These values are recognized for property `RoslynCompilerType`: - `Core`: use the compiler that comes with the .NET SDK From 61a1e92b300daa4b509a98775d4ce3f4a2c78531 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Fri, 22 Aug 2025 16:17:55 +0200 Subject: [PATCH 3/6] Allow users to customize RoslynAssembliesPath --- documentation/general/decouple-vs-and-net-sdk.md | 2 +- .../targets/Microsoft.NET.Sdk.BeforeCommon.targets | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/general/decouple-vs-and-net-sdk.md b/documentation/general/decouple-vs-and-net-sdk.md index b4343ed17473..4c9037c3760f 100644 --- a/documentation/general/decouple-vs-and-net-sdk.md +++ b/documentation/general/decouple-vs-and-net-sdk.md @@ -139,7 +139,7 @@ and the SDK targets use `$(RoslynTasksAssembly)` to load the build task. The SDK also sets the following properties: - `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. -- `RoslynAssemblies` to the directory path of other roslyn assemblies (like `Microsoft.CodeAnalysis.dll`). +- `RoslynAssembliesPath` to the directory path of other roslyn assemblies (like `Microsoft.CodeAnalysis.dll`). In builds using .NET Framework MSBuild, the path is set to the Roslyn directory that ships with MSBuild (no .NET Framework Roslyn assemblies ship with the .NET SDK). These values are recognized for property `RoslynCompilerType`: 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 3341b3e0d8e9..69258b30e87c 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 @@ -338,11 +338,11 @@ Copyright (c) .NET Foundation. All rights reserved. - $(RoslynTargetsPath) + $(RoslynTargetsPath) $(MSBuildThisFileDirectory)..\..\..\Roslyn $(MSBuildThisFileDirectory)..\..\..\Roslyn\Microsoft.Build.Tasks.CodeAnalysis.dll - $(MSBuildThisFileDirectory)..\..\..\Roslyn\bincore + $(MSBuildThisFileDirectory)..\..\..\Roslyn\bincore $(MSBuildThisFileDirectory)..\..\..\Roslyn\binfx $(MSBuildThisFileDirectory)..\..\..\Roslyn\binfx\Microsoft.Build.Tasks.CodeAnalysis.Sdk.dll $(MSBuildThisFileDirectory)..\..\..\Roslyn\Microsoft.CSharp.Core.targets From a7716b2bdb546d07a4d98c9641430d4c01417036 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Mon, 25 Aug 2025 11:13:49 +0200 Subject: [PATCH 4/6] Set the property even for framework --- .../targets/Microsoft.NET.Sdk.BeforeCommon.targets | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 69258b30e87c..f051df623644 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 @@ -336,10 +336,12 @@ Copyright (c) .NET Foundation. All rights reserved. - + + $(RoslynTargetsPath) - + + $(MSBuildThisFileDirectory)..\..\..\Roslyn $(MSBuildThisFileDirectory)..\..\..\Roslyn\Microsoft.Build.Tasks.CodeAnalysis.dll $(MSBuildThisFileDirectory)..\..\..\Roslyn\bincore From 84534d57b0ef7707289834818f0e2da41dc9b77a Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Wed, 3 Sep 2025 09:09:17 +0200 Subject: [PATCH 5/6] Add RoslynCoreAssembliesPath --- documentation/general/decouple-vs-and-net-sdk.md | 9 +++++---- .../targets/Microsoft.NET.Sdk.BeforeCommon.targets | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/documentation/general/decouple-vs-and-net-sdk.md b/documentation/general/decouple-vs-and-net-sdk.md index 4c9037c3760f..2bb5e3f937e9 100644 --- a/documentation/general/decouple-vs-and-net-sdk.md +++ b/documentation/general/decouple-vs-and-net-sdk.md @@ -133,14 +133,15 @@ To mitigate this we will be fixing the `build-server shutdown` command to be rel ## 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. - -The SDK also sets the following properties: +Based on the value of the `RoslynCompilerType` property, the SDK (or compiler toolset packages) set the following properties: +- `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 - `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. + This property is a misnomer for historical reasons, it really points to _tasks_, there is no guarantee there will be any _targets_ in the directory. - `RoslynAssembliesPath` to the directory path of other roslyn assemblies (like `Microsoft.CodeAnalysis.dll`). In builds using .NET Framework MSBuild, the path is set to the Roslyn directory that ships with MSBuild (no .NET Framework Roslyn assemblies ship with the .NET SDK). +- `RoslynCoreAssembliesPath` to the directory path of other roslyn assemblies which target .NET Core regardless of the host being .NET Framework or Core MSBuild. These values are recognized for property `RoslynCompilerType`: - `Core`: use the compiler that comes with the .NET SDK 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 f051df623644..5f2c95dbb560 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 @@ -340,11 +340,12 @@ Copyright (c) .NET Foundation. All rights reserved. $(RoslynTargetsPath) + $(MSBuildThisFileDirectory)..\..\..\Roslyn\bincore $(MSBuildThisFileDirectory)..\..\..\Roslyn $(MSBuildThisFileDirectory)..\..\..\Roslyn\Microsoft.Build.Tasks.CodeAnalysis.dll - $(MSBuildThisFileDirectory)..\..\..\Roslyn\bincore + $(RoslynCoreAssembliesPath) $(MSBuildThisFileDirectory)..\..\..\Roslyn\binfx $(MSBuildThisFileDirectory)..\..\..\Roslyn\binfx\Microsoft.Build.Tasks.CodeAnalysis.Sdk.dll $(MSBuildThisFileDirectory)..\..\..\Roslyn\Microsoft.CSharp.Core.targets From 7fa322822707626c2614d035e031f90b477013a1 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Wed, 3 Sep 2025 09:12:46 +0200 Subject: [PATCH 6/6] Clarify another part of the docs --- documentation/general/decouple-vs-and-net-sdk.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/general/decouple-vs-and-net-sdk.md b/documentation/general/decouple-vs-and-net-sdk.md index 2bb5e3f937e9..ff77240fc4e3 100644 --- a/documentation/general/decouple-vs-and-net-sdk.md +++ b/documentation/general/decouple-vs-and-net-sdk.md @@ -147,7 +147,7 @@ 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 +- `Custom`: the SDK will not override `RoslynTasksAssembly` and the other properties listed above - used for example by Microsoft.Net.Compilers.Toolset package which injects its own version of the build task ## Alternative