Creación de un paquete NuGet con MSBuild

Cuando crea un paquete NuGet a partir del código, empaqueta la funcionalidad en un componente que se pueda compartir con otros desarrolladores, así como que estos puedan usarlo. En este artículo se describe cómo crear un paquete con MSBuild. MSBuild viene preinstalado con cada carga de trabajo de Visual Studio que incluya NuGet. Además, también se puede usar MSBuild mediante la CLI de dotnet con dotnet msbuild.

Con los proyectos .NET Core y .NET Standard que usan el formato de estilo SDK y cualquier otro proyecto de estilo SDK, NuGet usa la información del archivo de proyecto directamente para crear un paquete. En el caso de un proyecto sin SDK que use <PackageReference>, NuGet también usará el archivo del proyecto para crear un paquete.

Los proyectos con SDK tienen la funcionalidad de paquetes disponible de forma predeterminada. En el caso de los proyectos PackageReference sin SDK, deberá agregar el paquete NuGet.Build.Tasks.Pack a las dependencias del proyecto. Para obtener información detallada sobre los destinos de paquete de MSBuild, vea pack y restore de NuGet como destinos de MSBuild.

El comando que crea un paquete, msbuild -t:pack , es funcionalmente equivalente a dotnet pack .

Importante

Este tema se aplica a los proyectos con SDK, que suelen ser proyectos de .NET Core y .NET Standard, así como a los paquetes sin SDK que usan PackageReference.

Establecimiento de las propiedades

Las propiedades siguientes se requieren para crear un paquete.

  • PackageId, el identificador de paquete, que debe ser único en la galería que hospeda el paquete. Si no se especifica, el valor predeterminado es AssemblyName.
  • Version, un número de versión específico con el formato Version donde -Suffix identifica las versiones anteriores a la versión. Si no se especifica, el valor predeterminado es 1.0.0.
  • El título del paquete como debe aparecer en el host (por ejemplo, nuget.org)
  • Authors, información del autor y el propietario. Si no se especifica, el valor predeterminado es AssemblyName.
  • Company, el nombre de la empresa. Si no se especifica, el valor predeterminado es AssemblyName.

Además, si va a empaquetar proyectos que no son de estilo SDK y que usan PackageReference, se requiere lo siguiente:

  • PackageOutputPath, la carpeta de salida para el paquete generado al llamar al paquete.

En Visual Studio, puede establecer estos valores en las propiedades del proyecto (haga clic con el botón derecho en el proyecto en el Explorador de soluciones, elija Propiedades y seleccione la pestaña Paquete). También puede establecer estas propiedades directamente en los archivos del proyecto (.csproj).

<PropertyGroup>
  <PackageId>ClassLibDotNetStandard</PackageId>
  <Version>1.0.0</Version>
  <Authors>your_name</Authors>
  <Company>your_company</Company>
</PropertyGroup>

Importante

Asigne al paquete un identificador que sea único en nuget.org o en el origen de paquete que esté usando.

En el ejemplo siguiente se muestra un archivo del proyecto sencillo y completo que incluye estas propiedades.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <PackageId>ClassLibDotNetStandard</PackageId>
    <Version>1.0.0</Version>
    <Authors>your_name</Authors>
    <Company>your_company</Company>
  </PropertyGroup>
</Project>

También puede establecer las propiedades opcionales, como , y , tal y como se describe en MSBuild pack targets (Destinos de paquetes de MSBuild), Controlling dependency assets (Controlar recursos de dependencia) y NuGet metadata properties (Propiedades de TitlePackageDescriptionPackageTagsPackageTagsTitlePackageDescription

Nota

En el caso de los paquetes creados para consumo público, preste especial atención la propiedad PackageTags, dado que estas etiquetas ayudan a otros usuarios a encontrar el paquete y comprender lo que hace.

Para obtener más información sobre cómo declarar dependencias y especificar números de versión, vea Referencias del paquete en archivos del proyecto y Control de versiones de paquetes. También es posible exponer recursos directamente desde las dependencias en el paquete mediante los atributos <IncludeAssets> y <ExcludeAssets>. Para más información, consulte Controlar los recursos de dependencias.

Adición de un campo opcional de descripción

La descripción opcional del paquete, que se muestra en la página NuGet.org del paquete, se extrae de la usada en el archivo o se extraía a través de en el <description></description>.csproj archivo $description<description></description>.

En el siguiente texto XML del archivo para un paquete de .NET se muestra un ejemplo de un campo de descripción:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <PackageId>Azure.Storage.Blobs</PackageId>
    <Version>12.4.0</Version>
    <PackageTags>Microsoft Azure Storage Blobs;Microsoft;Azure;Blobs;Blob;Storage;StorageScalable</PackageTags>
    <Description>
      This client library enables working with the Microsoft Azure Storage Blob service for storing binary and text data.
      For this release see notes - https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/storage/Azure.Storage.Blobs/README.md and https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/storage/Azure.Storage.Blobs/CHANGELOG.md
      in addition to the breaking changes https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/storage/Azure.Storage.Blobs/BreakingChanges.txt
      Microsoft Azure Storage quickstarts and tutorials - https://docs.microsoft.com/en-us/azure/storage/
      Microsoft Azure Storage REST API Reference - https://docs.microsoft.com/en-us/rest/api/storageservices/
      REST API Reference for Blob Service - https://docs.microsoft.com/en-us/rest/api/storageservices/blob-service-rest-api
    </Description>
  </PropertyGroup>
</Project>

Elección de un identificador de paquete único y establecimiento del número de versión

El identificador del paquete y el número de versión son los dos valores más importantes del proyecto, ya que identifican de forma única el código exacto que se incluye en el paquete.

Procedimientos recomendados para el identificador del paquete:

  • Unicidad: el identificador debe ser único en nuget.org o en la galería que hospede el paquete. Antes de decidirse por un identificador, busque en la galería aplicable para comprobar si el nombre ya está en uso. Para evitar conflictos, un buen patrón consiste en usar el nombre de la empresa como la primera parte del identificador, por ejemplo Contoso..
  • Nombres de tipo espacio de nombres: siguen un patrón similar a los espacios de nombres de .NET, con notación de puntos en lugar de guiones. Por ejemplo, use Contoso.Utility.UsefulStuff en lugar de Contoso-Utility-UsefulStuff o Contoso_Utility_UsefulStuff. También es útil para los consumidores cuando el identificador del paquete coincide con los espacios de nombres que se usan en el código.
  • Paquetes deejemplo: si genera un paquete de código de ejemplo que muestra cómo usar otro paquete, adjunte como sufijo al identificador, como en Contoso.Utility.UsefulStuff.Sample . (El paquete de ejemplo tendría evidentemente una dependencia en el otro paquete). Cuando cree un paquete de ejemplo, use el valor contentFiles en <IncludeAssets>. En la carpeta content, organice el código de ejemplo en una carpeta denominada \Samples\<identifier> como en \Samples\Contoso.Utility.UsefulStuff.Sample.

Procedimientos recomendados para la versión del paquete:

  • En general, establezca la versión del paquete para que coincida con el proyecto (o ensamblado), aunque esto no es estrictamente necesario. Esto resulta muy sencillo cuando limita un paquete a un solo ensamblado. En general, recuerde que el propio NuGet trabaja con versiones del paquete al resolver las dependencias, no con versiones de ensamblado.
  • Cuando se usa un esquema de la versión no estándar, asegúrese de tener en cuenta las reglas de control de versiones de NuGet, como se explica en Control de versiones de paquetes. NuGet es principalmente compatible con semver 2.

Para información sobre la resolución de las dependencias, consulte Resolución de dependencias con PackageReference. Para información anterior que también podría ser útil para entender mejor el control de versiones, consulte esta serie de entradas de blog.

Adición del paquete NuGet.Build.Tasks.Pack

Si usa MSBuild con un proyecto sin SDK y PackageReference, agregue el paquete NuGet.Build.Tasks.Pack al proyecto.

  1. Abra el archivo del proyecto y agregue lo siguiente tras el elemento <PropertyGroup>:

    <ItemGroup>
      <!-- ... -->
      <PackageReference Include="NuGet.Build.Tasks.Pack" Version="5.2.0"/>
      <!-- ... -->
    </ItemGroup>
    
  2. Abra un símbolo del sistema para desarrolladores (en el cuadro Búsqueda, escriba Símbolo del sistema para desarrolladores).

    Normalmente, es preferible iniciar el símbolo del sistema para desarrolladores de Visual Studio en el menú Inicio, ya que se configurará con todas las rutas de acceso necesarias para MSBuild.

  3. Cambie a la carpeta que contiene el archivo del proyecto y escriba el siguiente comando para instalar el paquete NuGet.Build.Tasks.Pack.

    # Uses the project file in the current folder by default
    msbuild -t:restore
    

    Asegúrese de que la salida de MSBuild indica que la compilación se ha completado correctamente.

Ejecución del comando msbuild -t:pack

Para compilar un paquete NuGet (un archivo .nupkg) desde el proyecto, ejecute el comando msbuild -t:pack, que también genera el proyecto automáticamente:

En el símbolo del sistema para desarrolladores de Visual Studio, escriba el comando siguiente:

# Uses the project file in the current folder by default
msbuild -t:pack

El resultado mostrará la ruta de acceso al archivo .nupkg.

Microsoft (R) Build Engine version 16.1.76+g14b0a930a7 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.

Build started 8/5/2019 3:09:15 PM.
Project "C:\Users\username\source\repos\ClassLib_DotNetStandard\ClassLib_DotNetStandard.csproj" on node 1 (pack target(s)).
GenerateTargetFrameworkMonikerAttribute:
Skipping target "GenerateTargetFrameworkMonikerAttribute" because all output files are up-to-date with respect to the input files.
CoreCompile:
  ...
CopyFilesToOutputDirectory:
  Copying file from "C:\Users\username\source\repos\ClassLib_DotNetStandard\obj\Debug\netstandard2.0\ClassLib_DotNetStandard.dll" to "C:\Use
  rs\username\source\repos\ClassLib_DotNetStandard\bin\Debug\netstandard2.0\ClassLib_DotNetStandard.dll".
  ClassLib_DotNetStandard -> C:\Users\username\source\repos\ClassLib_DotNetStandard\bin\Debug\netstandard2.0\ClassLib_DotNetStandard.dll
  Copying file from "C:\Users\username\source\repos\ClassLib_DotNetStandard\obj\Debug\netstandard2.0\ClassLib_DotNetStandard.pdb" to "C:\Use
  rs\username\source\repos\ClassLib_DotNetStandard\bin\Debug\netstandard2.0\ClassLib_DotNetStandard.pdb".
GenerateNuspec:
  Successfully created package 'C:\Users\username\source\repos\ClassLib_DotNetStandard\bin\Debug\AppLogger.1.0.0.nupkg'.
Done Building Project "C:\Users\username\source\repos\ClassLib_DotNetStandard\ClassLib_DotNetStandard.csproj" (pack target(s)).

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:01.21

Generación automática del paquete en la compilación

Para ejecutar automáticamente msbuild -t:pack al compilar o restaurar el proyecto, agregue la siguiente línea al archivo del proyecto en <PropertyGroup>:

<GeneratePackageOnBuild>true</GeneratePackageOnBuild>

Cuando ejecuta msbuild -t:pack en una solución, se empaquetan todos los proyectos de la solución que se pueden empaquetar (la propiedad <IsPackable> se establece en true).

Nota

Cuando genera automáticamente el paquete, el tiempo de empaquetado aumenta el tiempo de compilación del proyecto.

Prueba de instalación del paquete

Antes de publicar un paquete, normalmente querrá probar el proceso de instalación de un paquete en un proyecto. Las pruebas aseguran que los archivos necesarios acaban en los lugares correctos en el proyecto.

Puede probar las instalaciones de forma manual en Visual Studio o en la línea de comandos mediante los pasos de instalación de paquetes normales.

Importante

Los paquetes son inmutables. Si corrige un problema, cambie el contenido del paquete y vuelva a empaquetar. Cuando vuelva a realizar la prueba, seguirá usando la versión anterior del paquete hasta que bote la carpeta global de paquetes. Esto resulta especialmente relevante cuando se prueban paquetes que no usan una etiqueta preliminar única en cada compilación.

Pasos siguientes

Una vez que haya creado un paquete, que es un archivo, puede publicarlo en la galería de su elección como se describe en .nupkg Publicación de un .nupkg.

Es posible que también quiera ampliar las funcionalidades del paquete o admitir otros escenarios, como se describe en los temas siguientes:

Por último, hay tipos de paquete adicionales que tener en cuenta: