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?
In NuGet 3.3, the contentFiles feature was introduced to support project.json managed projects and packages that are indirectly referenced in a project. This was an important change because it brings the ability to deliver static files, .pp file transforms, and language specific code into a project.
Open up your solution in Visual Studio Open your solution’s nuspec file and look for <files> tag You need to reference all folders and all files that you want to include in your nuget.
Put an image into that folder. In this example, our image is called dnf.png. Let’s create the nuspec manifest file for this package and populate it with the information NuGet needs. We can create and place this file at: Next, we need to author the nuspec appropriately to deliver this image with an EmbeddedResource action.
It is not supported for projects that use packages.config. This feature is only for packages that will be installed to projects that are managed using a project.json file. Currently only two projects types are managed by a project.json. The contentFiles option is not available for other project types.
Found updated documentation describing this in detail at MSBuild targets for NuGet.
By default, everything gets added to the root of the
content
andcontentFiles\any\<target_framework>
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
andcontentFiles
both), you can use the MSBuild propertyContentTargetFolders
, which defaults to "content;contentFiles" but can be set to any other folder names. Note that just specifying "contentFiles" inContentTargetFolders
puts files undercontentFiles\any\<target_framework>
orcontentFiles\<language>\<target_framework>
based onbuildAction
.
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)
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With