es

Central Package Management

Por qué PCPM se apoya en el CPM de Microsoft, no en su contra.

Central Package Management es una característica del SDK de .NET que mueve las versiones de los paquetes fuera de los ficheros .csproj individuales y a un único Directory.Packages.props en la raíz del workspace. PCPM está construido sobre CPM, no en su contra; esta página explica por qué y cómo sacarle el máximo partido.

El fichero CPM

Un Directory.Packages.props es un fichero .props de MSBuild normal. Vive en la raíz del workspace y se importa automáticamente en cada .csproj bajo el mismo árbol de directorios. Su trabajo es declarar entradas <PackageVersion />:

<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>
  <ItemGroup>
    <PackageVersion Include="Serilog" Version="3.1.1" />
    <PackageVersion Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
    <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
  </ItemGroup>
</Project>

La propiedad <ManagePackageVersionsCentrally>true<…/> es lo que hace que esto funcione — le dice a MSBuild que la versión de cualquier <PackageReference /> debe venir de este fichero y no del .csproj.

Un <PackageReference /> en cualquier .csproj se ve entonces así:

<ItemGroup>
  <PackageReference Include="Serilog" />
</ItemGroup>

Sin atributo Version. La versión es implícita; el .csproj solo conoce el id.

Por qué es el sustrato correcto para PCPM

La queja más común sobre los gestores de paquetes es “deriva de versiones entre proyectos”. Con CPM, esa queja es estructuralmente imposible: hay un único lugar para poner una versión, y se aplica en todas partes. El hecho de que PCPM escriba la versión por ti cuando ejecutas pcpm add es una conveniencia, no un requisito — puedes editar a mano Directory.Packages.props y pcpm install recogerá el cambio.

La segunda razón es que CPM ya es una característica de MSBuild. El SDK de .NET, Visual Studio, Rider y dotnet restore lo entienden todos. PCPM no tiene que enviar un target de build, un resolver personalizado, ni un plugin de NuGet.Protocol. Solo escribe ficheros CPM.

La tercera razón es que la comunidad .NET se ha decantado por CPM como respuesta al problema de los “muchos csproj. Apoyándose en él, PCPM hereda la solución que ya está ganando. Construyendo sobre él, PCPM se enfoca en las partes que CPM no resuelve: el store, los hardlinks, la resolución estricta.

El modelo de ficheros amigable con CPM

PCPM solo toca tres ficheros en tu workspace:

  • Directory.Packages.props — escrito por pcpm add, pcpm remove, pcpm convert. Nunca se sobrescribe si ya existe; PCPM adopta las entradas existentes.
  • pcpm.json — escrito por pcpm init. El manifiesto de PCPM. Casi nunca lo editas a mano.
  • pcpm.lock — escrito por pcpm install. El grafo resuelto con hashes de contenido. Generado, nunca editado a mano.

Los ficheros .csproj se tocan con pcpm add y pcpm remove para añadir o eliminar entradas <PackageReference />, y con pcpm convert para eliminar el atributo Version (en el caso en que no estuvieras usando CPM antes).

Los ficheros .targets de MSBuild que PCPM envía (pcpm.MsBuild.targets) se incluyen automáticamente a través del paquete NuGet pcpm.MsBuild. Este paquete contiene una tarea RelinkBin que vuelve a hacer hardlink de la salida de dotnet build al store, para que el binlog en CI no crezca con cada build. El paquete es opt-in; instálalo una vez por workspace si quieres este comportamiento.

Casos extremos

  • Overrides de versión por proyecto. Puedes sobreescribir la versión CPM para un solo proyecto con <PackageReference Include="X" Version="1.2.3" OverrideCentralPackageVersions="true" />. PCPM lo respeta; simplemente añade el override al grafo de resolución como una restricción más estrecha.
  • Versiones por TFM. <PackageVersion Include="X" Version="1.0.0"><Conditions><TargetFramework>net48</TargetFramework></Conditions></PackageVersion> está soportado. PCPM no envía una UI para ello; edita a mano el .props si lo necesitas.
  • Feeds privados. Si tienes un NuGet.config con <packageSource>, PCPM lo recoge y escribe los mismos feeds en pcpm.json.

Véase también