Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent duplicating files in NuGet content and contentFiles folders

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?

like image 756
Martin Prikryl Avatar asked Nov 24 '17 08:11

Martin Prikryl


People also ask

What is contentfiles in NuGet?

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.

How to create a NuGet in Visual Studio?

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.

How do I add an image to a NuGet package?

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.

Is the contentfiles option supported for projects that use packages?

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.


2 Answers

Found updated documentation describing this in detail at MSBuild targets for NuGet.

By default, everything gets added to the root of the content and contentFiles\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 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\<target_framework> or contentFiles\<language>\<target_framework> based on buildAction.

like image 162
Daniel Avatar answered Oct 17 '22 01:10

Daniel


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))

like image 22
Martin Ullrich Avatar answered Oct 17 '22 00:10

Martin Ullrich