You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/core/deploying/trimming/prepare-libraries-for-trimming.md
+8-75Lines changed: 8 additions & 75 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,46 +4,19 @@ description: Learn how to prepare .NET libraries for trimming.
4
4
author: sbomer
5
5
ms.author: svbomer
6
6
ms.date: 06/12/2023
7
-
zone_pivot_groups: dotnet-version
8
7
---
9
8
10
9
# Prepare .NET libraries for trimming
11
10
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:
13
12
14
13
* Describes how to prepare libraries for trimming.
15
14
* Provides recommendations for [resolving common trimming warnings](#resolve-trim-warnings).
16
15
17
16
## Prerequisites
18
17
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
-
43
18
[.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet) or later.
44
19
45
-
:::zone-end
46
-
47
20
## Enable library trim warnings
48
21
49
22
Trim warnings in a library can be found with either of the following methods:
@@ -93,56 +66,15 @@ To create the trimming test app:
93
66
94
67
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.
95
68
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
-
108
69
* Add `<PublishTrimmed>true</PublishTrimmed>`.
109
70
* Add a reference to the library project with `<ProjectReference Include="/Path/To/YourLibrary.csproj" />`.
110
71
* Specify the library as a trimmer root assembly with `<TrimmerRootAssembly Include="YourLibraryName" />`.
111
72
*`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.
112
73
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.
**Note:** In the preceding project file, when using .NET 7, replace `<TargetFramework>net8.0</TargetFramework>` with `<TargetFramework>net7.0</TargetFramework>`.
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.
153
85
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:
155
88
156
89
* If the new version added non-understood reflection patterns.
157
90
* Even if there were no API changes.
158
91
* Introducing trim analysis warnings is a breaking change when the library is used with `PublishTrimmed`.
159
92
160
93
## Resolve trim warnings
161
94
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.
163
96
164
97
### RequiresUnreferencedCode
165
98
@@ -204,11 +137,11 @@ In this case, the trim analysis keeps public methods of <xref:System.Tuple>, and
204
137
* When code is incompatible with trimming, annotate it with `RequiresUnreferencedCode` and propagate this annotation to callers until the relevant public APIs are annotated.
205
138
* 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.
206
139
* 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)
208
141
209
142
## Resolve warnings for non-analyzable patterns
210
143
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.
212
145
213
146
> [!WARNING]
214
147
> 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
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.
@@ -252,7 +185,7 @@ Without `DynamicDependency`, trimming might remove `Helper` from `MyAssembly` or
252
185
253
186
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).
254
187
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:
Copy file name to clipboardExpand all lines: docs/core/deploying/trimming/trimming-options.md
-72Lines changed: 0 additions & 72 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,7 +5,6 @@ author: sbomer
5
5
ms.author: svbomer
6
6
ms.date: 08/29/2024
7
7
ms.topic: reference
8
-
zone_pivot_groups: dotnet-version
9
8
---
10
9
11
10
# Trimming options
@@ -25,24 +24,12 @@ Trimming with `PublishTrimmed` was introduced in .NET Core 3.0. The other option
25
24
26
25
Place this setting in the project file to ensure that the setting applies during `dotnet build`, not just `dotnet publish`.
27
26
28
-
:::zone pivot="dotnet-8-0,dotnet-7-0"
29
-
30
27
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>`.
31
28
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
-
40
29
This setting also enables the trim-compatibility [Roslyn analyzer](#roslyn-analyzer) and disables [features that are incompatible with trimming](#framework-features-disabled-when-trimming).
41
30
42
31
## Trimming granularity
43
32
44
-
:::zone pivot="dotnet-8-0,dotnet-7-0"
45
-
46
33
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`:
47
34
48
35
```xml
@@ -65,65 +52,6 @@ If you change the trim mode to `partial`, you can opt-in individual assemblies t
65
52
66
53
This is equivalent to setting `[AssemblyMetadata("IsTrimmable", "True")]` when building the assembly.
67
54
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`.
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
-
127
55
## Root assemblies
128
56
129
57
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