Создание пакета с помощью CLI nuget.exe

Независимо от назначения вашего пакета или содержащегося в нем кода, с помощью одного из средств CLI (nuget.exe или dotnet.exe) вы можете создать компонент, которым можно поделиться с любым количеством разработчиков для совместного использования. Инструкции по установке средств CLI для NuGet см. в статье Установка клиентских средств NuGet. Обратите внимание на то, что средство CLI не входит в состав Visual Studio по умолчанию.

С технической точки зрения, пакет NuGet — это просто ZIP-файл, расширение которого изменено на .nupkg и содержимое которого соответствует определенным соглашениям. В этом разделе подробно описывается создание пакета, в котором соблюдаются эти соглашения.

Создание пакета начинается с подготовки скомпилированного кода (сборок), символов и других файлов, которые должны быть включены в пакет (см. раздел Процесс создания пакета). Этот процесс не зависит от компиляции и других задач по созданию файлов для пакета, хотя вы можете использовать информацию из файла проекта для синхронизации скомпилированных сборок и пакетов.

Внимание

Эта статья применяется к проектам со стилем, отличным от пакетов SDK, то есть не таких как проекты .NET Core и .NET Standard, для которых используются Visual Studio 2017 и NuGet 4.0 и более поздних версий.

Выбор сборок для добавления в пакет

Большинство пакетов общего назначения содержат одну или несколько сборок, которые другие разработчики могут использовать в собственных проектах.

  • Как правило, для каждой сборки лучше создавать собственный пакет NuGet, если эти сборки используются независимо. Например, если есть сборка Utilities.dll, которая зависит от сборки Parser.dll, но сборка Parser.dll также полезна сама по себе, создайте для каждой из этих сборок отдельный пакет. Это позволит разработчикам использовать Parser.dll независимо от Utilities.dll.

  • Если библиотека состоит из нескольких сборок, которые не используются сами по себе, то их предпочтительнее объединить в одном пакете. В продолжение предыдущего примера, если сборка Parser.dll содержит код, который используется только сборкой Utilities.dll, то сборку Parser.dll лучше включить в тот же пакет.

  • Аналогичным образом, если сборка Utilities.dll зависит от сборки Utilities.resources.dll, которая не используется сама по себе, включите их в один пакет.

Ресурсы представляют собой особый случай. Когда пакет устанавливается в проекте, NuGet автоматически добавляет ссылки на библиотеки DLL сборок в пакете, кроме тех из них, в именах которых есть .resources.dll, так как они считаются локализованными вспомогательными сборками (см. раздел Создание локализованных пакетов). По этой причине следует избегать использования .resources.dll в именах файлов пакета, которые содержат важный код.

Если библиотека содержит сборки COM-взаимодействия, следуйте дополнительным указаниям в разделе Создание пакетов, содержащих сборки COM-взаимодействия.

Назначение и структура файла NUSPEC

После того как вы решите, какие файлы нужно включить в пакет, следует создать манифест пакета в XML-файле .nuspec.

Манифест служит следующим целям:

  1. Описывает содержимое пакета и сам включается в него.
  2. Управляет созданием пакета и предоставляет диспетчеру NuGet указания по установке пакета в проекте. Например, в манифесте определяются другие зависимости пакета, чтобы диспетчер NuGet мог также установить их при установке основного пакета.
  3. Содержит обязательные и необязательные свойства, как описано ниже. Полные сведения, включая описание свойств, которые не упомянуты в этом разделе, см. в справочнике по файлам NUSPEC.

Обязательные свойства:

  • идентификатор пакета, который должен быть уникальным в пределах коллекции, содержащей пакет;
  • определенный номер версии в формате основной_номер.дополнительный_номер.исправление[-суффикс], где -суффикс указывает на предварительные версии;
  • название пакета, которое должно отображаться на сайте размещения (например, nuget.org);
  • сведения об авторе и владельце;
  • подробное описание пакета.

Часто используемые необязательные свойства:

