NuGet v4 contentFiles 没有被复制到输出

NuGet v4 contentFiles not getting copied to output

我在使用 NuGet v4 CLI 将文件复制到输出时遇到问题。

我的目录结构如下:

1
2
3
4
repo
repo\\CodeAnalyzer.nuspec
repo\\CodeAnalyzer.props
repo\\contentFiles\\any\\any\\StyleCop.ruleset

这是我的 CodeAnalyzer.props 文件:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <PackageName>CodeAnalyzer</PackageName>
    <PackageVersion>0.1.0</PackageVersion>
  </PropertyGroup>
  <PropertyGroup>
      <CodeAnalysisRuleSet>StyleCop.ruleset</CodeAnalysisRuleSet>
  </PropertyGroup>
</Project>

和CodeAnalyzer.nuspec文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
  <metadata>
    <id>CodeAnalyzer</id>
    <description>Provides standard code analyzer tooling and customisation.</description>
    Me</authors>
    <version>0.1.0</version>
    <dependencies>
      <dependency id="StyleCop.Analyzers" version="1.1.118" />
    </dependencies>
    <contentFiles>
      <files include="any/any/*" buildAction="Content" copyToOutput="true" flatten="false" />
    </contentFiles>
  </metadata>
  <files>
    <file src="contentFiles\\any\\any\\StyleCop.ruleset" target="contentFiles" />
    <file src="CodeAnalyzer.props" target="build" />
  </files>
</package>

在 CLI 上,我使用以下方式打包:

.\
uget.exe pack .\\CodeAnalyzer.nuspec

在生成的 .nupkg 中,有一个 contentFiles 目录,其中包含 StyleCop.ruleset 文件,这样就可以了。

如果我随后将包安装到项目中,它会很好地获取 StyleCop.Analyzers 依赖项,并查找 StyleCop.ruleset 文件,因此 .props 文件很好。

但是 StyleCop.ruleset 文件没有放在任何地方。

感觉我已经尝试了很多将 buildActions 更改为 None/Content、copyToOutput 为 true/false、contentFiles.file 元素和 file.file 元素的不同路径。

编辑:消费项目正在使用 NuGet 包的 PackageReferences,而不是 packages.config。


contentFilesPackageReferencecontentpackages.config 的工作方式根本不同。使用 packages.config,您必须使用工具 (Visual Studio) 来安装包,并且在安装时,NuGet 会将 content 复制到项目目录以及它需要的任何其他更改(例如告诉项目系统修改 csproj )。使用 packages.config 还原在概念上与安装不同,所有还原所做的只是将包解压缩到预期的位置,以便 lib/<tfm>/*.dll 程序集在编译时可用。

使用 PackageReference 可以手动编辑 csproj,而无需使用任何知道发生这种情况的工具。这意味着当 NuGet 进行还原时,它不知道这是第一次为项目还原特定包,还是只是第一次在这台计算机上(实际上,NuGet 甚至不检查机上的项目,所以目前不知道该包之前是否在当前计算机上的项目中恢复过)。尽管您仍然可以使用工具(Visual Studio 或 dotnet add package),但这只不过是一种编辑 csproj 的便捷方式。可以说 PackageReference 不再存在安装与恢复的概念。现在只有还原。

由于 PackageReference 不再存在安装的概念,如果 NuGet 要将文件复制到使用项目的目录,如何处理内容文件是一个大问题。如果 NuGet 每次还原都复制文件,这意味着如果项目的开发人员修改了文件,他们会在下一次 NuGet 还原时丢失他们的更改。如果 NuGet 不覆盖文件,那么当项目更改包版本时,新包中的新内容将不会更新。

因此,contentFiles 的工作方式是 NuGet 将文件告知构建系统,并将它们用作来自全局包文件夹的链接。在 .NET Framework TFM 的构建时或 .NET Core TFM 的发布时,文件被复制到输出目录。但是他们从来没有被复制到项目目录中。如果使用 Visual Studio,它们应该出现在解决方案资源管理器中,但是如果单击文件将其打开,它将以只读模式打开,因为对使用的全局包文件夹进行特定于项目的更改会很糟糕通过计算机上的所有项目。因此,从概念上讲,它类似于在每次构建时复制文件,并且为了阻止使用项目的开发人员进行更改,它不会费心将文件复制到目录中。这也意味着检查源代码控制的工作更少。

由于您使用的内容文件是构建时资产,而不是运行时资产,我建议 contentFiles 不是放置规则集文件的正确位置。我只是把它放在你的 props 文件旁边的 build/ 目录中。由于您的 props 文件没有指定规则集文件的路径,我相信它会告诉 MSBuild 查看 props 文件的目录,所以它会正常工作。最坏的情况是您将其更改为 $(MSBuildThisFileDirectory)StyleCop.ruleset。这是假设您对无法修改规则集文件的消费项目感到满意。如果您确实希望他们能够修改文件,那么 NuGet 不是合适的交付机制,我建议您改为查看 dotnet new item templates。


我遇到了这个问题,当时我进行了很多更改,但没有任何效果。最后通过使用 PackageReferences

解决

packages.config 项目使用 content/
PackageReference 项目使用 contentFiles/

您可以在此处找到有关不可变内容的更多信息:

内容文件示例

nuget-contentFiles-揭秘

  • 通过 packages.config 具有 nuget 引用的现有项目
  • 安装了带有内容文件的 NuGet 包
  • 构建项目
  • No content files in output directory

  • packages.configPackageReferences 的转换
  • 构建项目
  • Content files have been copied to output directory

  • IDE 是 Visual Studio 2017。该项目是一个应用程序项目,这意味着它是旧的 csproj 格式。

    更新答案

    GeneratePathProperty 属性已添加到 PackageReference

    1
    2
    3
    <PackageReference Include="EO.Pdf" GeneratePathProperty="true">
        <Version>19.0.83</Version>
    </PackageReference>

    检查您的 \\\\obj\\\\.csproj.nuget.g.props 以验证变量是否已生成

    变量以 Pkg 为前缀。听起来它们是为所有带有工具文件夹的 nuget 包自动生成的。


    这是解决此问题的另一个答案:

    https://stackoverflow.com/a/68243917/56621

    TL;DR - 将文件打包到包中时,请确保遵循目标框架/语言的"任意/任意"命名约定,否则将无法正常工作