简体   繁体   中英

Targets file for deploying nativs dlls to output directory

I have a nuget that has the following structure:

Lib
  -> net45
    -> MyDll.dll
Runtimes
  -> win10-x64
    -> native
      dependency1.dll
      dependency2.dll
      dependency3.dll

I add this nuget to one of my projects. Whenever I build that project, I expect ALL dlls to be copied into the output directory. However, only 'MyDll.dll' gets copied, and all the dlls from the native Runtimes folder don't. I've seen this post that explains how to use a .targets file to accomplish this: Add native files from NuGet package to project output directory . However, I can't find concrete information on how to add .targets file and this post is 6 years old. Surely something new/better exists by now?

Basically, what's the best way to copy native dlls into a build's output directory?

This really depends if your client project is native or managed.

If your project is native one, what you need to do is the following:

  1. Assume we have the following structure:
  • bin
    • Win32
      • yourlibrary.lib
      • yourlibrary.dll
    • x64
      • yourlibrary.lib
      • yourlibrary.dll
  • include
    • yourlib.h
  • YourPackage.nuspec
  • YourPackage.targets
  1. YourPackage.nuspec file that contains something like this:
<?xml version="1.0"?>
<package >
  <metadata>
    <id>YourPackage</id>
    <version>1.0.0.0</version>
    <title>Your Packaged Software</title>
    <authors>your name</authors>
    <owners>your name</owners>
    <iconUrl>link to icon</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Description for your package</description>
    <releaseNotes>Fixed that, added this</releaseNotes>
    <copyright>Copyright by you</copyright>
    <tags>native yourpackage library</tags>
  </metadata>
  <files>
    <!-- .targets file that should be included in the dependee project automatically by Nuget -->
    <file src="YourPackage.targets" target="\build\native\YourPackage.targets" />

    <!-- Include header files for development -->
    <file src="include\**" target="\lib\native\include" />
  
    <!-- Binaries -->
    <file src="bin\**" target="\lib\native\bin" />
  </files>
</package>
  1. Then add the .target file:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
  <ItemDefinitionGroup>
    <!-- COMPILATION -->
    <!-- header files (.h) that should be copied  -->
    <ClCompile>
      <AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\lib\native\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <!-- This is just for the convinience, so you can check within C++ code if the package is used, i.e.: #ifdef HAS_YOUR_PACKAGE -->
      <PreprocessorDefinitions>HAS_YOUR_PACKAGE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ClCompile>
  </ItemDefinitionGroup>

  <!-- LINKING -->
  <!-- Add static/import library for linking -->
  <ItemDefinitionGroup>
    <Link>
      <AdditionalLibraryDirectories>$(MSBuildThisFileDirectory)..\..\lib\native\bin\$(Platform)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
      <AdditionalDependencies>yourlibrary.lib;%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  
  <!-- DEPLOYMENT -->
  <!-- Copy dlls to $(OutDir) -->
  <ItemGroup>
    <NativeLibs Include="$(MSBuildThisFileDirectory)..\..\lib\native\bin\$(Platform)\*.dll" />
    <None Include="@(NativeLibs)">
      <Link>%(FileName)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>     
</Project>

  1. After you have all this, run in the package directory: nuget pack YourPackage.nuspec This will create a new nuget package that upon consuming in the native projects should work.

UPDATE Important note: In the last part of .targets file you have to name variable that holds the file names you are copying to output folder. Don't give this variable generic name 'NativeLibs' because if you will have more than 1 native nuget package, there will be a conflict in VS on loading projects that use the package.

To avoid conflicting names, give it a unique name. Something like YourPackageNativeLibs will work. So the last part will look like:

  <!-- DEPLOYMENT -->
  <!-- Copy dlls to $(OutDir) -->
  <ItemGroup>
    <YourPackageNativeLibs Include="$(MSBuildThisFileDirectory)..\..\lib\native\bin\$(Platform)\*.dll" />
    <None Include="@(YourPackageNativeLibs)">
      <Link>%(FileName)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>     
</Project>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM