My NuGet package needs to deliver some rather large files to build output directory.
In an old NuGet model, such files have to be stored in content
folder of the .nupkg
. While in a new model introduced in NuGet 3.3, such files have to be stored in contentFiles
folder.
To maintain a compatibility with older versions of NuGet and mainly with Package.config
package management format, I need to duplicate the files into both folders. That unfortunately almost doubles a size of the package.
Is there a way to prevent that? Can I somehow link contentFiles
to content
folder?
If you only want to output the file to the build output (content
only copies the file to the output directory but does cause it to be set as copy to output directory item), you can use a completely different approach by creating an msbuild file that will be included in the project.
You can do this by putting both the file - say test.jpg
into the tools
folder (you could also use build
) and add a Your.Package.Id.targets
file to the build
folder (the name being the package id of your package with .targets
as extension) with the following content:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Content Include="$(MSBuildThisFileDirectory)..\tools\test.jpg">
<Link>test.jpg</Link>
<Visible>false</Visible>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
</Project>
This target will be automatically imported into the project files regardless of which "style" of NuGet reference is used (packages.config
, PackageReference
) and should be backwards compatible to older versions of VS as long as they support NuGet and ToolsVersion 4.0
.
The Link
metadata denotes where in the output / publish directories the file will end up. You could set it to e.g. defaultContent\images\foo.jpg
to create a nested structure and rename the file. (you could even use MSBulid variables to use some of the referencing project's configuration). The Visible
metadata prevents the solution explorer from showing the full relative path to the file, which could end up in lots of nested ..
nodes. The CopyToPublishDirectory
applies to .NET Core / ASP.NET Core apps or SDK-based projects using the Publish
target for publishing.
Note that you can set the Inclue
-path to anything depending on where in your package the file is. You can also use wildcards (but then set Link
to %(Filename)%(Extension)
)
Found updated documentation describing this in detail at
MSBuild targets for NuGet.
--- 8< ---
By default, everything gets added to the root of the content and contentFiles\any\ folder within a package and preserves the relative folder structure, unless you specify a package path:
<Content Include="..\win7-x64\libuv.txt">
<Pack>true</Pack>
<PackagePath>content\myfiles\</PackagePath>
</Content>
If you want to copy all your content to only a specific root folder(s) (instead of content and contentFiles both), you can use the MSBuild property ContentTargetFolders, which defaults to "content;contentFiles" but can be set to any other folder names. Note that just specifying "contentFiles" in ContentTargetFolders puts files under contentFiles\any\ or contentFiles\\ based on buildAction.
--- >8 ---