剪裁选项
以下 MSBuild 属性和项会影响剪裁的独立部署行为。 一些选项提及 ILLink
,这是实现剪裁的基础工具的名称。 有关基础工具的详细信息,请参阅剪裁器文档。
.NET Core 3.0 中引入了 PublishTrimmed
剪裁功能。 其他选项仅在 .NET 5 及更高版本中可用。
启用剪裁
<PublishTrimmed>true</PublishTrimmed>
在发布期间启用剪裁。 这还会关闭不兼容剪裁的功能,并在生成期间启用剪裁分析。
注意
如果将剪裁指定为从命令行启用,调试体验将有所不同,并且可能会在最终产品中遇到其他 bug。
将此设置放入项目文件中,以确保不只是在 dotnet publish
期间,在 dotnet build
期间也会应用该设置。
此设置启用剪裁,默认情况下会剪裁所有程序集。 在 .NET 6 中,默认情况下,只有选择通过 [AssemblyMetadata("IsTrimmable", "True")]
剪裁的程序集才会进行剪裁。 可以使用 <TrimMode>partial</TrimMode>
返回到之前的行为。
此设置剪裁已配置用于剪裁的所有程序集。 在 .NET 6 的 Microsoft.NET.Sdk
中,将剪裁具有 [AssemblyMetadata("IsTrimmable", "True")]
的所有程序集,.NET 运行时程序集就是这种情况。 在 .NET 5 中,netcoreapp 运行时包中的程序集配置为通过 <IsTrimmable>
MSBuild 元数据进行剪裁。 其他 SDK 可定义不同的默认值。
此设置还启用兼容剪裁的 Roslyn 分析器,并禁用不兼容剪裁的功能。
剪裁粒度
使用 TrimMode
属性将剪裁粒度设置为 partial
或 full
。 控制台应用(从 .NET 8 开始,Web SDK 应用)的默认设置为 full
:
<TrimMode>full</TrimMode>
若要仅剪裁已选择剪裁的程序集,请将该属性设置为 partial
:
<TrimMode>partial</TrimMode>
如果将剪裁模式更改为 partial
, 则可以使用 <TrimmableAssembly>
选择单个程序集进行剪裁。
<ItemGroup>
<TrimmableAssembly Include="MyAssembly" />
</ItemGroup>
这相当于在生成程序集时设置 [AssemblyMetadata("IsTrimmable", "True")]
。
以下粒度设置控制如何丢弃未充分利用的 IL。 可将其设置为影响所有剪裁器输入程序集的属性,或者设置为可替代该属性设置的单个程序集上的元数据。
<TrimMode>link</TrimMode>
启用成员级剪裁,这会从类型中删除未使用的成员。 这是 .NET 6+ 中的默认设置。
<TrimMode>copyused</TrimMode>
启用程序集级剪裁;如果使用程序集的任何部分(以静态理解的方式),则将保留整个程序集。
具有 <IsTrimmable>true</IsTrimmable>
元数据但没有显式 TrimMode
的程序集将使用全局 TrimMode
。 Microsoft.NET.Sdk
的默认 TrimMode
在 .NET 6+ 中为 link
,在先前版本中为 copyused
。
剪裁其他程序集
在 .NET 6+ 中,PublishTrimmed
使用以下程序集级别的属性剪裁程序集:
[AssemblyMetadata("IsTrimmable", "True")]
框架库具有此属性。 在 .NET 6+ 中,还可选择按名称指定程序集(不带 .dll
扩展名),在不使用此属性的情况下对库进行剪裁。
单个程序集的剪裁设置
发布剪裁后的应用时,SDK 将计算名为 ManagedAssemblyToLink
的 ItemGroup
,这表示要进行剪裁处理的文件集。 ManagedAssemblyToLink
可能具有控制每个程序集剪裁行为的元数据。 若要设置此元数据,请在内置的 PrepareForILLink
目标运行之前创建一个目标。 下面的示例演示如何启用 MyAssembly
的剪裁。
<Target Name="ConfigureTrimming"
BeforeTargets="PrepareForILLink">
<ItemGroup>
<ManagedAssemblyToLink Condition="'%(Filename)' == 'MyAssembly'">
<IsTrimmable>true</IsTrimmable>
</ManagedAssemblyToLink>
</ItemGroup>
</Target>
还可为具有 [AssemblyMetadata("IsTrimmable", "True"])
的程序集设置 <IsTrimmable>false</IsTrimmable>
,用它来替代库创建者指定的剪裁行为。
请勿在 ManagedAssemblyToLink
中添加或移除项,因为 SDK 会在发布过程中计算此集,并期望它没有发生更改。 支持的元数据为:
根程序集
如果某个程序集未经剪裁,则将其视为“根”,这意味着将保留它及其所有静态理解的依赖项。 其他程序集的名称可能是根(无 .dll
扩展名):
<ItemGroup>
<TrimmerRootAssembly Include="MyAssembly" />
</ItemGroup>
根描述符
指定分析的根的另一种方法是使用剪裁器描述符格式的 XML 文件。 这使你可以查找特定的成员而非整个程序集。
<ItemGroup>
<TrimmerRootDescriptor Include="MyRoots.xml" />
</ItemGroup>
例如,MyRoots.xml
可能会查找由应用程序动态访问的特定方法:
<linker>
<assembly fullname="MyAssembly">
<type fullname="MyAssembly.MyClass">
<method name="DynamicallyAccessedMethod" />
</type>
</assembly>
</linker>
分析警告
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
启用剪裁分析警告。
剪裁将删除不可静态访问的 IL。 使用反射或其他模式来创建动态依赖项的应用可能会因剪裁而中断。 要警告此类模式,请将 <SuppressTrimAnalysisWarnings>
设置为 false
。 这将包括有关整个应用的警告,其中包括你自己的代码、库代码以及框架代码。
Roslyn 分析器
在 .NET 6 及更高版本中设置 PublishTrimmed
还将启用 Roslyn 分析器,该分析器仅显示有限的一组分析警告。 还可独立于 PublishTrimmed
启用或禁用该分析器。
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
为一部分剪裁分析警告启用 Roslyn 分析器。
禁止显示警告
可以使用工具链遵循的常用 MSBuild 属性来取消单个警告代码,包括 NoWarn
、WarningsAsErrors
、WarningsNotAsErrors
和 TreatWarningsAsErrors
。 还有另一个选项,可单独控制 ILLink 警告即错误的行为:
<ILLinkTreatWarningsAsErrors>false</ILLinkTreatWarningsAsErrors>
请勿将 ILLink 警告视为错误。 在全局将编译器警告视为错误时,这对于避免将剪裁分析警告转换为错误可能很有用。
显示详细警告
在 .NET 6 及更高版本中,对于来自 PackageReference
的每个程序集,剪裁分析最多为其生成一个警告,以指示程序集的内部机制与剪裁功能不兼容。 你还可显示所有程序集的各个警告:
<TrimmerSingleWarn>false</TrimmerSingleWarn>
显示所有详细警告,而不是将其折叠为每个程序集的单个警告。
删除符号
通常会对符号进行剪裁,以匹配剪裁的程序集。 还可以删除所有符号:
<TrimmerRemoveSymbols>true</TrimmerRemoveSymbols>
删除剪裁后的应用程序中的符号,包括嵌入的 PDB 和单独的 PDB 文件。 这同时适用于应用程序代码以及符号附带的任何依赖项。
SDK 还可使用属性 DebuggerSupport
来禁用调试器支持。 禁用调试器支持时,剪裁将自动删除符号(TrimmerRemoveSymbols
将默认为 true)。
剪裁框架库功能
框架库的一些功能区域随附有剪裁器指令,这些剪裁器指令可以删除已禁用功能的代码。
<AutoreleasePoolSupport>false</AutoreleasePoolSupport>
(默认值)删除在支持的平台上创建自动发布池的代码。 请参阅用于托管线程的 AutoreleasePool。 这是 .NET SDK 的默认值。
<DebuggerSupport>false</DebuggerSupport>
删除代码可提供更佳的调试体验。 此设置还会删除符号。
<EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization>
删除 BinaryFormatter 序列化支持。 有关详细信息,请参阅 BinaryFormatter 序列化方法已过时。
<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>
删除不安全的 UTF-7 编码代码。 有关详细信息,请参阅 UTF-7 代码路径已过时。
<EventSourceSupport>false</EventSourceSupport>
删除与 EventSource 相关的代码或逻辑。
<HttpActivityPropagationSupport>false</HttpActivityPropagationSupport>
删除与 System.Net.Http 的诊断支持相关的代码。
<InvariantGlobalization>true</InvariantGlobalization>
删除全球化特定的代码和数据。 有关详细信息,请参阅固定模式。
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
删除与热重载相关的元数据更新特定逻辑。
<StackTraceSupport>false</StackTraceSupport>
(.NET 8+)删除对运行时生成堆栈跟踪(例如,Environment.StackTrace或 Exception.ToString)的支持。 将从堆栈跟踪字符串中删除的信息量可能取决于其他部署选项。 此选项不会影响调试器生成的堆栈跟踪。
<UseNativeHttpHandler>true</UseNativeHttpHandler>
将 HttpMessageHandler 的默认平台实现用于 Android/iOS,并删除托管实现。
<UseSystemResourceKeys>true</UseSystemResourceKeys>
删除
System.*
程序集的异常消息。 当System.*
程序集中引发异常时,该消息将是简化的资源 ID,而不是完整的消息。
这些属性将导致剪裁相关代码,同时还将通过 runtimeconfig 文件禁用功能。 有关这些属性(包括相应的 runtimeconfig 选项)的详细信息,请参阅功能切换。 某些 SDK 可能具有这些属性的默认值。
剪裁时禁用的框架功能
以下功能不兼容剪裁,因为它们需要不以静态方式引用的代码。 这些设置在剪裁应用中默认处于禁用状态。
警告
启用这些功能的风险由你自担。 这些功能可能会中断经过裁剪的应用,且不会执行任何操作来保留动态引用的代码。
<BuiltInComInteropSupport>
内置的 COM 支持已禁用。
<CustomResourceTypesSupport>
不支持使用自定义资源类型。 将裁剪向自定义资源类型应用反射的 ResourceManager 代码路径。
<EnableCppCLIHostActivation>
C++/CLI 主机激活已禁用。
<EnableUnsafeBinaryFormatterInDesigntimeLicenseContextSerialization>
禁止 DesigntimeLicenseContextSerializer 使用
BinaryFormatter
序列化。<StartupHookSupport>
不支持使用
DOTNET_STARTUP_HOOKS
运行Main
之前的代码。 有关详细信息,请参阅主机启动挂钩。
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