Ниже приведен типичный (но вымышленный) файл .nuspec с комментариями, описывающими свойства.

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
    <metadata>
        <!-- Identifier that must be unique within the hosting gallery -->
        <id>Contoso.Utility.UsefulStuff</id>

        <!-- Package version number that is used when resolving dependencies -->
        <version>1.8.3</version>

        <!-- Authors contain text that appears directly on the gallery -->
        <authors>Dejana Tesic, Rajeev Dey</authors>

        <!-- 
            Owners are typically nuget.org identities that allow gallery
            users to easily find other packages by the same owners.  
        -->
        <owners>dejanatc, rjdey</owners>
        
         <!-- Project URL provides a link for the gallery -->
        <projectUrl>http://github.com/contoso/UsefulStuff</projectUrl>

         <!-- License information is displayed on the gallery -->
        <license type="expression">Apache-2.0</license>
        

        <!-- Icon is used in Visual Studio's package manager UI -->
        <icon>icon.png</icon>

        <!-- 
            If true, this value prompts the user to accept the license when
            installing the package. 
        -->
        <requireLicenseAcceptance>false</requireLicenseAcceptance>

        <!-- Any details about this particular release -->
        <releaseNotes>Bug fixes and performance improvements</releaseNotes>

        <!-- 
            The description can be used in package manager UI. Note that the
            nuget.org gallery uses information you add in the portal. 
        -->
        <description>Core utility functions for web applications</description>

        <!-- Copyright information -->
        <copyright>Copyright ©2016 Contoso Corporation</copyright>

        <!-- Tags appear in the gallery and can be used for tag searches -->
        <tags>web utility http json url parsing</tags>

        <!-- Dependencies are automatically installed when the package is installed -->
        <dependencies>
            <dependency id="Newtonsoft.Json" version="9.0" />
        </dependencies>
    </metadata>

    <!-- A readme.txt to display when the package is installed -->
    <files>
        <file src="readme.txt" target="" />
        <file src="icon.png" target="" />
    </files>
</package>

Подробные сведения об объявлении зависимостей и указании номеров версий см. в разделе packages.config и Управление версиями пакета. Доступ к ресурсам зависимостей в пакете можно также предоставлять напрямую с помощью атрибутов include и exclude элемента dependency. См. подраздел "Зависимости" в разделе Справочник по файлам NUSPEC.

Так как манифест включается в пакет, создаваемый на его основе, вы можете получить дополнительные примеры, изучив существующие пакеты. Хорошим их источником может служить папка global-packages на компьютере, расположение которой можно получить с помощью следующей команды:

nuget locals -list global-packages

Перейдите в любую папку пакет\версия, скопируйте файл .nupkg в файл .zip, затем откройте этот файл .zip и изучите содержимое файла .nuspec в нем.

Примечание.

При создании файла .nuspec из проекта Visual Studio манифест содержит токены, которые заменяются сведениями из проекта при сборке пакета. См. раздел Создание файла NUSPEC на основе проекта Visual Studio.

Создание NUSPEC-файла

Создание полного манифеста, как правило, начинается с базового файла .nuspec, который создается одним из следующих способов на основе:

Затем нужно отредактировать файл вручную так, чтобы он описывал содержимое итогового пакета.

Внимание

Автоматически формируемые файлы .nuspec содержат заполнители, которые нужно изменить перед созданием пакета с помощью команды nuget pack. Если файл .nuspec содержит заполнители, эта команда завершается сбоем.

На основе рабочего каталога, соответствующего соглашениям

Так как пакет NuGet — это просто ZIP-файл, расширение которого изменено на .nupkg, зачастую проще всего создать нужную структуру папок в локальной файловой системе, а затем создать файл .nuspec на основе этой структуры. Команда nuget pack автоматически добавляет все файлы, имеющиеся в этой структуре папок (кроме папок, начинающихся с ., что позволяет иметь закрытые файлы в этой же структуре).

Преимущество такого подхода в том, что вам не нужно указывать в манифесте файлы, которые требуется включить в пакет (как описано далее в этом разделе). В процессе сборки можно создать структуру папок, которая будет в точности перенесена в пакет, и легко включить в него другие файлы, которые в противном случае не были бы добавлены в проект:

  • содержимое и исходный код, которые следует внедрить в конечный проект;
  • Скрипты PowerShell
  • преобразования существующих файлов конфигурации и исходного кода в проекте.

Ниже представлены соглашения в отношении папок.

Папка Description Действие при установке пакета
(корневая) Расположение файла readme.txt При установке пакета в Visual Studio отображается файл readme.txt в корневой папке проекта.
lib/{tfm} Файлы сборки (.dll), документации (.xml) и символов (.pdb) для данного моникера целевой платформы (TFM) Сборки добавляются как ссылки для использования во время компиляции или выполнения. Файлы .xml и .pdb копируются в папки проекта. Сведения о создании вложенных папок для определенных целевых платформ см. в разделе Поддержка нескольких целевых платформ.
ref/{tfm} Файлы сборки (.dll) и символов (.pdb) для определенного моникера целевой платформы (TFM) Сборки добавляются как ссылки для использования только во время компиляции. Поэтому в папку bin проекта ничего не копируется.
runtimes Файлы сборки (.dll), символов (.pdb) и машинных ресурсов (.pri) для определенной архитектуры Сборки добавляются как ссылки для использования только во время выполнения. Остальные файлы копируются в папки проекта. В папке /ref/{tfm} всегда должна быть соответствующая сборка (TFM) для AnyCPU, чтобы предоставить соответствующие сборки, используемые во время компиляции. См. раздел Поддержка нескольких целевых платформ.
content Произвольные файлы Содержимое копируется в корневую папку проекта. Папку content можно представить как корневую папку целевого приложения, которое будет использовать пакет. Чтобы пакет добавил изображение в папку /images приложения, поместите это изображение в папку content/images пакета.
сборка Файлы MSBuild .targets и .props(3.x+). Автоматическое добавление в проект.
buildMultiTargeting Файлы MSBuild .targets и .props(4.0+) для кроссплатформенного определения. Автоматическое добавление в проект.
buildTransitive Файлы MSBuild .targets и .props(5.0+), которые можно транзитивно передавать в любой соответствующий проект. См. об этой функции. Автоматическое добавление в проект.
средства Скрипты и программы PowerShell, доступные из консоли диспетчера пакетов Папка tools добавляется в переменную среды PATH только для консоли диспетчера пакетов (в частности, она не добавляется в переменную PATH для среды MSBuild при сборке проекта).

Так как в структуре папок может быть сколько угодно сборок для любого числа целевых платформ, этот метод обязателен при создании пакетов, поддерживающих несколько платформ.

После того как вы подготовите нужную структуру папок, выполните в ней следующую команду, чтобы создать файл .nuspec:

nuget spec

Созданный файл .nuspec не содержит явных ссылок на файлы в структуре папок. NuGet автоматически включает все файлы при создании пакета. Однако вам необходимо отредактировать значения-заполнители в других частях манифеста.

На основе библиотеки DLL сборки

В такой простой ситуации, как создание пакета на основе сборки, вы можете создать файл .nuspec из содержащихся в сборке метаданных с помощью следующей команды:

nuget spec <assembly-name>.dll

При использовании такого формата ряд заполнителей в манифесте заменяется конкретными значениями из сборки. Например, свойству <id> присваивается имя сборки, а свойству <version> — ее версия. Однако остальные свойства в манифесте не имеют соответствующих значений в сборке и поэтому по-прежнему содержат заполнители.

На основе проекта Visual Studio

Создавать файл .nuspec на основе файла .csproj или .vbproj удобно, так как ссылки на другие пакеты, установленные в проекте, как и на зависимости, создаются автоматически. Просто выполните следующую команду в папке, в которой находится файл проекта:

# Use in a folder containing a project file <project-name>.csproj or <project-name>.vbproj
nuget spec

Получившийся файл <project-name>.nuspec содержит токены, которые заменяются во время создания пакета значениями их проекта, включая ссылки на другие пакеты, которые уже установлены.

Если у вас есть зависимости пакетов для включения в файл .nuspec, используйте вместо этого nuget pack и получите файл .nuspec из созданного файла .nupkg. Например, используйте следующую команду.

# Use in a folder containing a project file <project-name>.csproj or <project-name>.vbproj
nuget pack myproject.csproj

Токен отделяется символами $ с обеих сторон свойства проекта. Например, значение <id> в созданном таким образом манифесте, как правило, имеет следующий вид:

<id>$id$</id>

Этот токен заменяется значением AssemblyName из файла проекта во время упаковки. Точные сведения о том, как значения из проекта сопоставляются с токенами .nuspec, см. в справочнике по токенам замены.

Токены избавляют от необходимости изменять критически важные значения, такие как номер версии, в файле .nuspec при обновлении пакета. (При необходимости токены всегда можно заменить на конкретные значения.)

Обратите внимание на то, что при работе с проектом Visual Studio доступно несколько дополнительных параметров создания пакета, которые описываются далее в подразделе Выполнение команды nuget pack для создания файла NUPKG.

Пакеты на уровне решения

Только в NuGet 2.x. Недоступно в NuGet 3.0 и более поздних версиях.

В NuGet 2.x поддерживалась концепция пакетов на уровне решения, которые устанавливают средства или дополнительные команды для консоли диспетчера команд (содержимое папки tools), но не добавляют ссылки, содержимое или настройки сборки в проекты решения. Такие пакеты не содержат файлов непосредственно в папках lib, content или build, а их зависимости не содержат файлов в соответствующих папках lib, content или build.

