NuGet product used (NuGet.exe | VS UI | Package Manager Console | dotnet.exe): dotnet.exe and msbuild.exe
dotnet.exe --version (if appropriate): 2.1.600-preview-009426
msbuild version: 16.0.218-preview+g5c625fa747
dotnet new classlib
<PropertyGroup>
<PackageLicenseFile>license</PackageLicenseFile>
</PropertyGroup>
<ItemGroup>
<None Include="license" Pack="true" PackagePath="$(PackageLicenseFile)" />
</ItemGroup>
license
file with any textdotnet pack
> dotnet pack
Microsoft (R) Build Engine version 16.0.225-preview+g5ebeba52a1 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restore completed in 39.19 ms for E:\dev\misc\libtest3\libtest3.csproj.
C:\Program Files\dotnet\sdk\2.1.600-preview-009426\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.RuntimeIdentifierInference.targets(143,5): message NETSDK1057: You are working with a preview version of the .NET Core SDK. You can define the SDK version via a global.json file in the current project. More at https://go.microsoft.com/fwlink/?linkid=869452 [E:\dev\misc\libtest3\libtest3.csproj]
libtest3 -> E:\dev\misc\libtest3\bin\Debug\netstandard2.0\libtest3.dll
C:\Program Files\dotnet\sdk\2.1.600-preview-009426\Sdks\NuGet.Build.Tasks.Pack\build\NuGet.Build.Tasks.Pack.targets(199,5): error NU5030: The license file 'license' does not exist in the package. [E:\dev\misc\libtest3\libtest3.csproj]
If I remove the <PackageLicenseFile>license</PackageLicenseFile>
line, it packs fine and license
file is added to nupkg. It also works if I drop the PackagePath="$(PackageLicenseFile)"
portion. And it works if I use license.txt
as a file name everywhere.
This is function of how paths are handled in general.
Putting simply "license" in PackagePath (what it resolves to), gets treated as a folder, rather than a file. Which also explains why dropping PackagePath works.
Another option would be to specify ".".
Closing per my above comment.
IMO this is a bad behavior. It is very common to include an extension-less LICENSE file along with the repo.
@replaysMike
It doesn't prevent you from packing a extensionless license, as I said in my above comment.
Furthermore this behavior is about way more than licenses, and requiring a trailing slash for directories would be a breaking change at this point.
This is a really bad practice and it is also broken also in nuget.exe 4.9.2.5706 and that trick with the trailing dot doesn't work.
<license type="file">LICENSE</license>
...
<files>
<file src="licenses/LICENSE." target="" />
</files>
I tried the above with all combinations of LICENSE
without a dot and with a dot and having a dot only in one of them or another - nothing works and I always get this error:
Error NU5019: File not found: 'licenses/LICENSE.'.
Only when I add something like .txt
, it works, but then I have to modify a 3rd-party file.
Ok, I found a combination that works. This is not very obvious.
<license type="file">licenses\LICENSE.</license>
...
<files>
<file src="licenses\LICENSE" target="licenses\LICENSE." />
</files>
Notice how src
doesn't have a dot, but target
and file
do. It only works in this combination and all other dot placements fail. Seeing how you are adding a trailing underscore to the extension-less files to track them as such, I can see the lengths you went to deal with this. It would be simpler if you assumed a directory only if it ends in a slash.
@gh-andre
It would be simpler if you assumed a directory only if it ends in a slash.
That's not/wasn't my decision.
Pack (both nuget.exe and dotnet.exe) have worked a certain way for a very long time. Changing that now would be a big breaking change.
You can also do
<license type="file">LICENSE</license>
...
<files>
<file src="licenses\LICENS*" target="" />
</files>
@nkolev92 Thanks for responding. As long as there is a work around, I can live with it.
@nkolev92 Also, having this documented on MSDN would certainly help. Nuget seems to be tailored for .Net deployments and there is little-to-none on how to work with native packages, especially when contents is not Windows-specific.
I concur, this is still blocking an extensionless LICENSE file.
<PropertyGroup>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
</PropertyGroup>
<ItemGroup>
<None Include="..\..\LICENSE" Pack="true" PackagePath="$(PackageLicenseFile)">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Which yields:
Severity Code Description Project File Line Suppression State
Error NU5030 The license file 'LICENSE' does not exist in the package. my.project C:\Program Files\dotnet\sdk\2.1.507\Sdks\NuGet.Build.Tasks.Pack\build\NuGet.Build.Tasks.Pack.targets 202
Whereas, when the file is named LICENSE.txt
, for instance, the build succeeds, but only partially. The file is completely ignored, see below.
This is a bug, NuGet/Microsoft.
Further, dotnet pack
is only using PackageLicenseExpression
completely ignoring PackageLicenseFile
when that has been specified. This is not a documentation issue, but a failure to execute, especially when so much dust has been kicked up over a migration path (loosely so-called).
This is kind of a kluge workaround IMO:
<PropertyGroup>
<_DesiredLicenseFileName>LICENSE.</_DesiredLicenseFileName>
<_InternalLicenseFileName>LICENSE.txt</_InternalLicenseFileName>
</PropertyGroup>
<Target Name="CopyLicenseFileForPackagingPurposes" BeforeTargets="BeforeBuild" Condition="!Exists('..\..\$(_InternalLicenseFileName)')">
<Copy SourceFiles="..\..\$(_DesiredLicenseFileName)" DestinationFiles="..\..\$(_InternalLicenseFileName)" />
</Target>
And so on...
<PropertyGroup>
<PackageLicenseFile>$(_InternalLicenseFileName)</PackageLicenseFile>
</PropertyGroup>
<ItemGroup>
<None Include="..\..\$(_InternalLicenseFileName)" Pack="true" PackagePath="$(_InternalLicenseFileName)">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Which we do end up with the License File in the package nuspec:
<license type="file">LICENSE.txt</license>
However, to include a deprecateLicenseUrl there as well is unprofessional, Microsoft. How do we torpedo that output?
<licenseUrl>https://aka.ms/deprecateLicenseUrl</licenseUrl>
@mwpowellhtx
This is kind of a kluge workaround IMO:
There is a simpler solution. This is how paths have been treated in nuget/msbuild for a while. Changing it would be a huge breaking change.
https://github.com/NuGet/Home/issues/7601#issuecomment-450209731
However, to include a deprecateLicenseUrl there as well is unprofessional, Microsoft. How do we torpedo that output?
Refer to the spec for that behavior: https://github.com/NuGet/Home/wiki/Packaging-License-within-the-nupkg
It is there for backwards compatibility.
Further, dotnet pack is only using PackageLicenseExpression completely ignoring PackageLicenseFile when that has been specified. This is not a documentation issue, but a failure to execute, especially when so much dust has been kicked up over a migration path (loosely so-called).
If you do that the following warning will be raised.
https://docs.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu5033
I have a test for that https://github.com/NuGet/NuGet.Client/blob/74508a570f9611e3ecd1641415a7bf9d9ee6e0ef/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs#L3455.
If you see it otherwise, please create a new issue with that information.
@nkolev92 This is effectively the workaround I've taken.
Or is a path to a license file. E.g.
<license type="file">LICENSE.txt</license>
Coupled with other precautions. i.e. copied LICENSE
to LICENSE.txt
as a before build target, added LICENSE.txt
to Git-ignored directories/files, and so on.
You can always do the below if you are using dotnet pack
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<PackageLicenseFile>License</PackageLicenseFile>
</PropertyGroup>
<ItemGroup>
<None Include="License" Pack="true" Visible="false" PackagePath=""/>
</ItemGroup>
</Project>
@nkolev92 That did not work, assuming file system behavior, <PackageLicenseFile>License</PackageLicenseFile>
is case insensitive, same as <PackageLicenseFile>LICENSE</PackageLicenseFile>
, and is the reason we are having this exchange in the first place.
To be clear, I am specifying <PackageLicenseFile>$(_InternalLicenseFileName)</PackageLicenseFile>
, which ends up being <_InternalLicenseFileName>LICENSE.txt</_InternalLicenseFileName>
, assuming LICENSE
precautions taken in advance, etc.
That did not work, assuming file system behavior,
License is case insensitive, same asLICENSE , and is the reason we are having this exchange in the first place.
I'm not following the concern.
Why wouldn't my example work? The casing is consistent. I just tested it myself and I did not hit any problems.
Furthermore, what you are articulating is just how MSBuild works since it is case insensitive.
The property names are case insensitive. The values in them are case preserving for the consumer of the property.
@nkolev92 So, what you're telling me is MSBuild's treatment of property values is inconsistent (i.e. case sensitive) with how the operating system treats file names (i.e. case insensitive). All I'm saying is, file name and property named LICENSE did not work, I got the packaging error.
So, what you're telling me is MSBuild's treatment of property values is inconsistent (i.e. case sensitive) with how the operating system treats file names (i.e. case insensitive).
No, what I'm saying it's the following. I'll illustrate with an example:
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<packagelicensefile>license</packagelicensefile>
<Target Name="MyTarget">
<Message Text="The PackageLicenseFile value is $(PackageLicenseFile)" Importance="high" />
</Target>
dotnet msbuild /t:MyTarget myproj.csproj
The PackageLicenseFile value is license
Reasoning: MSBuild evaluates top to bottom, and packagelicensefile is the latest declaration
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<packagelicensefile>LICENSE</packagelicensefile>
<Target Name="MyTarget">
<Message Text="The PackageLicenseFile value is $(PackageLicenseFile)" Importance="high" />
</Target>
dotnet msbuild /t:MyTarget myproj.csproj
The PackageLicenseFile value is LICENSE
<packagelicensefile>LICENSE</packagelicensefile>
<Target Name="MyTarget">
<Message Text="The PackageLicenseFile value is $(PackageLicenseFile)" Importance="high" />
</Target>
dotnet msbuild /t:MyTarget myproj.csproj
The PackageLicenseFile value is LICENSE
The MSBuild property names are case insensitive.
The values inside are case sensitive. It's up to consumer to enforce the casing.
In the license pack case it's NuGet and the file system.
In MSBuild it's valid to say
<None Include="files/license.txt"/>
<None Include="files/License.txt"/>
as long as the file system says it's ok.
I have uploaded an extensionless sample in the nuget samples repo that I have verified that it works on my end.
https://github.com/NuGet/Samples/tree/master/PackageLicenseFileExtensionlessExample
@nkolev92 No, you are missing the point. <PackageLicenseFile>LICENSE</PackageLicenseFile>
fails to package. It is because the file apparently cannot be called LICENSE
, or apparently any extensionless naming convention. Or if there is some internal machinery in MSBuild itself, it is case sensitive and wants License
, but this is inconsistent with the operating system naming convention. Anyway, we have an adequate, at best, workaround.
Tried the workarounds, but doesn't work - at least not on the official ASP.NET Core 2.1 Docker image. I ended up renaming the file from LICENCE
to LICENCE.txt
. Seems the simplest solution to me, instead of banging my head with such trivial things.
@DMW007 I ended up doing the same thing. Then MSBuild
sees it and life is good. Not perfect, but it is an acceptable work around.
You can always do the below if you are using dotnet pack
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>netstandard2.0</TargetFrameworks> <PackageLicenseFile>License</PackageLicenseFile> </PropertyGroup> <ItemGroup> <None Include="License" Pack="true" Visible="false" PackagePath=""/> </ItemGroup> </Project>
The above proposition from @nkolev92 just worked fine for me (with dotnet pack
) with a license file named LICENSE
, it took me hours to end up here because I couldn't make it work with the official documentation. Hopefully this will be documented explicitly at some point.
In any case, thank you.
@LukeMarlin Like you, I ended up isolating a "licensing" target that I could import into my projects along similar lines. However, you must rename the file as the file name "license", really "license." is not supported.
Any chance of re-opening this issue? Having a LICENSE
file at the root of the repository is a common standard on open-source projects.
We should be able to simply reference that file from our .csproj
using a relative path:
<PropertyGroup>
<PackageLicenseFile>..\..\LICENSE</PackageLicenseFile>
</PropertyGroup>
dotnet pack
fails when using the above:
C:\Program Files\dotnet\sdk\3.1.300\Sdks\NuGet.Build.Tasks.Pack\buildCrossTargeting\NuGet.Build.Tasks.Pack.targets(198,5):
error NU5030: The license file '..\..\LICENSE' does not exist in the package. [C:\Users\augustoproiete\my-project\src\MyProject\MyProject.csproj]
@gh-andre
It would be simpler if you assumed a directory only if it ends in a slash.
That's not/wasn't my decision.
Pack (both nuget.exe and dotnet.exe) have worked a certain way for a very long time. Changing that now would be a big breaking change.
You can also do<license type="file">LICENSE</license> ... <files> <file src="licenses\LICENS*" target="" /> </files>
Not sure why you took the "E" off. You need only put "*" on the end.
Most helpful comment
IMO this is a bad behavior. It is very common to include an extension-less LICENSE file along with the repo.