Open jmarolf opened 4 years ago
Example repo: https://github.com/xoofx/RoslynErrorApp
/cc @rainersigwald
From looking at @xoofx repo, The issue is that loading the WorkloadSDKResolver requires System.Runtime 5.0.0.0, but the target framework for the application is netcoreapp3.1. I would expect a different result if the app were targeting net5.0 or rollforward were enabled for it to run on a 5.0 runtime.
to add to this problem, this apparently reproduces in the latest dotnet format
:
> dotnet format -w .\test.csproj -v diag
Using MSBuild.exe located in 'C:\Program Files\dotnet\sdk\5.0.100\'
Formatting code files in workspace 'C:\source\jmarolf\scratch\test\test.csproj'.
Loading workspace.
Msbuild failed when processing the file 'C:\source\jmarolf\scratch\test\test.csproj' with message: The SDK resolver type "WorkloadSdkResolver" failed to load. Could not load file or assembly 'System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified. C:\source\jmarolf\scratch\test\test.csproj
Complete in 1485ms.
Determining formattable files.
Complete in 35ms.
Running formatters.
Complete in 17ms.
Formatted 0 of 0 files.
Format complete in 1542ms.
From looking at @xoofx repo, The issue is that loading the WorkloadSDKResolver requires System.Runtime 5.0.0.0, but the target framework for the application is netcoreapp3.1. I would expect a different result if the app were targeting net5.0 or rollforward were enabled for it to run on a 5.0 runtime.
Indeed, but that's the problem. When you are using a MSBuildWorkspace
, it forces your application to use the same runtime than the SDK currently installed. It makes things very brittle (it fails at runtime if not) and not very practical (you can't create easily a tool that can work on any machine situation across any SDK versions)
Indeed, but that's the problem. When you are using a
MSBuildWorkspace
, it forces your application to use the same runtime than the SDK currently installed.
This is a feature request for MSBuild Locator. Currently it locates a .NET 5 installation of MSBuild even when running on .NET Core 3. The assembly handling would not be required if the correct version of MSBuild was used.
This is a feature request for MSBuild Locator.
Specifically it's microsoft/MSBuildLocator#92.
if the correct version of MSBuild was used
Note though that this is kinda fuzzy. If .NET SDK 5.0.100 is installed and is what would be used to build the projects in question if you went to that directory and did dotnet build
, but the MSBuildWorkspace-using application targets .NET Core 3.1, what is "correct"?
but the MSBuildWorkspace-using application targets .NET Core 3.1, what is "correct"?
.NET Core 3.1 is correct in this case, because it's the most recent one that works.
Not if the project targets .NET 5.0 . . .
But that case would give a nice error message about the current version of MSBuild/SDK not supporting the target framework for the project, as opposed to the error today that just says the runtime can't be found. 😄
Yes, I think it's better than today. Just not "always obviously correct".
In the meantime, I just released a small utility library called Broslyn to workaround this issue.
@xoofx I keep finding new cases where that seems like the best approach.
@xoofx that is awesome! I feel like there could be a slightly more optimal version of it where it sneaks out the parameters that would have been sent to csc rather than triggering a full build, but as it is today it will be reliable and plenty good for my case 🙂 (Edit: I realize that I'm basically asking for what Buildalyzer does, ignore my second remark)
This is a really important missing feature to the .NET eco-system IMO. I've lost count of how many times this has been needed, here's just one from memory, when using NSwag.MSBuild
, they implemented their own assembly resolution, which as you can imagine is a whole source of bugs.
I have a relatively simple use case today; I want to build a tool that can be integrated into CI that will produce a json file containing all contract definitions for messages consumed and published from a project.
I have built 2 implementations, one using the Roslyn Semantic Model, and the other using MetadataLoadContext
, they work in a controlled environment, but both suffer from the same problem - how do I get the assemblies a project will actually be using?
I need to do a publish, and then figure out the runtime folder, it's buggy and messy. The other option is for me to get the Roslyn Semantic Model by implementing it as a Roslyn Analyzer, and then take a flag to tell me it's a CI build and to write the file (this is so hacky, I actually like it a little!), or do I build it as a msbuild task (which is always more work than I think)?
Ultimately, so many of these problems go away if we are able to point to a csproj and say "What do you have?", and are able to get the data that would be passed to csc, or get a Roslyn Workspace just like Broslyn & Buildalyzer are doing today.
Most tools using
MSBuildWorkspace
eventually need to implement their own assembly resolver that mimics the MSBuild one (like we do here). Either the MSBuild locator class should do this by default or there should be a way forMSBuildWorkspace
to opt into more "loose" assembly loading behavior.