Skip to content

Commit a1f249c

Browse files
authored
Add roslyn compiler toolset tests (#48837)
1 parent 13e31ff commit a1f249c

File tree

3 files changed

+52
-8
lines changed

3 files changed

+52
-8
lines changed

documentation/general/decouple-vs-and-net-sdk.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,6 @@ Solutions that mix .NET SDK and Visual Studio projects will end up with multiple
119119

120120
The compiler will offer a property that allows SDK projects to use the MSBuild version of the compiler when being built with `msbuild`: `<RoslynCompilerType>Framework</RoslynCompilerType>`. 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.
121121

122-
> [!NOTE]
123-
> These values are recognized for property `RoslynCompilerType`:
124-
> - `Core`: use the compiler that comes with the .NET SDK
125-
> - `Framework`: use the compiler that comes with .NET Framework MSBuild
126-
> - `FrameworkPackage`: download the Microsoft.Net.Sdk.Compilers.Toolset package which contains the .NET Framework compiler corresponding to the .NET SDK version
127-
128122
### .NET Framework based analyzers
129123

130124
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,20 @@ Today there is not a 100% reliable way to shutdown the VBCSCompiler process. The
137131

138132
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).
139133

134+
## RoslynCompilerType
135+
136+
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],
137+
and the SDK targets use `$(RoslynTasksAssembly)` to load the build task.
138+
139+
The SDK also sets `RoslynTargetsPath` to the directory path of the roslyn tasks assembly. This property is used by some targets
140+
but it should be avoided if possible because the tasks assembly name can change as well, not just the directory path.
141+
142+
These values are recognized for property `RoslynCompilerType`:
143+
- `Core`: use the compiler that comes with the .NET SDK
144+
- `Framework`: use the compiler that comes with .NET Framework MSBuild
145+
- `FrameworkPackage`: download the Microsoft.Net.Sdk.Compilers.Toolset package which contains the .NET Framework compiler corresponding to the .NET SDK version
146+
- `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
147+
140148
## Alternative
141149

142150
### Make the compiler in Visual Studio pluggable
@@ -189,6 +197,7 @@ There is only one version of the DevKit extension. It is released using the late
189197
[matrix-of-paine]: https://aka.ms/dotnet/matrixofpaine
190198
[sdk-lifecycle]: https://learn.microsoft.com/en-us/dotnet/core/porting/versioning-sdk-msbuild-vs#lifecycle
191199
[code-razor-vs-load]: https://github.com/dotnet/roslyn/blob/9aea80927e3d4e5a2846efaa710438c0d8d2bfa2/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProject.cs#L1009
200+
[roslyn-build-task]: https://github.com/dotnet/roslyn/blob/ccb05769e5298ac23c01b33a180a0b3715f53a18/src/Compilers/Core/MSBuildTask/README.md
192201
[setup-dotnet]: https://github.com/actions/setup-dotnet
193202
[pr-detect-torn-state]: https://github.com/dotnet/installer/pull/19144
194203
[issue-analyzer-mt]: https://github.com/dotnet/sdk/issues/20355

src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ Copyright (c) .NET Foundation. All rights reserved.
222222
</PropertyGroup>
223223

224224
<!-- NOTE: Keep in sync with https://github.com/dotnet/msbuild/blob/main/src/Tasks/Microsoft.Common.tasks -->
225-
<!-- `Condition="Exists('$(RoslynTargetsPath)')` is needed because the package might not be yet downloaded during restore in VS
225+
<!-- `Condition="Exists(...)` is needed because the package might not be yet downloaded during restore in VS
226226
and we do not want to fail the restore phase because of that. -->
227227
<UsingTask TaskName="Microsoft.CodeAnalysis.BuildTasks.CopyRefAssembly" AssemblyFile="$(RoslynTasksAssembly)" Condition="Exists('$(RoslynTasksAssembly)')" />
228228
<UsingTask TaskName="Microsoft.CodeAnalysis.BuildTasks.Csc" AssemblyFile="$(RoslynTasksAssembly)" Condition="Exists('$(RoslynTasksAssembly)')" />

