-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
Version Used:
5.6.0-2.26152.102
Steps to Reproduce:
- Create a project that uses Roslyn. The contents of
.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis" Version="5.6.0-2.26152.102" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="5.6.0-2.26152.102" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="5.6.0-2.26152.102" />
<PackageReference Include="Microsoft.Build" Version="18.1.1-preview-25556-03" />
</ItemGroup>
</Project>
- Add the following to
Program.cs:
using Microsoft.Build.Logging;
using Microsoft.CodeAnalysis.MSBuild;
string projPath = "D:\\TestProj\\TestProj\\TestProj.csproj";
var props = new Dictionary<string, string>()
{
{ "Platform", "AnyCPU"},
{ "Configuration", "Debug"},
{ "AlwaysCompileMarkupFilesInSeparateDomain", "False"},
{ "SolutionDir", "D:\\TestProj\\SlnFolder"},
{ "SolutionName", "TestProj"},
{ "SolutionPath", "D:\\TestProj\\SlnFolder\\TestProj.sln"},
};
var binaryLogger = new BinaryLogger();
binaryLogger.CollectProjectImports = BinaryLogger.ProjectImportsCollectionMode.Embed;
binaryLogger.Parameters = "D:\\log.binlog";
var workspace = MSBuildWorkspace.Create(props);
await workspace.OpenProjectAsync(projPath, binaryLogger);
binaryLogger.Shutdown();
- Create a test console project under .NET 6 in the
D:\TestProj\TestProj\TestProj.csprojdirectory. The contents of.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
</Project>
-
Create a solution at the path:
D:\TestProj\SlnFolder\TestProj.sln. Add the test project to the solution. -
Add
global.jsonto theD:\TestProj\SlnFoldersolution directory. The contents ofglobal.json:
{
"sdk": {
"version": "6.0.100",
"rollForward": "latestFeature"
}
}
-
Build the solution (from the solution directory) using
dotnet build -bl. The machine being tested is expected to have a newer .NET version in addition to .NET 6 (for example, .NET 10). This should result in a binary log from the build. -
Run the project that uses Roslyn. The result should be binary logs for the project located at
D:\TestProj\TestProj\TestProj.csproj.
Expected Behavior:
Both when building a solution using dotnet and when using workspace.OpenProjectAsync (since workspace contains information about which solution the project belongs to), global.json is considered.
Actual Behavior:
global.json is considered when building the solution using dotnet, but it is ignored when opening the project via workspace.OpenProjectAsync (the workspace contains information about which solution the project belongs to). To see this, we can compare the binary logs obtained during compilation and when running the project that uses Roslyn. For example, during compilation, the value of the MSBuildExtensionsPath environment variable is C:\Program Files\dotnet\sdk\6.0.100. When using Roslyn, the value is C:\Program Files\dotnet\sdk\10.0.103\. Also, during compilation and when using Roslyn, targets are taken from C:\Program Files\dotnet\sdk\6.0.100 and C:\Program Files\dotnet\sdk\10.0.103 respectively.
Note that when using the OpenSolutionAsync method instead of OpenProjectAsync, global.json is also ignored.
If global.json is placed at the project level (D:\TestProj\TestProj), and the project is then re-run via Roslyn, binary logs are similar to those obtained when building via dotnet. The most likely reason for this is that global.json is searched for relative to the current working directory. Apparently, when a project is analyzed using Roslyn, the current working directory is the directory of the project being analyzed. In our case, this is D:\TestProj\TestProj.
Could you please explain why there is a difference in the way global.json is considered when compiling via dotnet and when using Roslyn?
Is there a way to consider global.json that is not located in the project directory or one of its subdirectories, but is located next to the solution to which the project belongs? Provided that when workspace.OpenProjectAsync is called, the workspace contains information that the project belongs to the specific solution.