aybe
aybe

Reputation: 16662

Unable to add LICENSE/README to NuGet package: error NU5030

I have the following .targets file that I import in multiple .csproj projects:

<Project>
    <PropertyGroup>
        ...         
        <PackageLicenseFile>LICENSE</PackageLicenseFile>
        <PackageReadmeFile>README.md</PackageReadmeFile>
        ...         
    </PropertyGroup>
</Project>

Both LICENSE and README.md files are next to that .targets file which is at root of repository.

But I get the following error:

error NU5030: The license file 'C:\...\blah\LICENSE' does not exist in the package. [C:\...\blah\whatever\whatever.csproj]

Reference documentation:

Question:

How can I get these two files packed onto the NuGet package?

Upvotes: 3

Views: 693

Answers (3)

mr5
mr5

Reputation: 3590

Sharing another answer here as the accepted answer didn't work for me. If you have a similar folder structure like below:

[+] ProjectFolder/
  - LICENSE
  - README
 [+] src/
   - Project.csproj
   - Project.sln
   ...
 [+] test/
   ...

Add the following in your .csproj

<ItemGroup>
  <None Include="..\LICENSE">
    <Pack>True</Pack>
    <PackagePath></PackagePath>
  </None>
</ItemGroup>

Upvotes: 2

mkjeldsen
mkjeldsen

Reputation: 2180

To generalize the accepted answer to this question, the duplicate https://stackoverflow.com/a/75622542/482758, and its cross-post https://github.com/NuGet/Home/issues/12463:

The license file specified in the PackageLicenseFile build property must be "included in the package" but the mechanism for doing so is subtle and poorly documented.

  1. A license file is typically of a type not included in the package by default, hence the need for the explicit inclusion via the None item (None because the file does not require special handling).
    • The path passed to the include item is the correct path to the file, in the form of either an absolute path or a relative path from the build time evaluated location of the include item.
      • Common properties for aid in specifying this path include SolutionDir, which is usually the project root; MSBuildThisFileDirectory, which is the directory of the containing file; and MSBuildProjectDirectory, which is the directory of the project being built.
  2. Besides being selected for inclusion, file inclusion must not be generally disabled via IncludeContentInPack, whose value must be true and defaults to true.
  3. The PackagePath attribute of the include item determines the virtual path of the license file as it appears in the package, and evaluates to the original file name if left empty.
  4. The PackageLicenseFile's value must point to the resolved PackagePath value.

The accepted answer to this question worked because the license file was not first explicitly included via some include item (e.g. None). We can conclude this because attempting to pack a project containing a path to a file that does not exist produces a NU5019: File not found error. Additionally, the specific value of $(MSBuildThisFileDirectory)LICENSE works because that directory contains both the .targets file as well as the license file (that path would have resolved incorrectly inside a .csproj file).

The answer https://stackoverflow.com/a/75622542/482758 worked because the author had manually disabled IncludeContentInPack so no configuration could possibly work. By the time the author corrected that particular mistake the license file had been relocated to the same directory as the file containing the include item, so that answer no longer answers the original question wherein the license file was in an ancestor directory.

To summarize:

If you have a LICENSE.txt file in the same directory as the .sln file then the following configuration will work no matter which property file it is placed in (Directory.Build.props, Directory.Build.targets, other .props or .targets, .csproj):

  <PropertyGroup>
    <PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
  </PropertyGroup>

  <ItemGroup>
    <None Include="$(SolutionDir)LICENSE.txt" Pack="true" PackagePath="" />
  </ItemGroup>

If the license file is not in the solution directory, or a directory easily reached from the solution directory, one of the other build properties may be more convenient. If the file happens to be in the .csproj directory, no path prefix is necessary at all.

Upvotes: 3

aybe
aybe

Reputation: 16662

Finally found the cause thanks to a clue in the docs though that wasn't enough to get it working.

Not only there must be ItemGroup as well but these shall have $(MSBuildThisFileDirectory):

<Project>

    <PropertyGroup>
        <PackageLicenseFile>LICENSE</PackageLicenseFile>
        <PackageReadmeFile>README.md</PackageReadmeFile>
    </PropertyGroup>

    <ItemGroup>
        <None Include="$(MSBuildThisFileDirectory)LICENSE" Pack="true" PackagePath="" />
        <None Include="$(MSBuildThisFileDirectory)README.md" Pack="true" PackagePath="" />
    </ItemGroup>

</Project>

Upvotes: 5

Related Questions