.NET 6项目Azure DevOps发布--self-contained参数无效及DLL疑问
问题背景
我有一个需要在Azure DevOps构建流水线中构建的.NET 6项目,当前的azure-pipelines.yml配置如下:
trigger: - release/* pool: name: Test variables: solution: 'acoolproject.sln' acoolprojectweb: 'acoolproject.web\\acoolproject.web.csproj' buildPlatform: 'Any CPU' buildConfiguration: 'Release' steps: - task: gitversion/setup@0 inputs: versionSpec: '5.7.0' - task: gitversion/execute@0 inputs: updateAssemblyInfo: true - task: DotNetCoreCLI@2 inputs: command: 'restore' projects: $(solution) feedsToUse: 'select' - task: DotNetCoreCLI@2 inputs: command: 'publish' publishWebProjects: false projects: $(acoolprojectweb) arguments: '-o $(Build.ArtifactStagingDirectory) -c $(buildConfiguration)' zipAfterPublish: false - task: variabledehydration@0 inputs: prefixes: 'GITVERSION,BUILD' outpath: '$(Build.ArtifactStagingDirectory)' - task: PublishBuildArtifacts@1 inputs: PathtoPublish: '$(Build.ArtifactStagingDirectory)' ArtifactName: 'drop' publishLocation: 'Container'
构建产物包含一个runtimes文件夹,体积约170-180MB,远超项目实际大小。
问题1:添加--self-contained false参数后无效果
修改发布任务,添加--self-contained false参数:
- task: DotNetCoreCLI@2 inputs: command: 'publish' publishWebProjects: false projects: $(acoolprojectweb) arguments: '-o $(Build.ArtifactStagingDirectory) -c $(buildConfiguration) --self-contained false' zipAfterPublish: false
但修改后runtimes文件夹仍存在,体积与之前完全一致,为何该参数没有效果?
问题2:指定特定运行时后出现大体积ICU DLL
尝试指定运行时win10-x86并保留--self-contained false:
- task: DotNetCoreCLI@2 inputs: command: 'publish' publishWebProjects: false projects: $(acoolprojectweb) arguments: '-o $(Build.ArtifactStagingDirectory) -c $(buildConfiguration) -r win10-x86 --self-contained false' zipAfterPublish: false
体积有所减小,但项目根目录出现三个大体积DLL:
-a---- 21-05-2023 10:45 28327824 icudt68.dll -a---- 21-05-2023 10:45 2759032 icuin68.dll -a---- 21-05-2023 10:45 1864080 icuuc68.dll
为何会出现这些文件?
关于--self-contained false无效的原因
项目配置覆盖命令行参数
检查acoolproject.web.csproj文件,若其中在<PropertyGroup>里设置了<SelfContained>true</SelfContained>,命令行的--self-contained false会被项目文件的配置覆盖。需删除该配置或改为<SelfContained>false</SelfContained>。依赖项自带原生运行时
如果项目引用的NuGet包(如跨平台库、SQLite/MongoDB等数据库驱动)包含原生运行时,这些包会自带runtimes文件夹存放不同平台的二进制文件。即使是非自包含发布,这些依赖的原生运行时也会被发布出来。
关于ICU DLL出现的原因
ICU(International Components for Unicode)是.NET处理全球化、字符编码、区域设置相关功能的核心组件。当指定具体运行时(如win10-x86)且非自包含发布时,.NET会将对应运行时的ICU原生库复制到输出目录,避免目标环境的.NET运行时缺少或版本不匹配这些库。
移除ICU DLL的方法
若项目不需要全球化相关功能(如仅处理英文、无多区域需求),可在csproj中添加以下配置启用不变全球化模式,从而移除ICU依赖:
<PropertyGroup> <InvariantGlobalization>true</InvariantGlobalization> </PropertyGroup>
该模式会使用简化的全球化实现,同时进一步减小发布体积。
额外优化建议
裁剪无用运行时与代码
在csproj中添加以下配置,指定目标运行时并启用代码裁剪:<PropertyGroup> <RuntimeIdentifiers>win10-x86</RuntimeIdentifiers> <PublishTrimmed>true</PublishTrimmed> </PropertyGroup>PublishTrimmed会移除未被使用的代码和依赖,但需注意:若项目使用反射或动态加载,需配置TrimmerRootAssembly防止必要代码被误删。清理冗余NuGet依赖
使用dotnet list package命令分析项目依赖树,移除不必要的依赖包,避免其引入额外的原生运行时文件。
内容的提问来源于stack exchange,提问作者Ask Sejsbo

