Skip to content

Commit 003b119

Browse files
authored
Update zone pivots for .NET 9 (#43413)
1 parent 1731c3f commit 003b119

26 files changed

+27
-1357
lines changed

docs/core/deploying/trimming/prepare-libraries-for-trimming.md

Lines changed: 8 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -4,46 +4,19 @@ description: Learn how to prepare .NET libraries for trimming.
44
author: sbomer
55
ms.author: svbomer
66
ms.date: 06/12/2023
7-
zone_pivot_groups: dotnet-version
87
---
98

109
# Prepare .NET libraries for trimming
1110

12-
The .NET SDK makes it possible to reduce the size of self-contained apps by [trimming](trim-self-contained.md). Trimming removes unused code from the app and its dependencies. Not all code is compatible with trimming. .NET provides trim analysis warnings to detect patterns that may break trimmed apps. This article:
11+
The .NET SDK makes it possible to reduce the size of self-contained apps by [trimming](trim-self-contained.md). Trimming removes unused code from the app and its dependencies. Not all code is compatible with trimming. .NET provides trim analysis warnings to detect patterns that might break trimmed apps. This article:
1312

1413
* Describes how to prepare libraries for trimming.
1514
* Provides recommendations for [resolving common trimming warnings](#resolve-trim-warnings).
1615

1716
## Prerequisites
1817

19-
:::zone pivot="dotnet-6-0"
20-
21-
[.NET 6 SDK](https://dotnet.microsoft.com/download/dotnet) or later.
22-
23-
To get the most up-to-date trimming warnings and analyzer coverage:
24-
25-
* Install and use the .NET 8 SDK or later.
26-
* Target `net8.0` or later.
27-
28-
:::zone-end
29-
30-
:::zone pivot="dotnet-7-0"
31-
32-
[.NET 7 SDK](https://dotnet.microsoft.com/download/dotnet) or later.
33-
34-
To get the most up-to-date trimming warnings and analyzer coverage:
35-
36-
* Install and use the .NET 8 SDK or later.
37-
* Target `net8.0` or later.
38-
39-
:::zone-end
40-
41-
:::zone pivot="dotnet-8-0"
42-
4318
[.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet) or later.
4419

45-
:::zone-end
46-
4720
## Enable library trim warnings
4821

4922
Trim warnings in a library can be found with either of the following methods:
@@ -93,56 +66,15 @@ To create the trimming test app:
9366

9467
If library targets a TFM that is not trimmable, for example `net472` or `netstandard2.0`, there's no benefit to creating a trimming test app. Trimming is only supported for .NET 6 and later.
9568

96-
:::zone pivot="dotnet-6-0"
97-
98-
* Set `<TrimmerDefaultAction>` to `link`. <!-- only diff with .NET7+ -->
99-
* Add `<PublishTrimmed>true</PublishTrimmed>`.
100-
* Add a reference to the library project with `<ProjectReference Include="/Path/To/YourLibrary.csproj" />`.
101-
* Specify the library as a trimmer root assembly with `<TrimmerRootAssembly Include="YourLibraryName" />`.
102-
* `TrimmerRootAssembly` ensures that every part of the library is analyzed. It tells the trimmer that this assembly is a "root". A "root" assembly means the trimmer analyzes every call in the library and traverses all code paths that originate from that assembly.
103-
104-
:::zone-end
105-
106-
:::zone pivot="dotnet-7-0"
107-
10869
* Add `<PublishTrimmed>true</PublishTrimmed>`.
10970
* Add a reference to the library project with `<ProjectReference Include="/Path/To/YourLibrary.csproj" />`.
11071
* Specify the library as a trimmer root assembly with `<TrimmerRootAssembly Include="YourLibraryName" />`.
11172
* `TrimmerRootAssembly` ensures that every part of the library is analyzed. It tells the trimmer that this assembly is a "root". A "root" assembly means the trimmer analyzes every call in the library and traverses all code paths that originate from that assembly.
11273

113-
:::zone-end
114-
115-
:::zone pivot="dotnet-8-0"
116-
117-
* Add `<PublishTrimmed>true</PublishTrimmed>`.
118-
* Add a reference to the library project with `<ProjectReference Include="/Path/To/YourLibrary.csproj" />`.
119-
* Specify the library as a trimmer root assembly with `<TrimmerRootAssembly Include="YourLibraryName" />`.
120-
* `TrimmerRootAssembly` ensures that every part of the library is analyzed. It tells the trimmer that this assembly is a "root". A "root" assembly means the trimmer analyzes every call in the library and traverses all code paths that originate from that assembly.
121-
122-
:::zone-end
123-
12474
### .csproj file
12575

126-
:::zone pivot="dotnet-6-0"
127-
128-
:::code language="xml" source="~/docs/core/deploying/trimming/snippets/MyTestLib6app/XMLFile1.xml":::
129-
130-
:::zone-end
131-
132-
:::zone pivot="dotnet-7-0"
133-
13476
:::code language="xml" source="~/docs/core/deploying/trimming/snippets/ConsoleApp1/ConsoleApp1.csproj":::
13577

136-
**Note:** In the preceding project file, when using .NET 7, replace `<TargetFramework>net8.0</TargetFramework>` with `<TargetFramework>net7.0</TargetFramework>`.
137-
138-
:::zone-end
139-
140-
:::zone pivot="dotnet-8-0"
141-
142-
:::code language="xml" source="~/docs/core/deploying/trimming/snippets/ConsoleApp1/ConsoleApp1.csproj":::
143-
144-
:::zone-end
145-
14678
Once the project file is updated, run `dotnet publish` with the target [runtime identifier (RID)](../../rid-catalog.md).
14779

14880
```dotnetcli
@@ -151,15 +83,16 @@ dotnet publish -c Release -r <RID>
15183

15284
Follow the preceding pattern for multiple libraries. To see trim analysis warnings for more than one library at a time, add them all to the same project as `ProjectReference` and `TrimmerRootAssembly` items. Adding all the libraries to the same project with `ProjectReference` and `TrimmerRootAssembly` items warns about dependencies if ***any*** of the root libraries use a trim-unfriendly API in a dependency. To see warnings that have to do with only a particular library, reference that library only.
15385

154-
***Note:*** The analysis results depend on the implementation details of the dependencies. Updating to a new version of a dependency may introduce analysis warnings:
86+
> [!NOTE]
87+
> The analysis results depend on the implementation details of the dependencies. Updating to a new version of a dependency might introduce analysis warnings:
15588
15689
* If the new version added non-understood reflection patterns.
15790
* Even if there were no API changes.
15891
* Introducing trim analysis warnings is a breaking change when the library is used with `PublishTrimmed`.
15992

16093
## Resolve trim warnings
16194

162-
The preceding steps produce warnings about code that may cause problems when used in a trimmed app. The following examples show the most common warnings with recommendations for fixing them.
95+
The preceding steps produce warnings about code that might cause problems when used in a trimmed app. The following examples show the most common warnings with recommendations for fixing them.
16396

16497
### RequiresUnreferencedCode
16598

@@ -204,11 +137,11 @@ In this case, the trim analysis keeps public methods of <xref:System.Tuple>, and
204137
* When code is incompatible with trimming, annotate it with `RequiresUnreferencedCode` and propagate this annotation to callers until the relevant public APIs are annotated.
205138
* Avoid using code that uses reflection in a way not understood by the static analysis. For example, reflection in static constructors should be avoided. Using statically unanalyzable reflection in static constructors result in the warning propagating to all members of the class.
206139
* Avoid annotating virtual methods or interface methods. Annotating virtual or interface methods requires all overrides to have matching annotations.
207-
* If an API is mostly trim-incompatible, alternative coding approaches to the API may need to be considered. A common example is reflection-based serializers. In these cases, consider adopting other technology like source generators to produce code that is more easily statically analyzed. For example, see [How to use source generation in System.Text.Json](../../../standard/serialization/system-text-json/source-generation.md)
140+
* If an API is mostly trim-incompatible, alternative coding approaches to the API might need to be considered. A common example is reflection-based serializers. In these cases, consider adopting other technology like source generators to produce code that is more easily statically analyzed. For example, see [How to use source generation in System.Text.Json](../../../standard/serialization/system-text-json/source-generation.md)
208141

209142
## Resolve warnings for non-analyzable patterns
210143

211-
It's better to resolve warnings by expressing the intent of your code using `[RequiresUnreferencedCode]` and `DynamicallyAccessedMembers` when possible. However, in some cases, you may be interested in enabling trimming of a library that uses patterns that can't be expressed with those attributes, or without refactoring existing code. This section describes some advanced ways to resolve trim analysis warnings.
144+
It's better to resolve warnings by expressing the intent of your code using `[RequiresUnreferencedCode]` and `DynamicallyAccessedMembers` when possible. However, in some cases, you might be interested in enabling trimming of a library that uses patterns that can't be expressed with those attributes, or without refactoring existing code. This section describes some advanced ways to resolve trim analysis warnings.
212145

213146
> [!WARNING]
214147
> These techniques might change the behavior or your code or result in run time exceptions if used incorrectly.
@@ -235,7 +168,7 @@ If you're sure that the requirements are met, you can silence this warning by ad
235168

236169
:::code language="csharp" source="~/docs/core/deploying/trimming/snippets/MyLibrary/Class1.cs" id="snippet_AD2" highlight="9-10":::
237170

238-
It's important to underline that it's only valid to suppress a warning if there are annotations or code that ensure the reflected-on members are visible targets of reflection. It isn't sufficient that the member was a target of a call, field or property access. It may appear to be the case sometimes but such code is bound to break eventually as more trimming optimizations are added. Properties, fields, and methods that aren't visible targets of reflection could be inlined, have their names removed, get moved to different types, or otherwise optimized in ways that break reflecting on them. When suppressing a warning, it's only permissible to reflect on targets that were visible targets of reflection to the trimming analyzer elsewhere.
171+
It's important to underline that it's only valid to suppress a warning if there are annotations or code that ensure the reflected-on members are visible targets of reflection. It isn't sufficient that the member was a target of a call, field, or property access. It might appear to be the case sometimes, but such code is bound to break eventually as more trimming optimizations are added. Properties, fields, and methods that aren't visible targets of reflection could be inlined, have their names removed, get moved to different types, or otherwise be optimized in ways that break reflecting on them. When suppressing a warning, it's only permissible to reflect on targets that were visible targets of reflection to the trimming analyzer elsewhere.
239172

240173
:::code language="csharp" source="~/docs/core/deploying/trimming/snippets/MyLibrary/Class1.cs" id="snippet_AD3" highlight="6-8":::
241174

@@ -252,7 +185,7 @@ Without `DynamicDependency`, trimming might remove `Helper` from `MyAssembly` or
252185

253186
The attribute specifies the members to keep via a `string` or via `DynamicallyAccessedMemberTypes`. The type and assembly are either implicit in the attribute context, or explicitly specified in the attribute (by `Type`, or by `string`s for the type and assembly name).
254187

255-
The type and member strings use a variation of the C# documentation comment ID string [format](/dotnet/csharp/language-reference/language-specification/documentation-comments#id-string-format), without the member prefix. The member string shouldn't include the name of the declaring type, and may omit parameters to keep all members of the specified name. Some examples of the format are shown in the following code:
188+
The type and member strings use a variation of the C# documentation comment ID string [format](/dotnet/csharp/language-reference/language-specification/documentation-comments#id-string-format), without the member prefix. The member string shouldn't include the name of the declaring type, and might omit parameters to keep all members of the specified name. Some examples of the format are shown in the following code:
256189

257190
:::code language="csharp" source="~/docs/core/deploying/trimming/snippets/MyLibrary/Class1.cs" id="snippet_AD5":::
258191

docs/core/deploying/trimming/trimming-options.md

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ author: sbomer
55
ms.author: svbomer
66
ms.date: 08/29/2024
77
ms.topic: reference
8-
zone_pivot_groups: dotnet-version
98
---
109

1110
# Trimming options
@@ -25,24 +24,12 @@ Trimming with `PublishTrimmed` was introduced in .NET Core 3.0. The other option
2524
2625
Place this setting in the project file to ensure that the setting applies during `dotnet build`, not just `dotnet publish`.
2726

28-
:::zone pivot="dotnet-8-0,dotnet-7-0"
29-
3027
This setting enables trimming and trims all assemblies by default. In .NET 6, only assemblies that opted-in to trimming via `[AssemblyMetadata("IsTrimmable", "True")]` (added in projects that set `<IsTrimmable>true</IsTrimmable>`) were trimmed by default. You can return to the previous behavior by using `<TrimMode>partial</TrimMode>`.
3128

32-
:::zone-end
33-
34-
:::zone pivot="dotnet-6-0"
35-
36-
This setting trims any assemblies that have been configured for trimming. With `Microsoft.NET.Sdk` in .NET 6, this includes any assemblies with `[AssemblyMetadata("IsTrimmable", "True")]`, which is the case for the .NET runtime assemblies. In .NET 5, assemblies from the netcoreapp runtime pack are configured for trimming via `<IsTrimmable>` MSBuild metadata. Other SDKs might define different defaults.
37-
38-
:::zone-end
39-
4029
This setting also enables the trim-compatibility [Roslyn analyzer](#roslyn-analyzer) and disables [features that are incompatible with trimming](#framework-features-disabled-when-trimming).
4130

4231
## Trimming granularity
4332

44-
:::zone pivot="dotnet-8-0,dotnet-7-0"
45-
4633
Use the `TrimMode` property to set the trimming granularity to either `partial` or `full`. The default setting for console apps (and, starting in .NET 8, Web SDK apps) is `full`:
4734

4835
```xml
@@ -65,65 +52,6 @@ If you change the trim mode to `partial`, you can opt-in individual assemblies t
6552

6653
This is equivalent to setting `[AssemblyMetadata("IsTrimmable", "True")]` when building the assembly.
6754

68-
:::zone-end
69-
70-
:::zone pivot="dotnet-6-0"
71-
72-
The following granularity settings control how aggressively unused IL is discarded. This can be set as a property affecting all trimmer input assemblies, or as metadata on an [individual assembly](#trimming-settings-for-individual-assemblies), which overrides the property setting.
73-
74-
- `<TrimMode>link</TrimMode>`
75-
76-
Enable member-level trimming, which removes unused members from types. This is the default in .NET 6+.
77-
78-
- `<TrimMode>copyused</TrimMode>`
79-
80-
Enable assembly-level trimming, which keeps an entire assembly if any part of it is used (in a statically understood way).
81-
82-
Assemblies with `<IsTrimmable>true</IsTrimmable>` metadata but no explicit `TrimMode` will use the global `TrimMode`. The default `TrimMode` for `Microsoft.NET.Sdk` is `link` in .NET 6+, and `copyused` in previous versions.
83-
84-
## Trim additional assemblies
85-
86-
In .NET 6+, `PublishTrimmed` trims assemblies with the following assembly-level attribute:
87-
88-
```csharp
89-
[AssemblyMetadata("IsTrimmable", "True")]
90-
```
91-
92-
The framework libraries have this attribute. In .NET 6+, you can also opt in to trimming for a library without this attribute, specifying the assembly by name (without the `.dll` extension).
93-
94-
## Trimming settings for individual assemblies
95-
96-
When publishing a trimmed app, the SDK computes an `ItemGroup` called `ManagedAssemblyToLink` that represents the set of files to be processed for trimming. `ManagedAssemblyToLink` might have metadata that controls the trimming behavior per assembly. To set this metadata, create a target that runs before the built-in `PrepareForILLink` target. The following example shows how to enable trimming of `MyAssembly`.
97-
98-
```xml
99-
<Target Name="ConfigureTrimming"
100-
BeforeTargets="PrepareForILLink">
101-
<ItemGroup>
102-
<ManagedAssemblyToLink Condition="'%(Filename)' == 'MyAssembly'">
103-
<IsTrimmable>true</IsTrimmable>
104-
</ManagedAssemblyToLink>
105-
</ItemGroup>
106-
</Target>
107-
```
108-
109-
You can also use this target to override the trimming behavior specified by the library author, by setting `<IsTrimmable>false</IsTrimmable>` for an assembly with `[AssemblyMetadata("IsTrimmable", "True"])`.
110-
111-
Do not add or remove items from `ManagedAssemblyToLink`, because the SDK computes this set during publish and expects it not to change. The supported metadata is:
112-
113-
- `<IsTrimmable>true</IsTrimmable>`
114-
115-
Control whether the given assembly is trimmed.
116-
117-
- `<TrimMode>copyused</TrimMode>` or `<TrimMode>link</TrimMode>`
118-
119-
Control the [trimming granularity](#trimming-granularity) of this assembly. This metadata takes precedence over the global `TrimMode`. Setting `TrimMode` on an assembly implies `<IsTrimmable>true</IsTrimmable>`.
120-
121-
- `<TrimmerSingleWarn>True</TrimmerSingleWarn>`
122-
123-
Control whether to show [single warnings](#show-detailed-warnings) for this assembly.
124-
125-
:::zone-end
126-
12755
## Root assemblies
12856

12957
If an assembly is not trimmed, it's considered "rooted", which means that it and all of its statically understood dependencies will be kept. Additional assemblies can be "rooted" by name (without the `.dll` extension):

0 commit comments

Comments
 (0)