CPM (Gerenciamento Central de Pacotes)
O gerenciamento de dependência é um recurso principal do NuGet. O gerenciamento de dependências para um único projeto pode ser fácil. O gerenciamento de dependências para soluções de diversos projetos pode se tornar difícil à medida que elas começam a escalar em tamanho e complexidade. Em situações em que você gerencia dependências comuns para muitos projetos diferentes, você pode aproveitar os recursos do CPM (gerenciamento central de pacotes) do NuGet para fazer tudo isso da facilidade de um único local.
Historicamente, as dependências do pacote NuGet foram gerenciadas em um dos dois locais:
-
packages.config
– um arquivo XML usado em tipos de projeto mais antigos para manter a lista de pacotes referenciados pelo projeto. -
<PackageReference />
- Um elemento XML usado em projetos do MSBuild define dependências do pacote NuGet.
Começando com nuGet 6.2, você pode gerenciar centralmente suas dependências em seus projetos com a adição de um arquivo Directory.Packages.props
e uma propriedade MSBuild.
O recurso está disponível em todas as ferramentas integradas do NuGet, começando com as versões a seguir.
Ferramentas mais antigas ignorarão as configurações e os recursos de gerenciamento de pacote central. Para usar esse recurso em toda a extensão, verifique se todos os ambientes de build usam as versões de ferramentas compatíveis mais recentes.
O gerenciamento de pacotes central aplica-se a todos os projetos do MSBuild baseados em <PackageReference>
(incluindo CSPROJ herdados), desde que as ferramentas compatíveis sejam usadas.
Habilitando o Gerenciamento Central de Pacotes
Para começar a usar o gerenciamento central de pacotes, você deve criar um arquivo Directory.Packages.props
na raiz do repositório e definir a propriedade MSBuild ManagePackageVersionsCentrally
para true
.
Você pode criá-lo manualmente ou usar a CLI do dotnet:
dotnet new packagesprops
Dentro do projeto, você define cada uma das versões de pacote respectivas necessárias para os seus projetos usando elementos <PackageVersion />
que especificam a ID e a versão do pacote.
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>
Para cada projeto, você define um <PackageReference />
mas omite o atributo Version
, pois a versão será obtida de um item de <PackageVersion />
correspondente.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
</ItemGroup>
</Project>
Agora você está usando o gerenciamento central de pacotes e gerenciando suas versões em um local central!
Regras centrais de gerenciamento de pacotes
O arquivo Directory.Packages.props
tem várias regras em relação ao local em que está localizado no diretório de um repositório e seu contexto. Para simplificar, apenas um arquivo Directory.Packages.props
é avaliado para um determinado projeto.
O que isso significa é que, se você tiver vários arquivos Directory.Packages.props
no repositório, o arquivo mais próximo do diretório do seu projeto será considerado. Isso lhe permite ter controle adicional sobre vários níveis do seu repositório.
Aqui está um exemplo, considere a seguinte estrutura de repositório:
Repository
|-- Directory.Packages.props
|-- Solution1
|-- Directory.Packages.props
|-- Project1
|-- Solution2
|-- Project2
- O Project1 avaliará o arquivo
Directory.Packages.props
no diretórioRepository\Solution1\
e deverá importar manualmente o próximo, se assim desejar.<Project> <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Packages.props, $(MSBuildThisFileDirectory)..))" /> <ItemGroup> <PackageVersion Update="Newtonsoft.Json" Version="12.0.1" /> </ItemGroup> </Project>
- O Project2 avaliará o arquivo
Directory.Packages.props
no diretórioRepository\
.
Observação: o MSBuild não importará automaticamente cada Directory.Packages.props
para você, apenas o primeiro mais próximo do projeto. Se você tiver vários Directory.Packages.props
, deverá importar o pai manualmente enquanto o Directory.Packages.props
raiz não o faria.
Começar
Para integrar totalmente o repositório, considere executar estas etapas:
- Crie um novo arquivo na raiz do repositório chamado
Directory.Packages.props
que declara suas versões de pacote definidas centralmente e defina a propriedade do MSBuildManagePackageVersionsCentrally
comotrue
. - Declare
<PackageVersion />
itens em seuDirectory.Packages.props
. - Declare itens
<PackageReference />
que não possuem atributosVersion
em seus arquivos de projeto.
Para ter uma ideia de como pode ser o gerenciamento central de pacotes, consulte nosso repositório de exemplos .
Fixação transitiva
Você pode substituir automaticamente uma versão de pacote transitivo mesmo sem um <PackageReference />
de nível superior explícito optando por um recurso conhecido como fixação transitiva. Isso promove uma dependência transitiva para uma dependência de nível superior implicitamente em seu nome, quando necessário.
Observe que os downgrades são permitidos ao fixar um pacote transitivo. Se você tentar fixar um pacote em uma versão inferior à solicitada por suas dependências, a restauração gerará um erro de NU1109.
Você pode habilitar esse recurso definindo a propriedade MSBuild CentralPackageTransitivePinningEnabled
para true
em um projeto ou em um arquivo de importação Directory.Packages.props
ou Directory.Build.props
:
<PropertyGroup>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
Fixação transitiva e pacote
Quando um pacote é fixado transitivamente, seu projeto usa um valor maior do que o solicitado por suas dependências. Se você criar um pacote com base em seu projeto, para garantir que o pacote funcione, o NuGet promoverá as dependências fixadas transitivamente para dependências explícitas no nuspec.
No exemplo a seguir, PackageA 1.0.0
tem uma dependência de PackageB 1.0.0
.
<Project>
<ItemGroup>
<PackageVersion Include="PackageA" Version="1.0.0" />
<PackageVersion Include="PackageB" Version="2.0.0" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="PackageA" />
</ItemGroup>
</Project>
Quando você usa o comando do pacote para criar um pacote, ambos os pacotes serão exibidos no grupo de dependências.
<group targetFramework="net6.0">
<dependency id="PackageA" version="6.12.1" exclude="Build,Analyzers" />
<dependency id="PackageB" version="6.12.1" exclude="Build,Analyzers" />
</group>
Por isso, o uso da fixação transitiva deve ser cuidadosamente avaliado ao criar uma biblioteca, pois isso pode levar a dependências que você não esperava.
Substituindo versões de pacote
Você pode substituir a versão individual de um pacote usando a propriedade VersionOverride
em um item <PackageReference />
. Isso substitui qualquer <PackageVersion />
definido centralmente.
<Project>
<ItemGroup>
<PackageVersion Include="PackageA" Version="1.0.0" />
<PackageVersion Include="PackageB" Version="2.0.0" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="PackageA" VersionOverride="3.0.0" />
</ItemGroup>
</Project>
Você pode desabilitar esse recurso definindo a propriedade MSBuild CentralPackageVersionOverrideEnabled
para false
em um projeto ou em um arquivo de importação Directory.Packages.props
ou Directory.Build.props
:
<PropertyGroup>
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
</PropertyGroup>
Quando esse recurso estiver desabilitado, especificar um VersionOverride
em qualquer item de <PackageReference />
resultará em um erro no momento da restauração indicando que o recurso está desabilitado.
Desabilitando o Gerenciamento Central de Pacotes
Se você quiser desabilitar o gerenciamento de pacotes central para qualquer projeto específico, poderá desabilitá-lo definindo a propriedade MSBuild ManagePackageVersionsCentrally
para false
:
<PropertyGroup>
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
</PropertyGroup>
Referências de Pacotes Globais
Nota
Esse recurso só está disponível no Visual Studio 2022 17.4 ou superior, no SDK do .NET 7.0.100.preview7 ou superior e no NuGet 6.4 ou superior.
Uma referência de pacote global é usada para especificar que um pacote será usado por cada projeto em um repositório. Isso inclui pacotes que fazem controle de versão, estendem seu build ou quaisquer outros pacotes necessários para todos os projetos. As referências de pacote global são adicionadas ao grupo de itens PackageReference com os seguintes metadados:
IncludeAssets="Runtime;Build;Native;contentFiles;Analyzers"
Isso garante que o pacote seja usado somente como dependência de desenvolvimento e evita quaisquer referências de assembly em tempo de compilação.PrivateAssets="All"
Isto impede que as referências globais de pacote sejam captadas por dependências posteriores.
GlobalPackageReference
itens devem ser colocados no seu Directory.Packages.props
para serem usados por todos os projetos em um repositório.
<Project>
<ItemGroup>
<GlobalPackageReference Include="Nerdbank.GitVersioning" Version="3.5.109" />
</ItemGroup>
</Project>
Aviso ao usar várias fontes de pacote
Ao usar o gerenciamento central de pacotes, você verá um aviso de NU1507
se tiver mais de uma fonte de pacote definida em sua configuração. Para resolver esse aviso, mapeie as fontes do pacote com de mapeamento de origem do pacote ou especifique uma única fonte de pacote.
There are 3 package sources defined in your configuration. When using central package management, please map your package sources with package source mapping (https://aka.ms/nuget-package-source-mapping) or specify a single package source.
Nota
O gerenciamento de pacotes central está em desenvolvimento ativo. Agradecemos por experimentar e fornecer qualquer feedback que você possa ter em NuGet/Home.