摘要
基于.NET Framework 4.8.1的传统ASP.NET Web程序,使用Gitlab Runner自动集成,在发布的网站目录下,没有bin\Roslyn文件夹。这里涉及到容易被忽视的Roslyn编译器的知识点。
Roslyn是什么?
在我们的ASP.NET Web项目源代码中有什么体现?
1、web.config下有配置节点
一般在web.config末尾能看到如下配置。
<configuration>
………………
<system.codedom>
<compilers>
<!-- For Roslyn -->
<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\"Web\" /optionInfer+" />
</compilers>
</system.codedom>
</configuration>
上边需要注意最新的包的版本号,目前是4.1.0.0最新。
2、Web项目需要引用两个包
<Project ToolsVersion="12.0" DefaultTargets="Build" Sdk="Microsoft.NET.Sdk.Web" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" Version="4.1.0" />
<PackageReference Include="Microsoft.Net.Compilers" Version="4.2.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
Microsoft.CodeDom.Providers.DotNetCompilerPlatform包和嵌入的文件
Microsoft.Net.Compilers包和嵌入的文件
在MSBuild过程中,Roslyn要做什么?
在我给msbuild.exe带上/v:diag后,得到了详细的日志:
PS:Gitlab Runner控制台的日志超过了4M默认大小,最后修改了Gitlab Runner的日志限制为8M,才得到了如下珍贵的内容。
……………………省略……………………
WebProjectOutputDir = X:\gitlab-runner\builds\01\nxx6sgtBR\0\loda.framework.erp\framework\passport\单点登录系统\Yee.Passport.Web
WebProjectOutputDirInsideProject = True
WebProjectOutputDirInsideProjectDefault = True
……………………省略……………………
标“CopyRoslynCompilerFilesToOutputDirectory: (目标 ID: 725)”(目标“PrepareForRun”依赖于它):
任务“Copy” (任务 ID: 612)
任务参数:DestinationFolder=X:\gitlab-runner\builds\01\nxx6sgtBR\0\loda.framework.erp\framework\passport\单点登录系统\Yee.Passport.Web\bin\roslyn (任务 ID: 612)
任务参数:SkipUnchangedFiles=True (任务 ID: 612)
任务参数:
SourceFiles=
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\csc.exe
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\csc.exe.config
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\csc.rsp
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\csi.exe
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\csi.exe.config
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\csi.rsp
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\Microsoft.Build.Tasks.CodeAnalysis.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\Microsoft.CodeAnalysis.CSharp.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\Microsoft.CodeAnalysis.CSharp.Scripting.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\Microsoft.CodeAnalysis.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\Microsoft.CodeAnalysis.Scripting.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\Microsoft.CodeAnalysis.VisualBasic.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\Microsoft.CSharp.Core.targets
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\Microsoft.DiaSymReader.Native.amd64.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\Microsoft.DiaSymReader.Native.x86.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\Microsoft.Managed.Core.CurrentVersions.targets
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\Microsoft.Managed.Core.targets
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\Microsoft.VisualBasic.Core.targets
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\System.Buffers.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\System.Collections.Immutable.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\System.Memory.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\System.Numerics.Vectors.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\System.Reflection.Metadata.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\System.Runtime.CompilerServices.Unsafe.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\System.Text.Encoding.CodePages.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\System.Threading.Tasks.Extensions.dll
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\vbc.exe
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\vbc.exe.config
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\vbc.rsp
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\VBCSCompiler.exe
C:\Users\loda\.nuget\packages\microsoft.codedom.providers.dotnetcompilerplatform\4.1.0\tools\roslyn-4.1.0\VBCSCompiler.exe.config (任务 ID: 612)
任务参数:Retries=0 (任务 ID: 612)
正在创建目录“X:\gitlab-runner\builds\01\nxx6sgtBR\0\loda.framework.erp\framework\passport\单点登录系统\Yee.Passport.Web\bin\roslyn”。 (任务 ID: 612)
上述日志是关键的内容,有两个看点:
- WebProjectOutputDir没有使用我在msbuild.exe传入的参数 /p:WebProjectOutputDir=$web_output_path
很奇怪,网站的确发布到了msbuild.exe指定的WebProjectOutputDir目录下。 - Roslyn工作正常,只是把产物拷贝到了解决方案之内,Gitlab Runner去了接下来的stage发布网站,是找不到上一个stage的目录下的文件的。
解决办法
在.csproj的Project定义一个自定义复制的任务:
<Target Name="CopyRoslynCompilerFilesToOutputDirectory2" AfterTargets="_CopyWebApplication">
<ItemGroup>
<RoslynFiles Include="$(CscToolPath)\*" />
</ItemGroup>
<PropertyGroup>
<!--<LodaRoslynFolder>$(WebProjectOutputDir)\bin\roslyn</LodaRoslynFolder>-->
</PropertyGroup>
<MakeDir Directories="$(WebProjectOutputDir)\bin\roslyn" />
<Copy SourceFiles="@(RoslynFiles)" DestinationFolder="$(WebProjectOutputDir)\bin\roslyn" SkipUnchangedFiles="true" Retries="$(CopyRetryCount)" RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)" />
</Target>
上边的配置的看点是AfterTargets="_CopyWebApplication",之所以设置在“_CopyWebApplication”这个Target之后,是我发现msbuild.exe最终把网站发布到了我指定的WebProjectOutputDir。因此_CopyWebApplication这个Target之后,WebProjectOutputDir这个参数是正常采用了msbuild.exe中接收到的参数。
至于Roslyn工作的时候,为什么日志里清晰的表明WebProjectOutputDir不采用msbuild.exe接收的参数呢?暂时没时间去查文档了。
后记
折腾了接近2天,写出来让大家少走弯路。已经很少有基于.NET Framework的项目还要老树发新枝了吧?
黑夜里不停折腾的代码行者。