Compartilhar via


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ório Repository\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ório Repository\.

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:

  1. 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 MSBuild ManagePackageVersionsCentrally como true.
  2. Declare <PackageVersion /> itens em seu Directory.Packages.props.
  3. Declare itens <PackageReference /> que não possuem atributos Version 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.