无论您的软件包执行什么功能或包含什么代码,您都可以使用 CLI 工具nuget.exe或dotnet.exe之一将该功能打包成组件,以便与其他开发人员共享和使用。 若要安装 NuGet CLI 工具,请参阅 安装 NuGet 客户端工具。 请注意,Visual Studio 不会自动包含 CLI 工具。
对于非 SDK 样式项目(通常是 .NET Framework 项目),请按照本文中所述的步骤创建包。 有关使用 Visual Studio 和
nuget.exeCLI 的分步说明,请参阅 创建和发布 .NET Framework 包。有关使用 SDK 样式格式的 .NET Core 和 .NET Standard 项目和其他任何 SDK 样式项目,请参阅 使用 dotnet CLI 创建 NuGet 包。
对于从
packages.configPackageReference 迁移到的项目,请使用 msbuild -t:pack。
从技术上讲,NuGet 包只是使用扩展名重命名 .nupkg 的 ZIP 文件,其内容与某些约定匹配。 本主题介绍创建满足这些约定的包的详细过程。
打包以编译的代码(程序集)、符号和/或其他要作为包传送的文件开始(请参阅 概述和工作流)。 此过程与编译或生成进入包的文件无关,尽管可以从项目文件中的信息进行绘制,以使编译的程序集和包保持同步。
重要
本主题适用于非 SDK 样式项目,通常是使用 Visual Studio 2017 及更高版本和 NuGet 4.0+ 的 .NET Core 和 .NET Standard 项目以外的项目。
确定要打包的程序集
大多数常规用途包包含一个或多个程序集,其他开发人员可以在自己的项目中使用这些程序集。
一般情况下,最好为每个 NuGet 包创建一个程序集,前提是每个程序集独立有用。 例如,如果你有一个
Utilities.dll依赖于Parser.dll,而Parser.dll本身很有用,那么应该为每个单独创建一个包。 这样,开发人员就可以独立于Utilities.dll使用Parser.dll。如果库由多个不独立有用的程序集组成,则可以将它们合并到一个包中。 使用前面的示例时,如果
Parser.dll包含仅由Utilities.dll使用的代码,那么将Parser.dll保留在同一个包中是可以的。同样,如果
Utilities.dll依赖于Utilities.resources.dll后者,后者本身又没有用处,那么请将两者放在同一个包中。
事实上,资源是一种特殊情况。 将包安装到项目中时,NuGet 会自动向包的 DLL 添加程序集引用, 不包括 那些被命名 .resources.dll 的程序集,因为它们假定是本地化附属程序集(请参阅 “创建本地化包”。 因此,请避免对包含基本包代码的文件使用 .resources.dll 。
如果您的库包含 COM 互操作程序集,请按照 使用 COM 互操作程序集创建包中的其他准则进行操作。
.nuspec 文件的角色和结构
了解要打包的文件后,下一步是在 XML 文件中创建包清单 .nuspec 。
清单:
- 描述包的内容,并包含在包中。
- 驱动包的创建,并指示 NuGet 如何将包安装到项目中。 例如,清单标识其他包依赖项,以便 NuGet 也可以在安装主包时安装这些依赖项。
- 包含必需属性和可选属性,如下所示。 有关确切的详细信息,包括此处未提及的其他属性,请参阅 .nuspec 参考。
必需属性:
- 包标识符,该标识符在承载包的库中必须是唯一的。
- Major.Minor.Patch[-Suffix] 中的特定版本号,其中 -Suffix 标识预发行版本
- 程序包标题,因为它应出现在主机上(如 nuget.org)
- 作者和所有者信息。
- 包的详细说明。
常见的可选属性:
- 发行说明
- 版权信息
- Visual Studio 中包管理器 UI 的简短说明
- 区域设置 ID
- 项目 URL
- 许可证作为表达式或文件(
licenseUrl已弃用,改用licensenuspec 元数据元素 ) - 图标文件(
iconUrl已不再推荐使用,请改用iconnuspec 元数据元素) - 依赖项和引用列表
- 有助于图库搜索的标记
下面是一个典型的(但虚构) .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 和 包版本控制。 还可以通过在dependency元素上使用include和exclude属性,直接在包中显示依赖项中的资源。 请参阅 .nuspec 参考 - 依赖项。
由于清单包含在从中创建的包中,因此可以通过检查现有包来查找任意数量的附加示例。 良好的源是计算机上的 全局包 文件夹,该文件夹的位置由以下命令返回:
nuget locals -list global-packages
进入任何 package\version 文件夹,将 .nupkg 文件复制到文件 .zip ,然后打开该文件 .zip 并检查 .nuspec 其中的文件。
注释
从 Visual Studio 项目创建 .nuspec 时,清单文件包含在生成包时替换为项目中信息的令牌。 请参阅 从 Visual Studio 项目创建 .nuspec。
创建 .nuspec 文件
创建完整清单通常从通过以下方法之一生成的基本 .nuspec 文件开始:
然后手动编辑文件,以便描述最终包中所需的确切内容。
重要
生成的.nuspec文件包含占位符nuget pack,需要在使用命令创建包之前进行修改。 如果该命令包含任何占位符,该 .nuspec 命令将失败。
从基于约定的工作目录
由于 NuGet 包只是使用扩展名重命名 .nupkg 的 ZIP 文件,因此通常最容易在本地文件系统上创建所需的文件夹结构,然后直接从该结构创建 .nuspec 文件。 然后,该 nuget pack 命令会自动添加该文件夹结构中的所有文件(不包括任何以 .开头的文件夹,允许将专用文件保存在同一结构中)。
此方法的优点是,无需在清单中指定要包含在包中的文件(如本主题稍后所述)。 只需让构建过程生成进入包的准确文件夹结构,并且可以轻松包含其他可能不属于项目的文件。
- 应注入目标项目的内容和源代码。
- PowerShell 脚本
- 对项目中现有配置和源代码文件的更改。
文件夹约定如下所示:
| 文件夹 | Description | 安装包时执行的操作 |
|---|---|---|
| (root) | readme.txt 的位置 | 安装包时,Visual Studio 会在包根目录中显示 readme.txt 文件。 |
| lib/{tfm} | 给定目标框架标识符(TFM)的程序集(.dll)、文档(.xml)和符号(.pdb)文件 |
程序集被添加为编译和运行时的引用,并且 .xml 和 .pdb 被复制到项目文件夹中。 请参阅 支持多个目标框架,以了解如何创建特定框架的子文件夹。 |
| ref/{tfm} | 给定目标框架标识符(TFM)的程序集(.dll)和符号文件(.pdb) |
程序集仅在编译期间作为引用添加,因此不会将任何内容复制到项目的 bin 目录中。 |
| 运行时 | 特定于体系结构的程序集 (.dll)、符号 (.pdb) 和本机资源 (.pri) 文件 |
程序集仅作为运行时的引用添加;其他文件将复制到项目文件夹中。 应始终在/ref/{tfm}文件夹下有一个相应的AnyCPU(TFM)特定程序集,以提供相应的编译时程序集。 请参阅 支持多个目标框架。 |
| 内容 | 任意文件 | 内容将复制到项目根目录。 将 内容 文件夹视为最终使用包的目标应用程序的根目录。 若要让包在应用程序的 /images 文件夹中添加图像,请将它放在包 的内容/图像 文件夹中。 |
| 内部版本 |
(3.x+) MSBuild .targets 和 .props 文件 |
自动被插入到项目中。 |
| buildMultiTargeting |
(4.0+) 用于跨框架目标的 MSBuild .targets 和 .props 文件 |
自动插入项目中。 |
| buildTransitive |
(5.0+) MSBuild .targets 和 .props 可传递流向任何使用的项目的文件。 请参阅 功能 页。 |
自动插入到项目中。 |
| tools | 可从包管理器控制台访问的 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,并从生成的 .nupkg 文件中获取 .nuspec 文件。 例如,使用以下命令。
# 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 )安装工具或其他命令,但不向解决方案中的任何项目添加引用、内容或生成自定义项。 此类包在其直接libcontent或build文件夹中不包含任何文件,并且其依赖项中没有其各自的lib文件或contentbuild文件夹。
NuGet 在 .nuget 文件夹中的 packages.config 文件记录已安装的解决方案级别包,而不是在项目的 packages.config 文件中。
具有默认值的新文件
以下命令创建包含占位符的默认清单,这可确保从正确的文件结构开始:
nuget spec [<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 包的自述文件显示如下:
注释
如果在 .nuspec 文件中包含一个空的 <files> 节点,NuGet 就不会在包中包含其他内容,仅包含 lib 文件夹中的内容。
在软件包中包含 MSBuild 道具及任务目标
在某些情况下,你可能希望在使用包的项目中添加自定义生成目标或属性,例如在生成过程中运行自定义工具或进程。 可以在 NuGet 包中了解有关 MSBuild 属性和目标的详细信息
在项目的生成文件夹中创建 <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 包以生成 .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。 若要从其他构建配置(如发布)打包文件,请使用带有配置的
-properties选项:nuget pack MyProject.csproj -properties Configuration=Release符号:若要包含允许使用者在调试器中单步执行包代码的符号,请使用
-Symbols以下选项:nuget pack MyProject.csproj -symbols
测试包安装
在发布包之前,通常需要测试将包安装到项目中的过程。 测试确保必要的文件最终都正确地放置在项目中。
可以使用常规 包安装步骤在 Visual Studio 或命令行中手动测试安装。
对于自动测试,基本过程如下所示:
- 将
.nupkg文件复制到本地文件夹。 - 使用
nuget sources add -name <name> -source <path>命令将文件夹添加到包源(请参阅 nuget 源)。 请注意,在任何给定计算机上只需设置此本地源一次。 - 使用
nuget install <packageID> -source <name>从该来源安装包,其中<name>与提供给nuget sources的来源名称匹配。 指定源可确保只能从该指定源安装包。 - 检查文件系统以检查是否已正确安装文件。
后续步骤
创建包(即 .nupkg 文件)后,即可将其发布到所选库,如 发布包中所述。
你可能还希望扩展包的功能,或者支持其他方案,如以下主题中所述:
最后,需要注意其他包类型: