Criar um pacote NuGet usando MSBuild

Ao criar um pacote NuGet de seu criar, você empacota essa funcionalidade em um componente que pode ser compartilhado e usado por uma infinidade de outros desenvolvedores. Este artigo descreve como criar um pacote usando MSBuild. O MSBuild vem pré-instalado com todas as cargas de trabalho do Visual Studio que contêm o NuGet. Além disso, você também pode usar o MSBuild por meio da CLI do dotnet com dotnet msbuild.

Para projetos .NET Core e .NET Standard que usam projetos no formato de estilo SDK e quaisquer outros estilos SDK, o NuGet usa as informações do arquivo de projeto diretamente para criar um pacote. Para projetos que não são de estilo SDK e que usam <PackageReference>, o NuGet também usa o arquivo de projeto para criar um pacote.

Projetos de estilo SDK têm a funcionalidade de empacotamento disponível por padrão. Para projetos de PackageReference que não são de estilo SDK, você precisa adicionar o pacote NuGet.Build.Tasks.Pack às dependências do projeto. Para obter informações detalhadas sobre os destinos de empacotamento do MSBuild, confira Empacotamento e restauração do NuGet como destinos do MSBuild.

O comando que cria um pacote, msbuild -t:pack, é a funcionalidade equivalente a dotnet pack.

Importante

Este tópico se aplica a projetos com estilo SDK, normalmente projetos do .NET Core e do .NET Standard, e a projetos que não são de estilo SDK que usam PackageReference.

Definir propriedades

As propriedades a seguir são necessárias para criar um pacote.

  • PackageId, o identificador de pacotes, que deve ser exclusivo na galeria que hospeda o pacote. Se esse campo não for especificado, o valor padrão será AssemblyName.
  • Version, um número de versão específico na forma Principal.Secundário.Patch[-Sufixo] em que -Sufixo identifica as versões de pré-lançamento. Se esse campo não for especificado, o valor padrão será 1.0.0.
  • O título do pacote como ele deve aparecer no host (como nuget.org)
  • Authors, informações de autor e proprietário. Se esse campo não for especificado, o valor padrão será AssemblyName.
  • Company, o nome da empresa. Se esse campo não for especificado, o valor padrão será AssemblyName.

Além disso, se você estiver empacotando projetos de estilo não SDK que usam PackageReference, o seguinte é necessário:

  • PackageOutputPath, a pasta de saída do pacote gerado ao chamar o pacote.

No Visual Studio, é possível definir esses valores nas propriedades do projeto (clique com o botão direito do mouse no projeto no Gerenciador de Soluções, escolha Propriedades e selecione a guia Pacote). Você também pode definir essas propriedades diretamente nos arquivos do projeto (.csproj).

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

Importante

Dê ao pacote um identificador exclusivo em nuget.org ou qualquer origem de pacote que estiver usando.

O exemplo a seguir mostra um arquivo de projeto simples e completo com essas propriedades incluídas.

<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>

Defina também as propriedades opcionais, como Title, PackageDescription e PackageTags, conforme descrito em Destinos do pacote MSBuild, Controlar ativos de dependência e Propriedades de metadados do NuGet.

Observação

Para pacotes compilados para consumo público, preste atenção especial à propriedade PackageTags, à medida que as marcas ajudam outras pessoas a localizar o pacote e entender o que ele faz.

Para obter detalhes sobre como declarar dependências e especificar números de versão, consulte Referências de pacote em arquivos de projeto e Controle de versão do pacote. Também é possível extrair ativos de dependências diretamente no pacote usando os atributos <IncludeAssets> e <ExcludeAssets>. Para saber mais, confira Controlar ativos de dependência.

Adicionar um campo de descrição opcional

A descrição opcional do pacote aparece na guia LEIAME da página nuget.org do pacote. A descrição é transferida do <Description> no arquivo de projeto ou do $description no arquivo .nuspec.

O exemplo a seguir mostra um Description no arquivo .csproj para um pacote .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://learn.microsoft.com/azure/storage/
      Microsoft Azure Storage REST API Reference - https://learn.microsoft.com/rest/api/storageservices/
      REST API Reference for Blob Service - https://learn.microsoft.com/rest/api/storageservices/blob-service-rest-api
    </Description>
  </PropertyGroup>
</Project>

Escolher um identificador de pacote exclusivo e definir o número de versão

O identificador do pacote e o número de versão identificam de forma exclusiva o código exato que está contido no pacote.

Siga estas práticas recomendadas para criar o identificador do pacote:

  • O identificador deve ser exclusivo em nuget.org e em todos os outros locais que hospedam o pacote. Para evitar conflitos, um bom padrão é usar o nome da sua empresa como a primeira parte do identificador.

  • Siga uma convenção de nomenclatura semelhante a namespaces do .NET, usando a notação de pontos. Por exemplo, use Contoso.Utility.UsefulStuff em vez de Contoso-Utility-UsefulStuff ou Contoso_Utility_UsefulStuff. Também é útil para os consumidores se você corresponder o identificador do pacote ao namespace usado pelo código.

  • Se você produzir um pacote de código de exemplo que demonstre como usar outro pacote, anexe .Sample como um sufixo ao identificador, como em Contoso.Utility.UsefulStuff.Sample.

    O pacote de exemplo tem uma dependência do pacote original. Ao criar o pacote de exemplo, adicione <IncludeAssets> com o valor contentFiles. Na pasta content, organize o código de exemplo em uma pasta chamada \Samples\<identificador>, como \Samples\Contoso.Utility.UsefulStuff.Sample.

Siga estas melhores práticas para definir a versão do pacote:

  • Em geral, defina a versão do pacote para corresponder à versão do projeto ou assembly, embora isso não seja estritamente necessário. Igualar a versão é uma questão simples quando você limita um pacote a um único assembly. O NuGet em si lida com versões do pacote ao resolver as dependências, não versões de assembly.

  • Ao usar um esquema de versão não padrão, considere as regras de controle de versão do NuGet, conforme explicado em Controle de versão de pacotes. O NuGet é em grande parte compatível com o Controle de Versão Semântico 2.0.0.

Observação

Para obter mais informações sobre a resolução de dependências, confira Resolução de dependências com PackageReference. Para obter informações que podem ajudar a entender o controle de versão, confira esta série de postagens no blog.

Adicionar o pacote NuGet.Build.Tasks.Pack

Se você estiver usando o MSBuild com um projeto que não é de estilo SDK e com PackageReference, adicione o pacote NuGet.Build.Tasks.Pack ao projeto.

  1. Abra o arquivo de projeto e adicione o seguinte após o elemento <PropertyGroup>:

    <ItemGroup>
      <!-- ... -->
      <PackageReference Include="NuGet.Build.Tasks.Pack" Version="6.7.0" PrivateAssets="all" />
      <!-- ... -->
    </ItemGroup>
    
  2. Abra um prompt de comando do Desenvolvedor (na caixa Pesquisar, digite Prompt de Comando do Desenvolvedor).

    Você normalmente deseja iniciar o Prompt de Comando do Desenvolvedor para Visual Studio usando o menu Iniciar, pois ele estará configurado com todos os caminhos necessários para o MSBuild.

  3. Alterne para a pasta que contém o arquivo de projeto e digite o seguinte comando para instalar o pacote NuGet.Build.Tasks.Pack.

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

    Verifique se a saída de MSBuild indica que a compilação foi concluída com êxito.

Execute o comando msbuild -t:pack

Para compilar um pacote do NuGet (um arquivo .nupkg) do projeto, execute o comando msbuild -t:pack, que também compila o projeto automaticamente:

No prompt de comando do Desenvolvedor para Visual Studio, digite o seguinte comando:

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

A saída mostra o caminho até o arquivo .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

Gerar pacote automaticamente no build

Para executar msbuild -t:pack automaticamente ao compilar ou restaurar o projeto, adicione a seguinte linha ao arquivo de projeto em <PropertyGroup>:

<GeneratePackageOnBuild>true</GeneratePackageOnBuild>

Ao executar msbuild -t:pack em uma solução, isso empacota todos os projetos na solução que são empacotáveis (a propriedade <IsPackable> é definida como true).

Observação

Ao gerar automaticamente o pacote, o tempo de empacotamento aumenta o tempo de compilação do seu projeto.

Instalação do pacote de teste

Antes de publicar um pacote, geralmente é recomendável testar o processo de instalação de um pacote em um projeto. Os testes garantem que os arquivos todos terminem em seus lugares corretos no projeto.

Você pode testar instalações manualmente no Visual Studio ou na linha de comando usando as etapas de instalação do pacote normais.

Importante

Os pacotes são imutáveis. Se corrigir um problema, altere o conteúdo do pacote e empacote novamente. Quando você testar novamente, ainda estará usando a versão antiga do pacote até que limpe sua pasta de pacotes globais. Isso é especialmente relevante ao testar pacotes que não usam um rótulo de pré-lançamento exclusivo em cada compilação.

Próximas etapas

Depois de criar um pacote, que é um arquivo .nupkg, você pode publicá-lo na galeria de sua escolha conforme descrito em Publicar um pacote.

Você também poderá estender os recursos do seu pacote ou dar suporte a outros cenários conforme descrito nos tópicos a seguir:

Por fim, há tipos de pacote adicionais a serem considerados: