Crear un paquete NuGet usando 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 equivalente funcionalmente 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 Principal.Secundaria.Revisión[-Sufijo] donde -Sufijo identifica las versiones preliminares. 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 Title, PackageDescription y PackageTags, tal como se describe en los destinos de paquetes de MSBuild, la sección Controlar los recursos de dependencias y Propiedades de los metadatos de NuGet.

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 aparece en la pestaña LÉAME de la página nuget.org del paquete. La descripción se extrae de <Description> en el archivo de proyecto o de $description en el archivo .nuspec.

El siguiente ejemplo muestra una Description en el archivo .csproj para un paquete .NET:

<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://video2.skills-academy.com/azure/storage/
      Microsoft Azure Storage REST API Reference - https://video2.skills-academy.com/rest/api/storageservices/
      REST API Reference for Blob Service - https://video2.skills-academy.com/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 identifican de forma exclusiva el código exacto que contiene el paquete.

Siga estos procedimientos recomendados para crear el identificador del paquete:

  • El identificador debe ser único en nuget.org y en todas las demás ubicaciones que hospeden el paquete. Para evitar conflictos, una buena pauta es utilizar el nombre de su empresa como primera parte del identificador.

  • Siga una convención de nomenclatura similar a la de los espacios de nombres .NET, en la que se utilice la notación por puntos. Por ejemplo, use Contoso.Utility.UsefulStuff en lugar de Contoso-Utility-UsefulStuff o Contoso_Utility_UsefulStuff. También es útil para los consumidores que el identificador del paquete coincida con el espacio de nombres que utiliza el código.

  • Si produce un paquete de código de ejemplo que demuestre cómo utilizar otro paquete, añada .Sample al identificador, como en Contoso.Utility.UsefulStuff.Sample.

    El paquete de ejemplo depende del paquete original. Al crear el paquete de muestra, añada <IncludeAssets> con el valor contentFiles. En la carpeta de contenido, organice el código de ejemplo en una carpeta llamada \Muestras<identificador>, como \MuestrasContoso.Utilidad.UsefulStuff.Sample.

Siga este procedimiento recomendado para establecer la versión del paquete:

  • En general, establezca la versión del paquete para que coincida con la versión del proyecto o ensamblado, aunque esto no es estrictamente necesario. Hacer coincidir la versión es sencillo cuando se limita un paquete a un único ensamblado. El propio NuGet se ocupa de las versiones de los paquetes al resolver las dependencias, no de las versiones de los ensamblados.

  • Si utiliza un esquema de 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 el Versionamiento Semántico 2.0.0.

Nota:

Para más información sobre la resolución de dependencias, consulte Resolución de dependencias con PackageReference. Si desea información que le ayude a entender el versionado, 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="6.7.0" PrivateAssets="all" />
      <!-- ... -->
    </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 ejecute msbuild -t:pack en una solución, se empaquetarán todos los proyectos de la solución que lo permitan (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 haya creado un paquete, que es un archivo .nupkg, puede publicarlo en la galería de su elección como se describe en Publicación de un paquete.

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: