如何在 Nuget 发布自己的类库包

我们可以将自己实现的类库发布到 Nuget 上,方便在未来开发应用程序时,对已有代码或结构进行复用。以下是在 Nuget 发布自己类库的一个简单介绍。

1. 首先,我们需要到 nuget.org 注册并 获取 API key

2. 随后,下载 Nuget 命令行工具,建议将 nuget.exe 注册到系统的环境变量中,方便后续步骤的操作

3. 在 CMD 中运行 Nuget 命令行工具,并将第一步中获取的 API Key 进行注册

nuget setApiKey <my_api_key>

4. 在已经准备好的发布项目(Project,而不是 Solution)的根目录打开 CMD,运行以下 Nuget 命令,从而创建 .nuspec 包输入描述文件

nuget spec

执行结束后,将会生成一个与项目同名的 .nuspec 文件

5. 使用文本编辑器,编辑生成的 .nuspec 文件

<!>注意
关于此 XML 文件的详细描述,可以参考微软的官方文档。下面以 Squirrel Framework 的 .nuspec 文件作为一个示例。

<?xml version="1.0"?>
<package>
  <metadata>
    <!-- 定义 Nuget Package 的包名,需要唯一,之后再发布新的版本也不需要更改 -->
    <id>SquirrelFramework</id>

    <!-- 定义 Package 的版本号,这里采用参数形式,会自动从项目属性的 Assembly Information 中读取版本号,也可以直接指定版本字符串,比如 1.0.0 -->
    <version>$version$</version>

    <!-- 定义 Package 的标题、描述、作者,以及所有者等 -->
    <title>Squirrel Framework</title>
    <description>A lightweight back-end framework and utilities kit based on MongoDB/Redis</description>
    <authors>Hendry</authors>
    <owners>Hendry</owners>
    <releaseNotes>The initial version of Squirrel Framework</releaseNotes>

    <!-- 指定 Package 的 License、项目地址、使用的图标、是否会提示下载用户确认 License 等 -->
    <licenseUrl>https://github.com/imnista/SquirrelFramework/blob/master/LICENSE</licenseUrl>
    <projectUrl>https://github.com/imnista/SquirrelFramework</projectUrl>
    <repository type="git" url="https://github.com/imnista/SquirrelFramework" />
    <iconUrl>http://s.nap7.com/nugetsquirrelframework.png</iconUrl>
    <requireLicenseAcceptance>true</requireLicenseAcceptance>
    <copyright>Copyright 2018 Hendry, nap7.com</copyright>

    <!-- 定义 Package 的 tag 标签,方便分类和搜索 -->
    <tags>mongodb redis utility kit back end light repository dao squirrel framework ddd</tags>

    <!-- 定义当前 Nuget Package 对其他第三方 Package 的依赖 -->
    <dependencies>
      <dependency id="Newtonsoft.Json" version="11.0.1" />
      <dependency id="MongoDB.Bson.signed" version="2.5.0" />
      <dependency id="MongoDB.Driver.Core.signed" version="2.5.0" />
      <dependency id="MongoDB.Driver.signed" version="2.5.0" />
      <dependency id="StackExchange.Redis.StrongName" version="1.2.6" />
    </dependencies>
  </metadata>
  <files>
    <!-- 定义编译时行为 -->
    <file src="build\**" target="build" />

    <!-- 当 Package 包含多个依赖项目时,在此添加内部的依赖项目 -->
    <file src="bin\Release\Common.Utility.dll" target="lib/net462" />
    <file src="bin\Release\SquirrelFramework.Configurations.dll" target="lib/net462" />
    <file src="bin\Release\SquirrelFramework.Domain.Model.dll" target="lib/net462" />
    <file src="bin\Release\SquirrelFramework.Domain.Service.dll" target="lib/net462" />
    <file src="bin\Release\SquirrelFramework.Repository.dll" target="lib/net462" />
  </files>
</package>

<!>注意
每个 nuget 包只对应一个 VS project,如果我们需要在 Nuget 中包含多个 DLL,则需要对这个 .nuspec 文件进行配置,如上的 <files> 节点就是做这件事情的。我们的代码中需要包含多个 DLL 引用,将它们都列举在此节点下,并给出其适应的 .NET 版本即可。

此外,如果我们的 Package 引用了其它第三方 Nuget Package,则不要在 <files> 节点里指定,而是在 <metadata> 的 <dependencies> 节点进行设置,用户安装 Package 时,会自动安装依赖项目。

