创建NuGet包时不要包含packages.config文件中的依赖项

61
我正在使用Nuget创建软件包。我想创建一个软件包,不包含任何依赖项(在.nuspec文件中)到其他NuGet软件包。我的项目在其packages.config文件中定义了NuGet软件包依赖项。
首先,我创建.nuspec文件...
C:\code\MySolution>.nuget\nuget.exe spec MyProject\MyProject.csproj

我编辑生成的.nuspec文件,使其最简化,没有任何依赖。

<?xml version="1.0"?>
<package >
  <metadata>
    <id>MyProject</id>
    <version>1.2.3</version>
    <title>MyProject</title>
    <authors>Example</authors>
    <owners>Example</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Example</description>
    <copyright>Copyright 2013 Example</copyright>
    <tags>example</tags>
    <dependencies />
  </metadata>
</package>

然后我构建解决方案并创建一个NuGet包...
C:\code\MySolution>.nuget\nuget.exe pack MyProject\MyProject.csproj -Verbosity detailed

这是该命令的输出...
Attempting to build package from 'MyProject.csproj'.
Packing files from 'C:\code\MySolution\MyProject\bin\Debug'.
Using 'MyProject.nuspec' for metadata.
Found packages.config. Using packages listed as dependencies

Id: MyProject
Version: 1.2.3
Authors: Example
Description: Example
Tags: example
Dependencies: Google.ProtocolBuffers (= 2.4.1.473)

Added file 'lib\net40\MyProject.dll'.

Successfully created package 'C:\code\MySolution\MyProject.1.2.3.nupkg'.

创建的.nupkg包中包含一个.nuspec文件,但其中包含了一个依赖项部分,在原始的.nuspec文件中没有...

<dependencies>
  <dependency id="Google.ProtocolBuffers" version="2.4.1.473" />
</dependencies>

我认为这是由于此处发生的原因...(来自上述输出)
Found packages.config. Using packages listed as dependencies

如何使NuGet不自动解析依赖项并将它们插入生成的.nuspec文件中,该文件是通过pack命令生成的?我目前正在使用NuGet 2.2。此外,我认为这种行为在旧版本的NuGet中没有发生过;这是一个新的“功能”吗?我找不到任何描述这个“功能”的文档或实现它的时间点。

删除packages.config文件或将其重命名。这样,打包操作就会忽略依赖项。这是我的临时解决方案,直到2.7发布。 - Razor
有人回答了这个问题并提供了可行的答案吗?没有这种能力可能是我遇到过的最愚蠢的事情。 - iGanja
对我来说,我无法将我的依赖项包含进去 :( - Poul K. Sørensen
我也一直无法包含我的依赖项。好几年了。我开始觉得这是一个巨大的谎言。 - StingyJack
在打包命令中使用“-IncludeReferencedProjects”标志以自动包含依赖项,但对于删除它们并没有太大帮助。 - Vern D.
6个回答

58

在2.7版本中,有一个名为developmentDependency的选项,可以设置到package.config中,以避免包含依赖项。

<?xml version="1.0" encoding="utf-8"?>
<packages>
    <package id="jQuery" version="1.5.2" />
    <package id="netfx-Guard" version="1.3.3.2" developmentDependency="true" />
    <package id="microsoft-web-helpers" version="1.15" />
</packages>

7
这个功能的开箱即用实现要求每个使用该软件包的用户都需要在他们将其包含在其中的每个项目的packages.config文件中添加此属性。许多用户甚至不知道这个属性的存在。我已经在博客上写过如何使软件包作者能够在安装其软件包时自动执行此步骤,从而将责任转移给用户:http://blog.danskingdom.com/have-your-nuget-package-install-itself-as-a-development-dependency/ - deadlydog
10
在Nuget 2.8中,您现在可以通过在nuspec文件中设置developmentDependencytrue来将您的软件包声明为“仅开发依赖项”。请参阅http://docs.nuget.org/docs/reference/nuspec-reference#Metadata_Section。@deadlydog - theDmi
1
@theDmi 是的,我已经更新了我的博客文章,并在这个帖子中发布了自己的答案,包含所有最新的信息。请随意给我的答案点赞,因为它提供了清晰的示例和比这个更多的信息。 - deadlydog

34

防止您的软件包依赖于其他软件包

NuGet 2.7开始,有一个新的developmentDependency属性 可以 添加到您项目的packages.config文件中的package节点。因此,如果您的项目包含了一个NuGet软件包,而您不希望您的NuGet软件包将其作为依赖项包含在内,您可以像这样使用此属性:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="CreateNewNuGetPackageFromProjectAfterEachBuild" version="1.8.1-Prerelease1" targetFramework="net45" developmentDependency="true" />
</packages>

在这里需要添加的重要部分是developmentDependency="true"

防止其他软件包依赖于您的开发软件包

如果您正在创建供他人使用的开发NuGet软件包,并且您知道他们不希望将其作为软件包依赖项,那么您可以通过在.nuspec文件的元数据部分中使用NuGet 2.8 developmentDependency属性来避免用户手动向其packages.config文件添加该属性。当其他人安装您的软件包时,这将自动将developmentDependency属性添加到packages.config文件中。但是,这要求用户至少安装了NuGet 2.8。幸运的是,我们可以利用NuGet 2.5 minClientVersion属性来确保用户至少安装了v2.8;否则,他们将被告知需要更新其NuGet客户端才能安装软件包。

我有一个开发用的NuGet包,这非常完美。以下是我的.nuspec文件示例,展示如何使用minClientVersion和developmentDependency属性(分别在第3行和第20行):
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
  <metadata minClientVersion="2.8">
    <id>CreateNewNuGetPackageFromProjectAfterEachBuild</id>
    <version>1.8.1-Prerelease1</version>
    <title>Create New NuGet Package From Project After Each Build</title>
    <authors>Daniel Schroeder,iQmetrix</authors>
    <owners>Daniel Schroeder,iQmetrix</owners>
    <licenseUrl>https://newnugetpackage.codeplex.com/license</licenseUrl>
    <projectUrl>https://newnugetpackage.codeplex.com/wikipage?title=NuGet%20Package%20To%20Create%20A%20NuGet%20Package%20From%20Your%20Project%20After%20Every%20Build</projectUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Automatically creates a NuGet package from your project each time it builds. The NuGet package is placed in the project's output directory.
    If you want to use a .nuspec file, place it in the same directory as the project's project file (e.g. .csproj, .vbproj, .fsproj).
    This adds a PostBuildScripts folder to your project to house the PowerShell script that is called from the project's Post-Build event to create the NuGet package.
    If it does not seem to be working, check the Output window for any errors that may have occurred.</description>
    <summary>Automatically creates a NuGet package from your project each time it builds.</summary>
    <releaseNotes>- Changed to use new NuGet built-in method of marking this package as a developmentDependency (now requires NuGet client 2.8 or higher to download this package).</releaseNotes>
    <copyright>Daniel Schroeder 2013</copyright>
    <tags>Auto Automatic Automatically Build Pack Create New NuGet Package From Project After Each Build On PowerShell Power Shell .nupkg new nuget package NewNuGetPackage New-NuGetPackage</tags>
    <developmentDependency>true</developmentDependency>
  </metadata>
  <files>
    <file src="..\New-NuGetPackage.ps1" target="content\PostBuildScripts\New-NuGetPackage.ps1" />
    <file src="Content\NuGet.exe" target="content\PostBuildScripts\NuGet.exe" />
    <file src="Content\BuildNewPackage-RanAutomatically.ps1" target="content\PostBuildScripts\BuildNewPackage-RanAutomatically.ps1" />
    <file src="Content\UploadPackage-RunManually.ps1" target="content\PostBuildScripts\UploadPackage-RunManually.ps1" />
    <file src="Content\UploadPackage-RunManually.bat" target="content\PostBuildScripts\UploadPackage-RunManually.bat" />
    <file src="tools\Install.ps1" target="tools\Install.ps1" />
    <file src="tools\Uninstall.ps1" target="tools\Uninstall.ps1" />
  </files>
</package>

如果您不想强制用户在使用您的软件包之前安装至少NuGet v2.8,则可以使用我提出并在博客中介绍的解决方案,该解决方案在NuGet 2.8 developmentDependency属性出现之前就已存在。

对我没用。这里使用的是Nuget 2.8,而developmentDependency="true"没有任何区别。当我通过Nuget管理器查看包时,“仍然”报告所有这些外部依赖项,并且仍将它们引入我的项目中。 - DiggyJohn
@DiggyJohn 嗯,我在发布之前测试过,对我来说运行得很好。我也使用v2.8。你是否也在使用.nuspec文件?也许你在.nuspec文件中将那些额外的文件列为依赖项了? - deadlydog
@DiggyJohn,如果你已经有了你的软件包的引用,那么它将不会更新。我必须从我的软件包配置中删除引用,然后重新安装软件包,它就会按预期显示。 - workabyte
使用 nuget 4.7,无论哪个选项都无法阻止下载依赖项。 - munchrall

13

如果您正在使用PackageReference元素而不是package.config文件,则这是解决方案:

<PackageReference Include="Nerdbank.GitVersioning" Version="1.5.28-rc" PrivateAssets="All" />
或者
<PackageReference Include="Nerdbank.GitVersioning" Version="1.5.28-rc">
   <PrivateAssets>all</PrivateAssets>
</PackageReference>

相关的GitHub讨论


1
如果这不起作用,请尝试删除“bin”和“obj”文件夹。 - Tereza Tomcova

4
根据问题#1956(https://nuget.codeplex.com/workitem/1956)和pull request 3998(https://nuget.codeplex.com/SourceControl/network/forks/adamralph/nuget/contribution/3998),此功能已经包含在2.7版本中,而不是2.4版本。然而,我无法找到有关该功能的文档,并且仍然没有弄清楚如何使用它。如果有人知道,请更新此答案。更新:开发人员已更新问题#1956。该功能未包含在2.4版本中,而是推迟到即将发布的2.7版本。这就是为什么目前还没有文档的原因。

1
问题最近已经更新。该功能似乎已经经过测试,发现了一些问题。http://nuget.codeplex.com/workitem/1956 - Eivind Gussiås Løkseth

4
您可以明确指定要包含哪些文件,然后在nuspec文件本身上运行pack命令。
<?xml version="1.0"?>
<package >
  <metadata>
    <id>MyProject</id>
    <version>1.2.3</version>
    <title>MyProject</title>
    <authors>Example</authors>
    <owners>Example</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Example</description>
    <copyright>Copyright 2013 Example</copyright>
    <tags>example</tags>
    <dependencies />
  </metadata>

  <files>
    <file src="bin\Release\MyProject.dll" target="lib" />
  </files>

</package>

您应该使用相对于nuspec文件的路径设置src属性。然后您可以运行pack命令。

nuget.exe pack MyProject\MyProject.nuspec

这是一个我没有考虑过的有趣方法;我将在有时间时尝试这个解决方案。我原本认为使用.nuspec文件生成包不是一个好主意,而是更喜欢使用.csproj文件。以这种方式构建包是否会产生任何后果? - Jesse Webb
1
@JesseWebb 我猜你不能使用变量填写一些字段,比如版本号,但除此之外应该没问题。我认为使用nuspec文件没有任何问题。你有任何反对的来源吗? - Ufuk Hacıoğulları
2
我猜这并没有被特别反对;NuGet文档只是建议在打包命令中使用csproj文件,“nuspec实际上会被捡起来”。http://docs.nuget.org/docs/creating-packages/creating-and-publishing-a-package#From_a_project 不过,这个解决方案似乎很有前途,我会尽快尝试一下...只是最近几周一直非常忙。 - Jesse Webb
@DiggyJohn 规范在后续版本中可能已更改。http://docs.nuget.org/docs/reference/nuspec-reference - Ufuk Hacıoğulları
使用 .nuspec 文件而不是 .csproj 文件作为参考将起作用(即不包括您未明确指定的依赖项)。 缺点是标准替换令牌将无法解析,例如 $version$ 将不会设置为项目的 AssemblyInfo.cs 中的值。 请参阅 https://learn.microsoft.com/en-us/nuget/schema/nuspec#replacement-tokens - stoj

1

我不确定为什么您想忽略NuGet包所需的依赖关系,但您是否考虑使用NuGet Package Explorer工具来创建您的包?


1
我们的构建过程由我们的CI服务器TeamCity自动化处理,因此我们没有考虑在这个过程中使用GUI工具。我认为这个工具不会帮助我们实现自动化。 - Jesse Webb
3
我们不需要在 .nuspec 中包含依赖项的原因是因为我们只是使用 GoogleProtocolBuffers 来生成适当的 C# 源代码文件,它不是一个运行时依赖项。 - Jesse Webb
1
您可以使用该工具创建和维护 .nuspec 文件,然后直接在构建服务器上从 .nuspec 文件生成包,而不是从 .csproj 文件。 - devdigital
1
我明白了,你建议使用这个工具来维护.nuspec文件,就像@UfukHacıoğulları在他的答案中建议的那样。当我尝试他的解决方案时,我会试试看的。 - Jesse Webb
1
在我们的情况下,这是因为我们正在对多个程序集使用ILMerge。我们不需要Nuget拉取所有依赖的程序集,因为它们已经是主要程序集的一部分,而且实际上也不再“依赖”于它们。 - DiggyJohn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接