Fix stdlib inconsistency between core and fx compiler#79911
Fix stdlib inconsistency between core and fx compiler#79911jjonescz merged 14 commits intodotnet:mainfrom
Conversation
| } | ||
|
|
||
| [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/79907")] | ||
| public void StdLib() |
There was a problem hiding this comment.
📝 This file contains only moved code (to share it) except this test which is new (and also shared).
| .FirstOrDefault() | ||
| ?? throw new InvalidOperationException("Visual Studio instance not found."); | ||
| return vsInstance.MSBuildPath; | ||
| } |
There was a problem hiding this comment.
📝 This didn't work but all the tests using it were skipped.
Co-authored-by: Joey Robichaud <[email protected]>
|
@jaredpar @RikkiGibson PTAL |
| commandLine.AppendSwitchIfNotNull("/nullable:", Nullable); | ||
| commandLine.AppendWhenTrue("/nosdkpath", _store, nameof(DisableSdkPath)); | ||
|
|
||
| // Pass sdkpath if we are invoking core compiler from framework to preserve the behavior that framework compiler would have. |
There was a problem hiding this comment.
I agree this perfectly preserves the original behavior here where /sdkpath was used whenever we used msbuild. This compiler argument doesn't really make sense in a .NET SDK world though for the following reasons:
- It means that project builds would be different when using
msbuildanddotnet buildbecause the compiler would get meaningfully different build parameters - It means that when we're building .NET Core projects we're giving them an
/sdkpaththat points to .NET Framework assemblies.
I'm wondering if there is a way we can constrain this shim a bit to narrow the impact. Would be nice if we could remove (2).
There was a problem hiding this comment.
To get rid of (1) perhaps we could use RuntimeEnvironment.GetRuntimeDirectory() even on .NET Core, that also points to a directory which contains mscorlib.dll (albeit the core one, not the framework one, so it's still different). Then we could also get rid of the new /sdkpath: option. That might be a different breaking change though (all core msbuild based builds would now reference mscorlib.dll implicitly).
Getting rid of (2) would still be a breaking change though. Let's say I have this project:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<OutputType>Exe</OutputType>
</PropertyGroup>
<Target Name="CustomTarget">
<Csc Sources="File.cs" />
</Target>
</Project>It's a .NET Core project that previously worked and now would be broken.
Btw, if you are building a normal .NET Core app, it should use NoStdLib=true anyway, so mscorlib.dll won't be referenced. I guess the .NET Framework path would still be added to search paths though.
There was a problem hiding this comment.
The cleanest solution might be to close this PR and accept the break :) If we want dotnet build and msbuild to behave in the same way and invoke core compiler by default, it would make sense to say that there will be no implicit reference of framework mscorlib.dll.
There was a problem hiding this comment.
What would a fix for the break look like? Essentially what code snippet would a customer write in order to get this scenario working again? The fear of the full break is this is most likely to impact customers in older project styles. That is where breaks are the most costly.
There was a problem hiding this comment.
They would need to set RoslynCompilerType=Framework (or FrameworkPackage to avoid tearing).
There was a problem hiding this comment.
Okay. Yeah that will work but ideally we're slowly deprecating RoslynCompilerType=Framework over the next few years. Don't want to have any scenarios where we're pushing people to use this while we're deprecating it.
src/Compilers/Core/MSBuildTaskTests/Microsoft.Build.Tasks.CodeAnalysis.UnitTests.csproj
Outdated
Show resolved
Hide resolved
| each error | ||
| -preferreduilang Specify the preferred output language name. | ||
| -nosdkpath Disable searching the default SDK path for standard library assemblies. | ||
| -sdkpath:<path> Location of the .NET Framework SDK directory (mscorlib.dll). |
There was a problem hiding this comment.
| -sdkpath:<path> Location of the .NET Framework SDK directory (mscorlib.dll). | |
| -sdkpath:<path> Path used to search for standard library assemblies |
Wanted to remove the Framework reference here as it's possible in the future we'd use this for .NET SDK as well. Consider for example that the RSP file we're generating for dotnet run app.cs could one day take advantage of this. Intstead of full pathing everything in the RSP it could be relative path + using /sdkpath to control where to look.
Tried to pattern the message no the wording of -nosdkpath
|
@RikkiGibson PTAL |
| protected override void AddResponseFileCommands(CommandLineBuilderExtension commandLine) | ||
| { | ||
| // Pass sdkpath if we are invoking core compiler from framework to preserve the behavior that framework compiler would have. | ||
| // Pass this option only to the built-in compiler (customer-supplied compiler might not support it). |
There was a problem hiding this comment.
I am somewhat confused by this, if user-supplied compiler doesn't respect this option, don't we have a reason to believe their compiler will not behave correctly? So why avoid passing the argument?
There was a problem hiding this comment.
I guess you are right. I was worried about this causing another regression (the custom compiler failing with unknown argument).
| protected override void AddResponseFileCommands(CommandLineBuilderExtension commandLine) | ||
| { | ||
| // Pass sdkpath if we are invoking core compiler from framework to preserve the behavior that framework compiler would have. | ||
| // Pass this option only to the built-in compiler (customer-supplied compiler might not support it). |
| [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/79907")] | ||
| public void StdLib_Csc(bool useSharedCompilation, bool disableSdkPath) | ||
| { | ||
| if (_msbuildExecutable == null) return; |
There was a problem hiding this comment.
Would it be helpful to log that we are essentially skipping the test in this scenario and in similar place in StdLib_Vbc test below?
There was a problem hiding this comment.
We log that in the constructor which runs for each test separately, so the test's log contain the information:
| }); | ||
|
|
||
| [Fact] | ||
| [Fact(Skip = "https://github.com/dotnet/roslyn/issues/79923")] |
There was a problem hiding this comment.
Normally I really do not like to skip tests if it can be avoided, but, it feels like the non-deterministic behavior makes this necessary.
There was a problem hiding this comment.
This test is completly unrelated to this PR and it has not worked for some time but my infra fixes made it actually run in the CI.
Follow up on #79911. Fixes another inconsistency between the core and fx compilers: if the `<Csc>` task is used manually on a C# file which has `using System.Linq;` (for example), the fx compiler handles that fine (because there is `csc.rsp` deployed with it which has a set of default references) whereas the core compiler fails. A real-world use-case can be seen in https://dev.azure.com/devdiv/DevDiv/_git/VS/pullrequest/684436. The fix is to include this default `csc.rsp` in scenarios where we invoke the core compiler on fx msbuild (to avoid a break there). We continue to not include that `csc.rsp` in scenarios where just the core csc is being used (again, to avoid a break in those scenarios).
Resolves #79907.