Fix compiler server on CoreCLR and enable bootstrapping on CoreCLR build#24239
Fix compiler server on CoreCLR and enable bootstrapping on CoreCLR build#24239agocke merged 15 commits intodotnet:dev15.6.xfrom
Conversation
netci.groovy
Outdated
| description("Windows CoreCLR unit tests") | ||
| steps { | ||
| batchFile(""".\\build\\scripts\\cibuild.cmd ${(configuration == 'debug') ? '-debug' : '-release'} -testCoreClr""") | ||
| batchFile("""powershell -noprofile -executionPolicy RemoteSigned -file .\\build\\scripts\\cibuild.cmd ${(configuration == 'debug') ? '-debug' : '-release'} -restore -cibuild -bootstrap -coreClrBuild -testCoreClr -binaryLog""") |
There was a problem hiding this comment.
This looks wrong. It's using powershell to target a CMD file. Not sure why we'd change this to use powershell here in any case.
There was a problem hiding this comment.
Yeah this should have been build.ps1. The problem is that cibuild.cmd passes the -build arg, which I made incompatible with -coreClrBuild. Would you prefer that both flags are required, and coreClrBuild just forces coreclr instead of desktop?
There was a problem hiding this comment.
I would do the following:
- Rename
-coreClrBuildto-buildCoreClr. - Allow mixing of
-buildand-buildCoreClr. Would actually set-buildto true if-buildCoreClris true inProcess-Arguments
This would give -buildCoreClr a lot of symetry with -buildAll
There was a problem hiding this comment.
The reason I didn't do that is because, unlike buildAll, this doesn't build the same stuff as -build (it only builds Compilers.sln). Is that still OK?
|
|
||
| <PropertyGroup> | ||
| <!-- Don't use the compiler server by default in the NuGet package. --> | ||
| <UseSharedCompilation Condition="'$(UseSharedCompilation)' == ''">false</UseSharedCompilation> |
There was a problem hiding this comment.
Why are we making this change? We made this "true" by default in the NuGet package in response to customer feedback here around performance.
There was a problem hiding this comment.
I don't think that's true -- this matches the desktop behavior as far as I can see.
There was a problem hiding this comment.
Any projects using the "new" project format will have UseSharedCompilation set to true by default: https://github.com/dotnet/sdk/blob/8a24663345cc5952062cb898431dbd8800b4da85/src/Tasks/Microsoft.NET.Build.Tasks/build/Microsoft.NET.Sdk.targets#L428
There was a problem hiding this comment.
I'm not sure why the line above says "in Visual Studio" -- this applies to the NuGet package.
There was a problem hiding this comment.
@tannergooding That line won't be evaluated until after we evaluate this property if the package is installed via NuGet.
There was a problem hiding this comment.
Yes, but this line will prevent the compiler server from being used on new SDK which has a different default from Desktop.
There was a problem hiding this comment.
@tannergooding The same property is set on Desktop:
build/scripts/build.ps1
Outdated
| } | ||
|
|
||
| if ($build -and $coreClrBuild) | ||
| { |
There was a problem hiding this comment.
Powershell braces start on same line as previous construct.
build/scripts/build.ps1
Outdated
| Move-Item "$configDir\Exes\Toolset\*" $dir | ||
| if ($coreClrBuild) { | ||
| $bootstrapFramework = "netcoreapp2.0" | ||
| Exec-Console "dotnet" "publish --no-restore src/Compilers/CSharp/csc -o `"$dir/bincore`" --framework $bootstrapFramework $bootstrapArgs -bl:$binariesDir/BootstrapCsc.binlog" |
There was a problem hiding this comment.
Log files should go into Binaries\Logs
| } | ||
| } | ||
|
|
||
|
|
|
@jaredpar Can you take another look at this? I think I've addressed your comments. |
| { | ||
| // CoreCLR doesn't have these APIs, so we just have to rely on | ||
| // Windows ACLs for security | ||
| return true; |
There was a problem hiding this comment.
Unfortunately at this point on CoreClr we don't have ACLs
https://github.com/dotnet/corefx/issues/24040
This means we no longer have ACLs or identity verification.
build/scripts/build.ps1
Outdated
| Exec-Console "dotnet" "publish --no-restore src/Compilers/VisualBasic/vbc -o `"$dir/bincore`" --framework $bootstrapFramework $bootstrapArgs -bl:$logDir/BootstrapVbc.binlog" | ||
| Exec-Console "dotnet" "publish --no-restore src/Compilers/Server/VBCSCompiler -o `"$dir/bincore`" --framework $bootstrapFramework $bootstrapArgs -bl:$logDir/BootstrapVBCSCompiler.binlog" | ||
| Exec-Console "dotnet" "publish --no-restore src/Compilers/Core/MSBuildTask -o `"$dir`" $bootstrapArgs -bl:$binariesDir/BootstrapMSBuildTask.binlog" | ||
| Exec-Console "dotnet" "$dir/bincore/VBCSCompiler.dll" -shutdown |
There was a problem hiding this comment.
exec is not really supported, AFAIK. The official guidance is just to pass the DLL as an argument.
build/scripts/build.ps1
Outdated
| function Build-Artifacts() { | ||
| if ($build) { | ||
| if ($buildCoreClr) | ||
| { |
build/scripts/build.ps1
Outdated
| } | ||
|
|
||
| if ($build -or $pack) { | ||
| if ($build -or $buildCoreClr -or $pack) { |
There was a problem hiding this comment.
I think we should be consistent with $buildAll here. Inside Process-Arguments we should set $build to $true if $buildCoreClr is also $true.
build/scripts/build.ps1
Outdated
| $args += " $projectFilePath" | ||
| Exec-Console $msbuild $args | ||
|
|
||
| if ($useDotnetBuild) |
There was a problem hiding this comment.
Braces same line in powershell
| Exec-Console "dotnet" "publish --no-restore src/Compilers/CSharp/csc -o `"$dir/bincore`" --framework $bootstrapFramework $bootstrapArgs -bl:$logDir/BootstrapCsc.binlog" | ||
| Exec-Console "dotnet" "publish --no-restore src/Compilers/VisualBasic/vbc -o `"$dir/bincore`" --framework $bootstrapFramework $bootstrapArgs -bl:$logDir/BootstrapVbc.binlog" | ||
| Exec-Console "dotnet" "publish --no-restore src/Compilers/Server/VBCSCompiler -o `"$dir/bincore`" --framework $bootstrapFramework $bootstrapArgs -bl:$logDir/BootstrapVBCSCompiler.binlog" | ||
| Exec-Console "dotnet" "publish --no-restore src/Compilers/Core/MSBuildTask -o `"$dir`" $bootstrapArgs -bl:$binariesDir/BootstrapMSBuildTask.binlog" |
There was a problem hiding this comment.
Why aren't we killing the server here
There was a problem hiding this comment.
No server to kill. The server can't be used via NuGet package until this is merged :)
There was a problem hiding this comment.
But once this is merged will need to kill the server. I would add back the kill and just catch the failure condition.
There was a problem hiding this comment.
Added Stop-BuildProcesses at the end here, so when this works we'll be all set.
There was a problem hiding this comment.
@agocke Don't you want to do it at the beginning in case there is detritus from a previous run? Imagine somebody running this script locally to test changes.
There was a problem hiding this comment.
I believe that's the purpose of the call in the try-finally at the top-level.
Certain dependent assemblies (System.IO.Pipes, System.IO.Pipes.AccessControl) are operating system dependent and thus end up in the runtimes subdirectory next to the build task. Unfortunately, there is no mechanism for automatic assembly resolution of plugin DLLs like MSBuild tasks, so we have to implement something similar ourselves. This change hooks assembly resolution and, when we see a well-known DLL request, we redirect it to the appropriate path.
38b64e6 to
34ed6fc
Compare
| <UseSharedCompilation>false</UseSharedCompilation> | ||
| <!-- Older versions of the CLI didn't set the DOTNET_HOST_PATH variable, which | ||
| means we have to use our shell wrappers and hope 'dotnet' is on the path. --> | ||
| <PropertyGroup Condition="'$(DOTNET_HOST_PATH)' == ''"> |
There was a problem hiding this comment.
Can we file an issue to track deleting this? Once we get past 2.1 we should no longer support this case.
There was a problem hiding this comment.
I think we'll have to support installing newer compilers on older runtimes for quite a while, no? Is there any reason not to support that, if this is the only complexity?
There was a problem hiding this comment.
I didn't think it was possible at all in older CLI. Could be wrong.
| Condition="'$(BuildingProject)' == 'true' AND '$(OS)' != 'Windows_NT'" | ||
| Condition="'$(BuildingProject)' == 'true' AND | ||
| '$(OS)' != 'Windows_NT' AND | ||
| '$(CscToolPath)' != ''" |
There was a problem hiding this comment.
Don't agree with the CscToolPath condition here. Consider the case where only CscToolPath was set but not VbcToolPath. In that case we still need to make the scripts executable.
build/scripts/build.ps1
Outdated
| [switch]$pack = $false, | ||
| [switch]$binaryLog = $false, | ||
| [string]$signType = "", | ||
| [switch]$buildCoreClr = $false, |
There was a problem hiding this comment.
Please group this with the other build options.
build/scripts/build.ps1
Outdated
| $args += " $projectFilePath" | ||
| Exec-Console $msbuild $args | ||
|
|
||
| if ($useDotnetBuild) |
build/scripts/build.ps1
Outdated
| Exec-Console $dotnet $args | ||
| } | ||
| else | ||
| { |
There was a problem hiding this comment.
Open Braces on same line in powershell.
| } | ||
|
|
||
| private static readonly string s_assemblyLocation = Utilities.TryGetAssemblyPath(typeof(AssemblyResolution).GetTypeInfo().Assembly); | ||
| private static Assembly TryRedirectToRuntimesDir(AssemblyName name) |
There was a problem hiding this comment.
Do we have a bug tracking the undo'ing of this at a later date?
There was a problem hiding this comment.
Will we actually undo it? I'm not sure MSBuild or CoreCLR are going to do anything about this.
There was a problem hiding this comment.
The solution can't be this code though. We need to file a bug with CoreClr to get them to tell us the right way to do this, or provide an assembly load context that has rationale behavior.
There was a problem hiding this comment.
Filed https://github.com/dotnet/coreclr/issues/15982. I'll add a link
| <file src="Dlls/MSbuildTask/netstandard1.3/publish/Microsoft.VisualBasic.Core.targets" target="tools" /> | ||
| <!-- N.B.: The backslashes below cannot be replaced with forward slashes. --> | ||
| <file src="Dlls\MSBuildTask\netstandard1.3\publish\System.*.dll" target="tools" /> | ||
| <file src="Dlls\MSBuildTask\netstandard1.3\publish\runtimes\**" target="tools\runtimes" /> |
There was a problem hiding this comment.
Can we pick \ or / for the slash direction? Don't care which we use, just prefer we use one of them.
There was a problem hiding this comment.
I'm now worried about changing anything here because I have no idea what it will do to the package layout.
| <file src="Exes/VBCSCompiler/netcoreapp2.0/publish/VBCSCompiler.runtimeconfig.json" target="tools/bincore" /> | ||
|
|
||
| <!-- References that are either not in the target framework or are a higher version --> | ||
| <!-- N.B.: The backslashes below cannot be replaced with forward slashes. --> |
There was a problem hiding this comment.
I don't want to ask but I have to ... why?
There was a problem hiding this comment.
It looks like NuGet has different behavior -- the backslashes are interpreted as "everything in this directory" while forward slashes are "the entire directory tree, including parent directories"
build/scripts/build.ps1
Outdated
| function Build-Artifacts() { | ||
| if ($build) { | ||
| if ($buildCoreClr) | ||
| { |
| case "System.Reflection": | ||
| return TryRedirect(name, s_b03f5f7f11d50a3a, 4, 1, 1, 0); | ||
|
|
||
| // Assemblies in the runtimes directory |
There was a problem hiding this comment.
Please expand the comment on why this makes a difference.
| } | ||
|
|
||
| private static readonly string s_assemblyLocation = Utilities.TryGetAssemblyPath(typeof(AssemblyResolution).GetTypeInfo().Assembly); | ||
| private static Assembly TryRedirectToRuntimesDir(AssemblyName name) |
There was a problem hiding this comment.
The solution can't be this code though. We need to file a bug with CoreClr to get them to tell us the right way to do this, or provide an assembly load context that has rationale behavior.
Customer scenario
This PR fixes the CoreCLR compiler server on Windows and changes our bootstrap build to act as a test case. The bug in the compiler server was we were attempting to do user ID verification on CoreCLR on Windows, but those APIs are not available on CoreCLR, so this would always fail. This fix disables user ID verification and relies only on Windows pipe ACLs, which should be enough to ensure that only properly privileged users can connect.
Bugs this fixes
Fixes #20900 and #24072
Workarounds, if any
There are no workarounds for using the compiler server under CoreCLR on Windows.
Risk
This change is substantially similar to what we do on Linux, so has already been given a fair amount of coverage.
Performance impact
This should make the compiler much faster on CoreCLR.
Is this a regression from a previous update?
No.
Root cause analysis
We didn't bootstrap using the compiler server on CoreCLR, which I've now added.
How was the bug found?
Customer reported.