test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Reflection;
45
using System.Runtime.CompilerServices;
56
using Basic.CompilerLog.Util;
67
using Microsoft.Build.Logging.StructuredLogger;
8+
using Microsoft.CodeAnalysis;
79

810
namespace Microsoft.NET.Build.Tests;
911

@@ -51,6 +53,14 @@ public void FullMSBuild_NonSdkStyle(bool useSharedCompilation, Language language
5153
VerifyCompiler(buildCommand, FxCompilerFileName(language), useSharedCompilation);
5254
}
5355

56+
[FullMSBuildOnlyTheory, CombinatorialData]
57+
public void FullMSBuild_SdkStyle_ToolsetPackage(bool useSharedCompilation, Language language)
58+
{
59+
var testAsset = CreateProject(useSharedCompilation, language, AddCompilersToolsetPackage);
60+
var buildCommand = BuildAndRunUsingMSBuild(testAsset);
61+
VerifyCompiler(buildCommand, FxCompilerFileName(language), useSharedCompilation, toolsetPackage: true);
62+
}
63+
5464
[Theory, CombinatorialData]
5565
public void DotNet(bool useSharedCompilation, Language language)
5666
{
@@ -59,6 +69,14 @@ public void DotNet(bool useSharedCompilation, Language language)
5969
VerifyCompiler(buildCommand, CoreCompilerFileName(language), useSharedCompilation);
6070
}
6171

72+
[Theory, CombinatorialData]
73+
public void DotNet_ToolsetPackage(bool useSharedCompilation, Language language)
74+
{
75+
var testAsset = CreateProject(useSharedCompilation, language, AddCompilersToolsetPackage);
76+
var buildCommand = BuildAndRunUsingDotNet(testAsset);
77+
VerifyCompiler(buildCommand, CoreCompilerFileName(language), useSharedCompilation, toolsetPackage: true);
78+
}
79+
6280
private TestAsset CreateProject(bool useSharedCompilation, Language language, Action<TestProject>? configure = null, [CallerMemberName] string callingMethod = "")
6381
{
6482
var (projExtension, sourceName, sourceText) = language switch
@@ -102,6 +120,13 @@ End Module
102120
return _testAssetsManager.CreateTestProject(project, callingMethod: callingMethod, targetExtension: projExtension);
103121
}
104122

123+
private static void AddCompilersToolsetPackage(TestProject project)
124+
{
125+
string roslynVersion = typeof(Compilation).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()!.InformationalVersion.Split('+')[0];
126+
Assert.False(string.IsNullOrEmpty(roslynVersion));
127+
project.PackageReferences.Add(new TestPackageReference("Microsoft.Net.Compilers.Toolset", roslynVersion));
128+
}
129+
105130
private TestCommand BuildAndRunUsingMSBuild(TestAsset testAsset)
106131
{
107132
var buildCommand = new MSBuildCommand(testAsset, "Build");
@@ -130,13 +155,23 @@ private void Run(FileInfo outputFile)
130155
.And.HaveStdOut("42");
131156
}
132157

133-
private static void VerifyCompiler(TestCommand buildCommand, string compilerFileName, bool usedCompilerServer)
158+
private static void VerifyCompiler(TestCommand buildCommand, string compilerFileName, bool usedCompilerServer, bool toolsetPackage = false)
134159
{
135160
var binaryLogPath = Path.Join(buildCommand.WorkingDirectory, "msbuild.binlog");
136161
using (var reader = BinaryLogReader.Create(binaryLogPath))
137162
{
138163
var call = reader.ReadAllCompilerCalls().Should().ContainSingle().Subject;
139164
Path.GetFileName(call.CompilerFilePath).Should().Be(compilerFileName);
165+
166+
const string toolsetPackageName = "microsoft.net.compilers.toolset";
167+
if (toolsetPackage)
168+
{
169+
call.CompilerFilePath.Should().Contain(toolsetPackageName);
170+
}
171+
else
172+
{
173+
call.CompilerFilePath.Should().NotContain(toolsetPackageName);
174+
}
140175
}
141176

142177
// Verify compiler server message.

0 commit comments

Comments
 (0)