Skip to content

Commit 487e059

Browse files
authored
Document package pruning (#3393)
1 parent f204fb6 commit 487e059

File tree

7 files changed

+144
-11
lines changed

7 files changed

+144
-11
lines changed

docs/TOC.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@
185185
### [NU1506](reference/errors-and-warnings/NU1506.md)
186186
### [NU1507](reference/errors-and-warnings/NU1507.md)
187187
### [NU1508](reference/errors-and-warnings/NU1508.md)
188+
### [NU1509](reference/errors-and-warnings/NU1509.md)
189+
### [NU1510](reference/errors-and-warnings/NU1510.md)
190+
### [NU1511](reference/errors-and-warnings/NU1511.md)
188191
### [NU1601](reference/errors-and-warnings/NU1601.md)
189192
### [NU1602](reference/errors-and-warnings/NU1602.md)
190193
### [NU1603](reference/errors-and-warnings/NU1603.md)

docs/consume-packages/Package-References-in-Project-Files.md

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ This may be useful, if you reference projects which are PackageReference styled
6161

6262
## PackageReference and sources
6363

64-
In PackageReference projects, the transitive dependency versions are resolved at restore time. As such, in PackageReference projects all sources need to be available for all restores.
64+
In PackageReference projects, the transitive dependency versions are resolved at restore time. As such, in PackageReference projects all sources need to be available for all restores.
6565

6666
## Floating Versions
6767

@@ -285,7 +285,7 @@ To suppress a warning project wide, consider doing:
285285
</ItemGroup>
286286
```
287287

288-
Sometimes warnings apply only to a certain package in the graph. We can choose to suppress that warning more selectively by adding a `NoWarn` on the PackageReference item.
288+
Sometimes warnings apply only to a certain package in the graph. We can choose to suppress that warning more selectively by adding a `NoWarn` on the PackageReference item.
289289

290290
```xml
291291
<PropertyGroup>
@@ -307,15 +307,15 @@ When in Visual Studio, you can also [suppress warnings](/visualstudio/ide/how-to
307307

308308
Input to NuGet restore is a set of `PackageReference` items from the project file (top-level or direct dependencies) and the output is a full closure of all the package dependencies including transitive dependencies. NuGet tries to always produce the same full closure of package dependencies if the input PackageReference list has not changed. However, there are some scenarios where it is unable to do so. For example:
309309

310-
* When you use floating versions like `<PackageReference Include="My.Sample.Lib" Version="4.*"/>`. While the intention here is to float to the latest version on every restore of packages, there are scenarios where users require the graph to be locked to a certain latest version and float to a later version, if available, upon an explicit gesture.
311-
* A newer version of the package matching PackageReference version requirements is published. E.g.
310+
- When you use floating versions like `<PackageReference Include="My.Sample.Lib" Version="4.*"/>`. While the intention here is to float to the latest version on every restore of packages, there are scenarios where users require the graph to be locked to a certain latest version and float to a later version, if available, upon an explicit gesture.
311+
- A newer version of the package matching PackageReference version requirements is published. E.g.
312312

313-
* Day 1: if you specified `<PackageReference Include="My.Sample.Lib" Version="4.0.0"/>` but the versions available on the
313+
- Day 1: if you specified `<PackageReference Include="My.Sample.Lib" Version="4.0.0"/>` but the versions available on the
314314
NuGet repositories were 4.1.0, 4.2.0 and 4.3.0. In this case, NuGet would have resolved to 4.1.0 (nearest minimum version)
315315

316-
* Day 2: Version 4.0.0 gets published. NuGet will now find the exact match and start resolving to 4.0.0
316+
- Day 2: Version 4.0.0 gets published. NuGet will now find the exact match and start resolving to 4.0.0
317317

318-
* A given package version is removed from the repository. Though nuget.org does not allow package deletions, not all package repositories have this constraint. This results in NuGet finding the best match when it cannot resolve to the deleted version.
318+
- A given package version is removed from the repository. Though nuget.org does not allow package deletions, not all package repositories have this constraint. This results in NuGet finding the best match when it cannot resolve to the deleted version.
319319

320320
### Enabling the lock file
321321

@@ -329,12 +329,13 @@ In order to persist the full closure of package dependencies you can opt-in to t
329329
</PropertyGroup>
330330
```
331331

332-
If this property is set, NuGet restore will generate a lock file - `packages.lock.json` file at the project root directory that lists all the package dependencies.
332+
If this property is set, NuGet restore will generate a lock file - `packages.lock.json` file at the project root directory that lists all the package dependencies.
333333

334334
> [!Note]
335335
> Once a project has `packages.lock.json` file in its root directory, the lock file is always used with restore even if the property `RestorePackagesWithLockFile` is not set. So another way to opt-in to this feature is to create a dummy blank `packages.lock.json` file in the project's root directory.
336336
337337
### `restore` behavior with lock file
338+
338339
If a lock file is present for project, NuGet uses this lock file to run `restore`. NuGet does a quick check to see if there were any changes in the package dependencies as mentioned in the project file (or dependent projects' files) and if there were no changes it just restores the packages mentioned in the lock file. There is no re-evaluation of package dependencies.
339340

340341
If NuGet detects a change in the defined dependencies as mentioned in the project file(s), it re-evaluates the package graph and updates the lock file to reflect the new package closure for the project.
@@ -366,6 +367,7 @@ You may also set this conditional MSBuild property in your project file:
366367
If locked mode is `true`, restore will either restore the exact packages as listed in the lock file or fail if you updated the defined package dependencies for the project after lock file was created.
367368

368369
### Make lock file part of your source repository
370+
369371
If you are building an application, an executable and the project in question is at the start of the dependency chain then do check in the lock file to the source code repository so that NuGet can make use of it during restore.
370372

371373
However, if your project is a library project that you do not ship or a common code project on which other projects depend upon, you **should not** check in the lock file as part of your source code. There is no harm in keeping the lock file but the locked package dependencies for the common code project may not be used, as listed in the lock file, during the restore/build of a project that depends on this common-code project.
@@ -388,7 +390,7 @@ You can control various behaviors of restore with lock file as described below:
388390
| NuGet.exe option | dotnet option | MSBuild equivalent option | Description |
389391
|:--- |:--- |:--- |:--- |
390392
| `-UseLockFile` |`--use-lock-file` | RestorePackagesWithLockFile | Opts into the usage of a lock file. |
391-
| `-LockedMode` | `--locked-mode` | RestoreLockedMode | Enables locked mode for restore. This is useful in CI/CD scenarios where you want repeatable builds.|
393+
| `-LockedMode` | `--locked-mode` | RestoreLockedMode | Enables locked mode for restore. This is useful in CI/CD scenarios where you want repeatable builds.|
392394
| `-ForceEvaluate` | `--force-evaluate` | RestoreForceEvaluate | This option is useful with packages with floating version defined in the project. By default, NuGet restore will not update the package version automatically upon each restore unless you run restore with this option. |
393395
| `-LockFilePath` | `--lock-file-path` | NuGetLockFilePath | Defines a custom lock file location for a project. By default, NuGet supports `packages.lock.json` at the root directory. If you have multiple projects in the same directory, NuGet supports project specific lock file `packages.<project_name>.lock.json` |
394396

@@ -458,3 +460,51 @@ You can leave off `$(AssetTargetFallback)` if you wish to overwrite, instead of
458460
> If you are using a [.NET SDK based project](/dotnet/core/sdk), appropriate `$(AssetTargetFallback)` values are configured and you do not need to set them manually.
459461
>
460462
> `$(PackageTargetFallback)` was an earlier feature that attempted to address this challenge, but it is fundamentally broken and *should* not be used. To migrate from `$(PackageTargetFallback)` to `$(AssetTargetFallback)`, simply change the property name.
463+
464+
## PrunePackageReference
465+
466+
The .NET Runtime is constantly evolving, with performance improvements and new APIs each release.
467+
There is a lot of functionality that's available within the runtime, but also as packages, such as [System..Text.Json](https://www.nuget.org/packages/System.Text.Json). This can often lead to a `System.Text.Json 8.0.0` in a project targeting `.NET 9` or `.NET 8`. This dependency is unnecessary and the build conflict resolution would not use the assembly coming from the package since it's already available in the .NET Runtime.
468+
Starting in in [NuGet version 6.13](..\release-notes\NuGet-6.13.md) and .NET SDK 9.0.200, `PrunePackageReference` enables the pruning of these packages at restore time for .NET SDK based projects.
469+
470+
Package pruning is available as an opt-in feature with the .NET 9 SDK, and will be enabled by default for all `.NET` frameworks and `>= .NET Standard 2.0` starting with .NET 10 SDK.
471+
472+
Package pruning is only available with the default dependency resolver as [released in 6.12](#nuget-dependency-resolver).
473+
474+
### PrunePackageReference specification
475+
476+
The list of packages to be pruned is defined with the `PrunePackageReference` item.
477+
478+
| Attributes | Description |
479+
|------------|-------------|
480+
| Version | Specifies the maximum version to be pruned. `1.0.0` means that all packages up to and including 1.0.0 will be pruned. For `1.0.0`, `0.9.0` and `1.0.0` will be pruned, but `1.0.1` would not. |
481+
482+
The following properties can be used to modify the pruning behavior.
483+
484+
| PropertyName | Description |
485+
|--------------|-------------|
486+
| RestoreEnablePackagePruning | Enables package pruning for the packages specified with `PrunePackageReference`. This property is per target framework and the valid values are `true` and `false`. Defaults may differ based on the .NET SDK as defined above. |
487+
488+
The .NET SDK predefines the list of packages to be pruned for you.
489+
490+
### How PrunePackageReference works
491+
492+
When a package is specified to be pruned during restore, it is removed from the dependency graph. This package is not downloaded and does not appear in any of the outputs of NuGet. When a package is pruned, there is a detailed verbosity message indicating that the package has been removed for the given target framework.
493+
494+
Pruning is only supported for transitive packages, meaning packages that are referenced by other packages or projects. The following table illustrates various package pruning behaviors.
495+
496+
| Dependency disposition | Behavior |
497+
|-----------------|----------|
498+
| Matches the ID of a transitive package coming through another package | Prune |
499+
| Matches the ID of a transitive package coming through another project | Prune |
500+
| Matches the ID of a direct `PackageReference` | Raise the [NU1510](../reference/errors-and-warnings/NU1510.md) warning and do not prune |
501+
| Matches the ID of a `ProjectReference` | Raise the [NU1511](../reference/errors-and-warnings/NU1511.md) warning and do not prune |
502+
503+
### PrunePackageReference applications
504+
505+
The benefits of package pruning are two-fold:
506+
507+
- Performance benefits, by virtue of reducing the number of packages within a dependency graph
508+
- Reduction of false positives by component scanners such as `NuGetAudit`
509+
510+
Pruning is particularly valuable when [auditing](./../concepts/Auditing-Packages.md) packages with `NuGetAuditMode` is set to `all`. If you are using the .NET 9, we recommend you try out pruning by setting `RestoreEnablePackagePruning` to `true`.

docs/reference/Errors-and-Warnings.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ NuGet supports the following configuration properties.
4343

4444
| Group | Warning numbers |
4545
| --- | --- |
46-
| Invalid input warnings | [NU1501](./errors-and-warnings/NU1501.md), [NU1502](./errors-and-warnings/NU1502.md), [NU1503](./errors-and-warnings/NU1503.md), [NU1504](./errors-and-warnings/NU1504.md), [NU1505](./errors-and-warnings/NU1505.md), [NU1506](./errors-and-warnings/NU1506.md), [NU1507](./errors-and-warnings/NU1507.md), [NU1508](./errors-and-warnings/NU1508.md) |
46+
| Invalid input warnings | [NU1501](./errors-and-warnings/NU1501.md), [NU1502](./errors-and-warnings/NU1502.md), [NU1503](./errors-and-warnings/NU1503.md), [NU1504](./errors-and-warnings/NU1504.md), [NU1505](./errors-and-warnings/NU1505.md), [NU1506](./errors-and-warnings/NU1506.md), [NU1507](./errors-and-warnings/NU1507.md), [NU1508](./errors-and-warnings/NU1508.md), [NU1509](./errors-and-warnings/NU1509.md), [NU1510](./errors-and-warnings/NU1510.md), [NU1511](./errors-and-warnings/NU1511.md) |
4747
| Unexpected package version warnings | [NU1601](./errors-and-warnings/NU1601.md), [NU1602](./errors-and-warnings/NU1602.md), [NU1603](./errors-and-warnings/NU1603.md), [NU1604](./errors-and-warnings/NU1604.md), [NU1605](./errors-and-warnings/NU1605.md), [NU1606](./errors-and-warnings/NU1108.md), [NU1607](./errors-and-warnings/NU1107.md) |
4848
| Resolver conflict warnings | [NU1608](./errors-and-warnings/NU1608.md) |
4949
| Package fallback warnings | [NU1701](./errors-and-warnings/NU1701.md), [NU1702](./errors-and-warnings/NU1702.md), [NU1703](./errors-and-warnings/NU1703.md)|

docs/reference/errors-and-warnings/NU1508.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ f1_keywords:
1919

2020
Sometimes when adding `NuGetAuditSuppress` items, you may end up adding an item for a particular package multiple times.
2121

22-
MSBuild projects commonly import multiple `.props` and `.targets` files, so the duplicates might not be in the same file, but may be in included files, such as `Directory.Build.props`, `Directory.Packages.props`, or `Directory.Build.targets`.
22+
MSBuild projects commonly import multiple `.props` and `.targets` files, so the duplicates might not be in the same file, but may be in imported files, such as `Directory.Build.props`, `Directory.Packages.props`, or `Directory.Build.targets`.
2323

2424
### Solution
2525

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
title: NuGet Warning NU1509
3+
description: NU1509 warning code
4+
author: nkolev92
5+
ms.author: nikolev
6+
ms.date: 02/04/2025
7+
ms.topic: reference
8+
f1_keywords:
9+
- "NU1509"
10+
---
11+
12+
# NuGet Warning NU1509
13+
14+
## Scenario 1
15+
16+
> Duplicate 'PrunePackageReference' items found. Remove the duplicate items or use the Update functionality to ensure a consistent restore behavior. The duplicate 'PrunePackageReference' items are: X 1.0.0, X 2.0.0.
17+
18+
### Issue
19+
20+
Sometimes when adding `PrunePackageReference` items, you may end up adding an item for a particular package multiple times.
21+
22+
MSBuild projects commonly import multiple `.props` and `.targets` files, so the duplicates might not be in the same file, but may be in imported files, such as `Directory.Build.props`, `Directory.Packages.props`, or `Directory.Build.targets`.
23+
24+
The `.NET SDK` provides a of list `PrunePackageReference`, so the conflict may be happening because you have specified a `PrunePackageReference` or due to a bug with the `.NET SDK`.
25+
26+
### Solution
27+
28+
Remove the duplicate item, so that it's included exactly once.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
title: NuGet Warning NU1510
3+
description: NU1510 warning code
4+
author: nkolev92
5+
ms.author: nikolev
6+
ms.date: 02/04/2025
7+
ms.topic: reference
8+
f1_keywords:
9+
- "NU1510"
10+
---
11+
12+
# NuGet Warning NU1510
13+
14+
## Scenario 1
15+
16+
> PackageReference System.Text.Json 9.0.0 will not be pruned. Consider removing this package from your dependencies, as it is likely unnecessary.
17+
18+
### Issue
19+
20+
The package `System.Text.Json` has been specified for pruning through the [PrunePackageReference](../../consume-packages/Package-References-in-Project-Files.md#prunepackagereference) feature.
21+
The `.NET SDK` generally specifies the list of packages to be pruned. The package is not needed as a direct PackageReference since the .NET runtime itself carries either the same or higher version of the assembly.
22+
23+
### Solution
24+
25+
Remove the PackageReference as it's unnecessary.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
title: NuGet Warning NU1511
3+
description: NU1511 warning code
4+
author: nkolev92
5+
ms.author: nikolev
6+
ms.date: 02/04/2025
7+
ms.topic: reference
8+
f1_keywords:
9+
- "NU1511"
10+
---
11+
12+
# NuGet Warning NU1511
13+
14+
## Scenario 1
15+
16+
> A ProjectReference cannot be pruned, X.
17+
18+
### Issue
19+
20+
The project id `X` has been specified for pruning through the [PrunePackageReference](../../consume-packages/Package-References-in-Project-Files.md#prunepackagereference) feature.
21+
Pruning of projects is not supported.
22+
23+
### Solution
24+
25+
- The `.NET SDK` generally specifies the list of packages to be pruned. It may mean that you have a project matching the id of a platform assembly.
26+
In this scenario, change the name of the project.
27+
- If the `PrunePackageReference` has been specified within your project, you may need to remove the `PrunePackageReference`

0 commit comments

Comments
 (0)