I've got the following .nuspec file, defining my package (simplified for better readability):
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
.
.
.
<dependencies/>
<contentFiles>
<files include="any\any\config\*.*" buildAction="None" copyToOutput="true" flatten="false"/>
</contentFiles>
</metadata>
<files>
<file src="bin\Assembly.dll" target="lib\net461" />
<file src="bin\Assembly.pdb" target="lib\net461" />
<file src="Config\cf.xml" target="contentFiles\any\any\config"/>
<file src="Config\cf.txt" target="contentFiles\any\any\config"/>
</files>
</package>
As you can see, it contains a compiled Assembly along with it's debug symbols file as well as two content Files in a sub directory.
This results in the following compilation output, where the Assembly.dll is extracted to the output directory as well as the config sub directory (with the two cf.* files in it):
What I want to do is to move the sub directory config one step up in the directory tree, so it sits next to the output directory - basically maintaining the structure of the file input in the .nuspec file (assuming bin is the output directory of my .csproj):
How can I tell the NuGet package the exact location where I want the contentFiles to be extracted to?
You can achieve this by creating a MSBuild target that moves your config
folder one level above the project build output.
Add a .targets
file with the following content to your NuGet's build\net461
folder:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Sets up items for target MoveConfigFiles, so that they can be used as Inputs and Outputs. -->
<Target Name="PrepareMoveConfigFiles" AfterTargets="Build">
<!-- ItemGroup wrapped in Target to delay evaluation of contained Items -->
<ItemGroup>
<!-- Contains source locations of files to be moved -->
<ConfigSourceFiles Include="$(OutputPath)\config\**\*.*" />
<!-- Contains target locations of files to be moved -->
<ConfigTargetFiles Include="@(ConfigSourceFiles->'%(FullPath)'->Replace('\config\', '\..\config\'))" />
</ItemGroup>
</Target>
<!-- Moves files from $(OutputPath)\config to $(OutputPath)\..\config,
then deletes $(OutputPath)\config. -->
<Target Name="MoveConfigFiles" AfterTargets="PrepareMoveConfigAndSqlFiles" Inputs="@(ConfigSourceFiles)" Outputs="@(ConfigTargetFiles)">
<Move SourceFiles="@(ConfigSourceFiles)" DestinationFiles="@(ConfigTargetFiles)" />
<RemoveDir Directories="$(OutputPath)\config" />
</Target>
</Project>
The target PrepareMoveConfigFiles
is executed after the Build
target (which guarantees the NuGet's contents exist in build output), and sets up items used as Inputs
and Outputs
of the next MoveConfigFiles
target. (The items are set inside this target to ensure they are evaluated after the Build
target has completed. If the item definitions would be placed below the Project
level, they would be evaluated earlier and thus would potentially be empty because the files of the content
folder have not yet been deployed.)
The ConfigSourceFiles
item just contains the source files, and ConfigTargetFiles
takes the paths of all ConfigSourceFiles
and replaces \config\
with \..\config\
, which leads to the desired target locations.
The MoveConfigFiles
target then uses the Move and RemoveDir tasks to accomplish the movement of files and deletion of the original config
folder.
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