6. 开始生成 Nuget Package

(1) 在确定我们的 Project 版本号设定正确后(如果是再次发布,记得将版本号递增),首先在 Release 模式下 Rebuild 代码。

(2) 随后,在项目目录打开 CMD,运行以下 Nuget 命令。

① 对于 .NET Framework 的 Project,执行以下命令即可:

nuget pack SquirrelFramework.csproj -Properties Configuration=Release -Properties NuspecFile=SquirrelFramework.nuspec

② 对于 .NET Core 的 Project,操作会多一点,首先需要将要包含的 DLL, 明确列明在 .nuspec 的 <files> 节点中(如果不设置,将会出现 “assembly outside lib folder” 警告,并生成错误的 Package 包)

<files>
    <file src="bin\Release\netstandard2.0\Common.Utility.dll" target="lib\netstandard2.0" />
</files>

然后需要执行:

dotnet pack --configuration release -p:NuspecFile=SquirrelFramework.nuspec

msbuild /t:pack /p:Configuration=Release /p:NuspecFile=SquirrelFramework.nuspec

<!>注意
如果目标是 .NET Core 的,不能用 nuget.exe 生成 Package,而是改用 dotnet 或 msbuild 命令,目前版本的 nuget.exe 并不支持 .NET Core!

另外,如果 .NET Core 工程使用了 .pfx 进行强签名,dotnet 工具是不能正常生成 build 代码的。必须改用没有密码保护的 .snk 进行强签名。

The .NET Core build chain lacks the infrastructure to deal with PFX signing. The current implementation is hard to make available in a platform-independent way. You can still give assemblies strong names with keys, but you can’t sign them with certificates. At least not using the .NET Core build tools.

关于 .NET Core 创建 package 的更多介绍,可参考这里

7. 在正式发布 Nuget 包前,对我们的 Package 进行测试

(1) 在 VS 中,新建一个用于测试 Nuget Package 的新工程(注意项目的 .NET version,如果项目的版本小于待测试的 Nuget Package 版本,则会造成 Package 中引用 DLL 的缺失)

(2) 依次点击菜单栏的 Tools -> Nuget Package Manager -> Package Manager Settings
在开启的 Options 窗口中,点击 Package Source 页

(3) 将上一步骤生成的 Nuget Package 拷贝到一个本地文件夹,并将这个本地文件夹指定为 Nuget 的一个新的 Package Source

(4) 正常在项目的 Nuget 管理器中,搜索并安装我们的 Nuget Package,开始功能测试

8. 正式发布 Nuget 包

测试通过后,在 CMD 中,输入以下命令即可正式发布 Nuget Package。

nuget push SquirrelFramework.1.0.11.nupkg -Source https://www.nuget.org/api/v2/package

我们可以通过 -Source 参数指定目标 Nuget 服务器,这里可以指定为一个自建的 Nuget 服务器,或 Nuget 官方服务器。

随后,我们也可以登陆 nuget.org 对旧版本的 Package 做下架处理(并不支持删除,因为删除包可能造成引用了这个包的旧有项目无法正常工作)。

9. 特别说明:如何将 Package 内部需要的配置文件设置为 Copy always

由于我们的 Squirrel Framework 需要对 Redis 及 MongoDB 进行读写,所以需要一些配置文件设置相关的连接串。这就需要 Nuget Package 在部署到具体项目后,可以将相关的 Config 文件,在具体项目 Build 时,自动拷贝到生成目录中。这项工作可以通过设置 MS-Build 文件完成。

(1) 首先,我们要确保用于生成 Nuget package 的主项目包含了这些配置文件(或者它们的引用),并设置其属性为 Copy always,这将保证我们的配置文件会被正确的包含在新生成的 Nuget package 中。

(2) 随后,在用于生成 Nuget package 的主项目中,创建一个名为 build 的文件夹,并创建一个与项目同名的 .props 文件。

<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <None Include="$(MSBuildProjectDirectory)\Config\*.config">
      <Link>Config\%(FileName)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>

(3) 在项目 .nuspec 文件的 <files> 节点下添加一个 <file> 节点,用于将 MS-Build 文件顺利包含在新生成的 package 中。

<file src="build\**" target="build" />

关于如何在创建 Package 时,添加 MS-Build 属性和参数,可参考微软的这份官方文档

关于创建 Nuget Package 的更多信息,可参考这里

Hendry

About Hendry

不经历复杂的简单,只是一种苍白。

发表评论

电子邮件地址不会被公开。 必填项已用*标注