6

I am trying to build a NuGet package that includes native DLLs which are to be placed in the output folder when a project uses the package. I have tried to use the several suggestions from this question, but I am always running in the same problem.

My current NuGet package layout is like this:

\build
  packageId.targets
  file1.dll
  file2.dll
\lib
  \netstandard1.4
    assembly.dll

The contents of packageId.targets is:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <NativeLibs Include="$(MSBuildThisFileDirectory)\*.dll"/>
    <None Include="@(NativeLibs)" Link="$(RecursiveDir)$(Filename)$(Extension)">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>

This should, according to the answers of the other questions, lead to my DLLs being placed in the bin\Debug directory of the project using the package. However, they are not. Instead, they are placed in bin\Debug\packages\packageId\build.

Now I have experimented a lot, and I noticed more and more strange behavior which I cannot make any sense of:

  • If I move the DLLs to the root of the NuGet package (like one answer suggests) and change the .targets file accordingly, they are not copied at all. There also is no error message.
  • If I change the .targets file to only reference file1.dll in both Include= and Link=, both files get copied anyway.
  • So I wondered if some policy just ignores the .targets file and copies whatever is in build to that path in the output folder, but when I remove the .targets file, the DLL files will not get copied anymore.

Now I understand even less what's happening.

What do I need to change to get the DLLs copied right into bin\Debug?

flyx
  • 35,506
  • 7
  • 89
  • 126
  • This seems to have been a Visual Studio bug. Updating to the latest version made the DLLs being placed directly in the ouptut directory. – flyx Sep 22 '18 at 07:36

1 Answers1

10

The new way to handle runtime-specific assents in NuGet is to use the runtimes folder to place native assets:

\lib
  \netstandard2.0
    ManagedWrapper.dll
\runtimes
  \win-x86
    \native 
     NativeThing.dll
  \win-x64
    \native 
     NativeThing.dll
  \linux-x64
    \native 
     libNativeThing.so
  \osx-x64
    \native 
     libNativeThing.dylib

If the package is consumed from a .NET Framework project, you may need to add a reference to the Microsoft.NETCore.Platforms package wich provides the runtime graph (runtimes.json) for NuGet to provide proper RID mappings if you don't use base RIDs (e.g. win10-x64 falls back to win-x64 resources).

Martin Ullrich
  • 94,744
  • 25
  • 252
  • 217
  • Thanks for this. But won't I lose the compatibility I get by using .NET Standard when I reference something in .NET Core? That is to say: When I use this feature, will I potentially sacrifice compatibility? Because if I do, then it seems to be wiser to stick to my solution that works since the latest VS update. – flyx Sep 22 '18 at 20:04
  • Not sure wha you loose. If you reference this netstandard library from a .NET Core application, it should either put the runtimes folder into the output directory (portable app) or the right native asset into the main output folder (RID-specific output / self-contained) – Martin Ullrich Sep 22 '18 at 23:18
  • Or do you mean that the package containing the graph has `NETCore` in it? that's just unfortunate naming. the package doesn't have much to do with .NET Core. – Martin Ullrich Sep 22 '18 at 23:19
  • Ah okay. Then all is well, thanks for the clarification. – flyx Sep 23 '18 at 08:29