NuGet отслеживает установленные пакеты уровня решения в файле packages.config в папке .nuget, а не в файле packages.config проекта.

нового файла со значениями по умолчанию.

Следующая команда создает манифест по умолчанию с заполнителями, формируя надлежащую структуру файлов:

nuget spec [<package-name>]

Если не указать параметр <package-name>, получившийся файл будет иметь имя Package.nuspec. Если указать имя, например Contoso.Utility.UsefulStuff, файл будет иметь имя Contoso.Utility.UsefulStuff.nuspec.

Полученный файл .nuspec содержит заполнители для значений, например projectUrl. Прежде чем использовать этот файл для создания итогового файла .nupkg, его необходимо отредактировать.

Выбор уникального идентификатора пакета и задание номера версии

Идентификатор пакета (элемент <id>) и номер версии (элемент <version>) — два самых важных значения в манифесте, так как они однозначно определяют код, содержащийся в пакете.

Рекомендации в отношении идентификатора пакета

  • Уникальность. Идентификатор должен быть уникальным в пределах nuget.org или другой коллекции, в которой размещается пакет. Прежде чем задавать идентификатор, проверьте, не используется ли оно уже в соответствующей коллекции. Во избежание конфликтов рекомендуется использовать в качестве первой части идентификатора название организации, например Contoso..
  • Имена в стиле пространств имен. Используйте шаблон, по которому строятся имена пространств имен в .NET, используя нотацию с точками, а не с дефисами. Например, используйте идентификатор Contoso.Utility.UsefulStuff вместо Contoso-Utility-UsefulStuff или Contoso_Utility_UsefulStuff. Пользователям также удобно, когда идентификатор пакета соответствует пространствам имен, используемым в коде.
  • Образцы пакетов. Если вы создаете пакет с образцом кода, демонстрирующим использование другого пакета, добавьте к идентификатору суффикс .Sample, например Contoso.Utility.UsefulStuff.Sample. (Пример пакета, конечно, имеет зависимость от другого пакета.) При создании примера пакета используйте ранее описанный выше метод рабочего каталога на основе соглашения. В папке content разместите код образца в папке с именем \Samples\<identifier>, например \Samples\Contoso.Utility.UsefulStuff.Sample.

Рекомендации в отношении версии пакета

  • Как правило, версия пакета должна соответствовать версии библиотеки, хотя это не строгое требование. Это легко реализовать, если пакет ограничен единственной сборкой, как было описано выше в подразделе Выбор сборок для добавления в пакет. В целом помните, что при разрешении зависимостей диспетчер NuGet ориентируется на версии пакетов, а не на версии сборок.
  • При применении нестандартной схемы версий обязательно учитывайте правила управления версиями в NuGet, которые изложены в разделе Управление версиями пакета.

Разобраться в принципах управления версиями также может помочь следующая серия коротких записей блога:

Добавление файла сведений и других файлов

Чтобы явным образом указать файлы, которые следует включить в пакет, используйте узел <files> в файле .nuspec, который находится после тега <metadata>:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
    <metadata>
    <!-- ... -->
    </metadata>
    <files>
        <!-- Add a readme -->
        <file src="readme.txt" target="" />

        <!-- Add files from an arbitrary folder that's not necessarily in the project -->
        <file src="..\..\SomeRoot\**\*.*" target="" />
    </files>
</package>

Совет

При использовании подхода на основе рабочего каталога, соответствующего соглашениям, файл readme.txt можно поместить в корневую папку пакета, а другое содержимое — в папку content. Элементы <file> в манифесте не требуются.

Если в корневую папку пакета добавлен файл с именем readme.txt, Visual Studio отображает содержимое этого файла в виде обычного текста сразу после установки пакета напрямую. (Файлы сведений не отображаются для пакетов, устанавливаемых как зависимости.) Например, вот как выглядит файл сведений для пакета HtmlAgilityPack:

The display of a readme file for a NuGet package upon installation

Примечание.

Если узел <files> в файле .nuspec пуст, NuGet включает в пакет только содержимое из папки lib.

Включение в пакет свойств и целей MSBuild

В некоторых случаях в проекты, использующие пакет, необходимо добавить пользовательские целевые объекты сборки или свойства, например, если во время сборки должно запускаться пользовательское средство или процесс. Дополнительные сведения о свойствах и целевых объектах MSBuild в пакетах NuGet.

Создайте <package_id>.targets или <package_id>.props (например, Contoso.Utility.UsefulStuff.targets) в папках сборки проекта.

Затем в файле .nuspec укажите ссылки на эти файлы в узле <files>:

<?xml version="1.0"?>
<package >
    <metadata minClientVersion="2.5">
    <!-- ... -->
    </metadata>
    <files>
        <!-- Include everything in \build -->
        <file src="build\**" target="build" />

        <!-- Other files -->
        <!-- ... -->
    </files>
</package>

После добавления пакетов в проект NuGet автоматически включит эти свойства и целевые объекты.

Выполнение команды nuget pack для создания файла NUPKG

Чтобы создать пакет на основе сборки или рабочего каталога, соответствующего соглашениям, выполните команду nuget pack, указав файл .nuspec, где <project-name> необходимо заменить на имя файла:

nuget pack <project-name>.nuspec

При использовании проекта Visual Studio выполните команду nuget pack, указав файл проекта. В результате автоматически загрузится файл .nuspec проекта, и все токены в нем будут заменены значениями из файла проекта.

nuget pack <project-name>.csproj

Примечание.

Использование файла проекта напрямую является необходимым для замены токенов, так как проект является источником значений токенов. Замена токенов не производится при использовании команды nuget pack с файлом .nuspec.

В любом случае команда nuget pack исключает папки, начинающиеся с точки, например .git или .hg.

NuGet указывает, есть ли в файле .nuspec ошибки, требующие исправления, например, если вы забыли изменить значения-заполнители в манифесте.

После успешного выполнения команды nuget pack вы получаете файл .nupkg, который можно опубликовать в подходящей коллекции, как описано в разделе Публикация пакета.

Совет

После создания пакета его полезно просмотреть, открыв в средстве Обозреватель пакетов. В нем в графической форме представлено содержимое пакета и его манифест. Вы также можете переименовать полученный файл .nupkg в файл .zip и просмотреть его содержимое напрямую.

Дополнительные параметры

С командой nuget pack можно использовать различные параметры командной строки для исключения файлов, переопределения номера версии в манифесте, изменения папки выходных данных и совершения других действий. Полный список параметров см. в справочнике по команде pack.

Ниже приводятся некоторые часто используемые с проектами Visual Studio параметры.

  • Проекты, на которые указывают ссылки. Если проект ссылается на другие проекты, вы можете включить их в пакет или добавить в качестве зависимостей с помощью параметра -IncludeReferencedProjects:

    nuget pack MyProject.csproj -IncludeReferencedProjects
    

    Включение является рекурсивным, поэтому если MyProject.csproj ссылается на проекты B и C, а они ссылаются на проекты D, E и F, в пакет включаются файлы из проектов B, C, D, E и F.

    Если в проекте, на который указывает ссылка, есть собственный файл .nuspec, NuGet вместо этого добавляет проект как зависимость. Такой проект необходимо упаковать и опубликовать отдельно.

  • Конфигурация сборки. По умолчанию NuGet использует стандартную конфигурацию сборки, указанную в файле проекта. Обычно это конфигурация Debug. Чтобы упаковать файлы из другой конфигурации сборки, например Release, используйте параметр -properties, указав конфигурацию:

    nuget pack MyProject.csproj -properties Configuration=Release
    
  • Символы. Чтобы включить символы, позволяющие пользователям осуществлять пошаговое выполнение кода в пакете, используйте параметр -Symbols:

    nuget pack MyProject.csproj -symbols
    

Тестирование установки пакета

Перед публикацией пакета, как правило, необходимо протестировать процесс его установки в проекте. Это позволяет убедиться в том, что все необходимые файлы помещаются в нужные места.

Установку можно протестировать вручную в Visual Studio или в командной строке, выполнив стандартную процедуру установки пакета.

Для автоматического тестирования выполните указанные ниже основные действия.

  1. Скопируйте файл .nupkg в локальную папку.
  2. Добавьте эту папку в источники пакета с помощью команды nuget sources add -name <name> -source <path> (см. описание команды nuget sources). Обратите внимание на то, что на каждом компьютере этот локальный источник необходимо задать только один раз.
  3. Установите пакет из источника с помощью команды nuget install <packageID> -source <name>, где <name> соответствует имени источника, предоставленному команде nuget sources. Указание источника позволяет гарантировать, что пакет будет устанавливаться только из него.
  4. В файловой системе проверьте, правильно ли установились файлы.

Next Steps

Создав пакет, то есть файл .nupkg, вы можете опубликовать его в любой коллекции на ваш выбор, как описано в разделе Публикация пакета.

Вы также можете расширить возможности пакета или обеспечить поддержку других сценариев, как описано в следующих разделах:

Наконец, существуют дополнительные типы пакетов, о которых нужно знать: