剪裁选项

本文中所述的 MSBuild 属性和项会影响剪裁的自包含部署的行为。 一些选项提及 ILLink,这是实现剪裁的基础工具的名称。 有关基础工具的详细信息,请参阅剪裁器文档

.NET Core 3.0 中引入了 PublishTrimmed 剪裁功能。 其他选项在 .NET 5 及更高版本中可用。

启用剪裁

  • <PublishTrimmed>true</PublishTrimmed>

    在发布期间启用剪裁。 此设置还会关闭剪裁不兼容的功能,并在生成期间启用 剪裁分析 。 在 .NET 8 及更高版本中,此设置还启用配置绑定和请求委托源生成器。

注意

如果将剪裁指定为从命令行启用,调试体验将有所不同,并且可能会在最终产品中遇到其他 bug。

将此设置放入项目文件中,以确保不只是在 dotnet publish 期间,在 dotnet build 期间也会应用该设置。

此设置默认启用剪裁和剪裁所有程序集。 在 .NET 6 中,默认仅剪裁了选择通过 [AssemblyMetadata("IsTrimmable", "True")] 剪裁的程序集(在设置 <IsTrimmable>true</IsTrimmable>的项目中添加)。 可以使用 <TrimMode>partial</TrimMode> 返回到之前的行为。

此设置剪裁已配置用于剪裁的所有程序集。 在 .NET 6 的 Microsoft.NET.Sdk 中,将剪裁具有 [AssemblyMetadata("IsTrimmable", "True")] 的所有程序集,.NET 运行时程序集就是这种情况。 在 .NET 5 中,netcoreapp 运行时包中的程序集配置为通过 <IsTrimmable> MSBuild 元数据进行剪裁。 其他 SDK 可能定义不同的默认值。

此设置还启用兼容剪裁的 Roslyn 分析器,并禁用不兼容剪裁的功能

剪裁粒度

使用 TrimMode 属性将剪裁粒度设置为 partialfull。 控制台应用(从 .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 的程序集将使用全局 TrimModeMicrosoft.NET.Sdk 的默认 TrimMode 在 .NET 6+ 中为 link,在先前版本中为 copyused

剪裁其他程序集

在 .NET 6+ 中,PublishTrimmed 使用以下程序集级别的属性剪裁程序集:

[AssemblyMetadata("IsTrimmable", "True")]

框架库具有此属性。 在 .NET 6+ 中,还可选择按名称指定程序集(不带 .dll 扩展名),在不使用此属性的情况下对库进行剪裁。

单个程序集的剪裁设置

发布剪裁后的应用时,SDK 将计算名为 ManagedAssemblyToLinkItemGroup,这表示要进行剪裁处理的文件集。 ManagedAssemblyToLink 可能具有用于控制每个程序集的剪裁行为的元数据。 若要设置此元数据,请在内置的 PrepareForILLink 目标运行之前创建一个目标。 下面的示例演示如何启用 MyAssembly 的剪裁。

<Target Name="ConfigureTrimming"
        BeforeTargets="PrepareForILLink">
  <ItemGroup>
    <ManagedAssemblyToLink Condition="'%(Filename)' == 'MyAssembly'">
      <IsTrimmable>true</IsTrimmable>
    </ManagedAssemblyToLink>
  </ItemGroup>
</Target>

还可以使用此目标通过设置 <IsTrimmable>false</IsTrimmable> 程序集 [AssemblyMetadata("IsTrimmable", "True"])来替代库作者指定的修整行为。

请勿添加或删除 ManagedAssemblyToLink项,因为 SDK 会在发布期间计算此集,并期望它不会更改。 支持的元数据为:

  • <IsTrimmable>true</IsTrimmable>

    控制是否剪裁给定的程序集。

  • <TrimMode>copyused</TrimMode><TrimMode>link</TrimMode>

    控制此程序集的剪裁粒度。 此元数据优先于全局 TrimMode元数据。 在程序集上设置 TrimMode 意味着 <IsTrimmable>true</IsTrimmable>

  • <TrimmerSingleWarn>True</TrimmerSingleWarn>

    控制是否显示此程序集的单个警告

根程序集

如果未修整程序集,则它被视为“rooted”,这意味着将保留它及其所有静态理解的依赖项。 其他程序集可以按名称“rooted”(没有 .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 属性来取消单个警告代码,包括 NoWarnWarningsAsErrorsWarningsNotAsErrorsTreatWarningsAsErrors。 有一个附加选项可以独立控制 ILLink 警告错误行为:

  • <ILLinkTreatWarningsAsErrors>false</ILLinkTreatWarningsAsErrors>

    请勿将 ILLink 警告视为错误。 这可能有助于避免在全局将编译器警告视为错误时将剪裁分析警告转换为错误。

显示详细警告

在 .NET 6 及更高版本中,对于来自 PackageReference 的每个程序集,剪裁分析最多为其生成一个警告,以指示程序集的内部机制与剪裁功能不兼容。 你还可显示所有程序集的各个警告:

  • <TrimmerSingleWarn>false</TrimmerSingleWarn>

    显示所有详细警告,而不是将其折叠为每个程序集的单个警告。

删除符号

通常会对符号进行剪裁,以匹配剪裁的程序集。 还可以删除所有符号:

  • <TrimmerRemoveSymbols>true</TrimmerRemoveSymbols>

    删除剪裁后的应用程序中的符号,包括嵌入的 PDB 和单独的 PDB 文件。 这同时适用于应用程序代码以及符号附带的任何依赖项。

SDK 还可使用属性 DebuggerSupport 来禁用调试器支持。 禁用调试器支持后,剪裁会自动删除符号(TrimmerRemoveSymbols 默认为 true)。

剪裁框架库功能

框架库的一些功能区域随附有剪裁器指令,这些剪裁器指令可以删除已禁用功能的代码。

MSBuild 属性 说明
AutoreleasePoolSupport 设置为 false时,删除在受支持的平台上创建 自动发布池 的代码。 false 是 .NET SDK 的默认值。
DebuggerSupport 设置为 false时,删除支持更好的调试体验的代码。 此设置还会删除符号
EnableUnsafeBinaryFormatterSerialization 设置为 false时,删除 BinaryFormatter 序列化支持。 有关详细信息,请参阅 BinaryFormatter 序列化方法已过时并且已删除内置 BinaryFormatter 实现,并且始终引发
EnableUnsafeUTF7Encoding 设置为 false后,删除不安全的 UTF-7 编码代码。 有关详细信息,请参阅 UTF-7 代码路径已过时
EventSourceSupport 设置为 false时,删除与 EventSource 相关的代码和逻辑。
HttpActivityPropagationSupport 设置为 false时,删除与诊断支持 System.Net.Http相关的代码。
InvariantGlobalization 设置为 true时,删除特定于全球化的代码和数据。 有关详细信息,请参阅固定模式
MetadataUpdaterSupport 设置为 “ false设置为”时,删除与热重载相关的元数据更新特定逻辑。
MetricsSupport 设置为 false时,删除对检测的支持 System.Diagnostics.Metrics
StackTraceSupport (.NET 8+) 设置为 false时,删除运行时生成堆栈跟踪(例如或 Environment.StackTrace Exception.ToString)的支持。 从堆栈跟踪字符串中删除的信息量可能取决于其他部署选项。 此选项不会影响调试器生成的堆栈跟踪。
UseNativeHttpHandler 设置为 true时,使用 Android 和 iOS 的默认平台实现 HttpMessageHandler 并删除托管实现。
UseSystemResourceKeys 设置为 true时,将去除程序集的 System.* 异常消息。 从 System.* 程序集引发异常时,该消息是简化的资源 ID,而不是完整消息。
XmlResolverIsNetworkingEnabledByDefault (.NET 8+) 设置为 false时,将删除对解析非文件 URL System.Xml的支持。 仅支持文件系统解析。

这些属性将导致剪裁相关代码,同时还将通过 runtimeconfig 文件禁用功能。 有关这些属性(包括相应的 runtimeconfig 选项)的详细信息,请参阅功能切换。 某些 SDK 可能具有这些属性的默认值。

剪裁时禁用的框架功能

以下功能与剪裁不兼容,因为它们需要不静态引用的代码。 默认情况下,在剪裁的应用中禁用这些功能。

警告

启用这些功能的风险由你自担。 这些功能可能会中断经过裁剪的应用,且不会执行任何操作来保留动态引用的代码。

  • <BuiltInComInteropSupport>

    内置的 COM 支持已禁用。

  • <CustomResourceTypesSupport>

    不支持使用自定义资源类型。 剪裁使用自定义资源类型的反射的 ResourceManager 代码路径。

  • <EnableCppCLIHostActivation>

    C++/CLI 主机激活已禁用。

  • <EnableUnsafeBinaryFormatterInDesigntimeLicenseContextSerialization>

    禁止 DesigntimeLicenseContextSerializer 使用 BinaryFormatter 序列化。

  • <StartupHookSupport>

    不支持之前MainDOTNET_STARTUP_HOOKS运行代码。 有关详细信息,请参阅主机启动挂钩