Gerenciamento de Pacotes Central (CPM)

O gerenciamento de dependências é um recurso central do NuGet. Gerenciar dependências para um único projeto pode ser fácil. O gerenciamento de dependências para soluções de vários projetos pode ser difícil à medida que elas começam a crescer em tamanho e complexidade. Em situações em que você gerencia dependências comuns para muitos projetos diferentes, é possível aproveitar os recursos de gerenciamento de pacotes central (CPM) do NuGet para fazer tudo isso com a facilidade de um único local.

Historicamente, as dependências de pacotes NuGet são gerenciadas em um de 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.

A partir do 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 do MSBuild.

O recurso está disponível em todas as ferramentas integradas do NuGet, começando com as versões a seguir.

As ferramentas mais antigas ignorarão as configurações e os recursos do gerenciamento de pacotes central. Para usar esse recurso ao máximo, certifique-se de que todos os seus ambientes de compilação usem as versões de ferramentas compatíveis mais recentes.

O gerenciamento de pacotes central se aplica a todos os <PackageReference>projetos MSBuild baseados em (incluindo CSPROJ herdado), desde que ferramentas compatíveis sejam usadas.

Habilitando o Gerenciamento de Pacotes Central

Para começar a usar o gerenciamento de pacotes central, você deve criar um arquivo Directory.Packages.props na raiz do repositório e definir a propriedade ManagePackageVersionsCentrally do MSBuild como true.

Dentro, você então define cada uma das respectivas versões de pacote necessárias de seus projetos usando elementos <PackageVersion /> que definem o 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 <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 de pacotes central e gerenciando suas versões em um local central!

Regras do Gerenciamento de Pacotes Central

O arquivo Directory.Packages.props tem uma série de regras com relação a onde ele está localizado no diretório de um repositório e seu contexto. Por uma questão de simplicidade, 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 em seu repositório, o arquivo mais próximo do diretório do seu projeto será avaliado para ele. Isso permite um controle extra em vários níveis do repositório.

Por exemplo, considere um repositório que tenha a estrutura a seguir.

Repository
 |-- Directory.Packages.props
 |-- Solution1
     |-- Directory.Packages.props
     |-- Project1
 |-- Solution2
     |-- Project2
  • Project1 irá avaliar o arquivo Directory.Packages.props no diretório Repository\Solution1\ e ele deve 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>
    
  • 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ê, mas 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.

Introdução

Para integrar totalmente seu repositório, considere seguir estas etapas:

  1. Crie um novo arquivo na raiz do repositório chamado Directory.Packages.props que declare suas versões de pacote definidas centralmente e defina a propriedade ManagePackageVersionsCentrally do MSBuild como true.
  2. Declare itens <PackageVersion /> em seu arquivo Directory.Packages.props.
  3. Declare itens <PackageReference /> sem atributos Version em seus arquivos de projeto.

Para ter uma ideia de como o gerenciamento de pacotes central pode ser, consulte nosso repositório de amostras.

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.

Você pode habilitar esse recurso definindo a propriedade CentralPackageTransitivePinningEnabled do MSBuild como true em um projeto ou em um arquivo de importação Directory.Packages.props ou Directory.Build.props.

<PropertyGroup>
  <CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>

Substituindo versões de pacotes

Você pode substituir uma versão de pacote individual 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 CentralPackageVersionOverrideEnabled do MSBuild como 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 é desabilitado, especificar um VersionOverride em qualquer item <PackageReference /> resultará em um erro no momento da restauração indicando que o recurso está desabilitado.

Desabilitando o Gerenciamento de Pacotes Central

Se você quiser desabilitar o gerenciamento de pacotes central para qualquer projeto específico, poderá fazê-lo definindo a propriedade ManagePackageVersionsCentrally do MSBuild como false:

<PropertyGroup>
  <ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
</PropertyGroup>

Referências de pacotes globais

Observação

Este recurso só está disponível no Visual Studio 2022 17.4 ou superior, no .NET SDK 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 um dos projetos em um repositório. Isso inclui pacotes que fazem controle de versão, estendem sua compilação ou quaisquer outros pacotes necessários para todos os projetos. As referências de pacotes globais 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 apenas como uma dependência de desenvolvimento e impede qualquer referência de assembly em tempo de compilação.
  • PrivateAssets="All"
    Isso impede que as referências de pacotes globais sejam selecionadas por dependências downstream.

Os itens GlobalPackageReference devem ser colocados em seu Directory.Packages.props para serem usados por cada projeto em um repositório:

<Project>
  <ItemGroup>
    <GlobalPackageReference Include="Nerdbank.GitVersioning" Version="3.5.109" />
  </ItemGroup>
</Project>

Aviso ao usar várias origens de pacotes

Ao usar o gerenciamento central de pacotes, você verá um aviso NU1507 se houver mais de uma origem de pacote definida em sua configuração. Para resolver esse aviso, mapeie as origens dos pacotes com o mapeamento de origens de pacotes ou especifique uma única origem 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.

Observação

O gerenciamento de pacotes central está em desenvolvimento ativo. Desde já, agradecemos se você experimentar e fornecer qualquer feedback que possa ter em NuGet/Home.