24

I'm creating a NuGet package with the following idea:

  • Has a platform dependent executable and a dll (Windows, Linux and MacOS).
  • The native binaries are 64-bit ones.
  • A .NET Standard 2.0 library to use these native resources.
  • During .NET library development and testing the native resources should be included in the build so they're usable.

The idea isn't to embed the native resources and then extract them but distribute alongside the .NET library that makes use of them. However, I've come across some problem I'd like to ask around a bit.

1. Is there a commonly accepted convention to the root to external dependencies? Currently, my structure is:

.\Solution.sln
.\Solution.nuspec
.\runtimes\win-x64\native\<.exe and .dll>
.\Project\Project.csproj

and this .NET Standard 2.0 library project compiles to Project\bin\Debug\netstandard2.0. I wonder though if there's some other convention or name for the root. I have read, amongst other sources and GitHub projects Creating NuGet packages.

2. Taking the .nuspec file is otherwise quite ordinary, I wonder how should I arrange the file references? I read the instructions at Nuspec replacement tokens and in the .nuspec file I have a section telling:

<files>
  <file src="bin/$configuration$/$id$.pdb" target="lib/netstandard20" />
  <file src="bin/$configuration$/$id$.dll" target="lib/netstandard20" />
  <file src="runtimes/win-x64/native/.exe" target="runtimes/win-x64/native/.exe" />
  <file src="runtimes/win-x64/native/.dll" target="runtimes/win-x64/native/.dll" />
</files>

but the native files do not get included. That's true also when I try to set a relative path starting with ..\ (I still may have this wrong, might just sleep over this a bit and try again).

3. Should I include some sort of a .props file that would then include both the wrapper and native resources correctly to those who use the Nuget library? It should be set up so that both files that all native resources are included and set so they're copied to project output along with other build artifacts.

4. Should I make some special arrangement to Project.csproj? Or maybe a better question is, is there some robust practice I should be aware of? I see there are questions and answers such as at https://github.com/aspnet/websdk/issues/204#issuecomment-302482115. Or in fact Automaticaly copy native dll to the bin folder of referencing project in Visual Studio and Automatic native and managed DLLs extracting from Nuget Package too. I should mention in Project.csproj I have only set:

<PropertyGroup>
  <RuntimeIdentifiers>win-x64;osx.10-11-x64;ubuntu.16.04-x64;debian.8-x64</RuntimeIdentifiers>
  <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
</PropertyGroup>

edit: Doh! I'm trying to create the package by dotnet pack .\Project\Project.csproj, which doesn't use the .nuspec file. Maybe a good way is to use the Nuget metadata tooling as described at Additions to the csproj format for .NET Core.

edit 2: It appears trying to pack via .csproj has a share of problems, more at https://github.com/NuGet/Home/issues/2372.

edit 3: In VS 2017 it appears the Package tab is the best way to go to add the details. Then the .csproj needs to be modified like

<PropertyGroup>
  <TargetFramework>netstandard2.0</TargetFramework>
  <RuntimeIdentifiers>win-x64;debian-x64</RuntimeIdentifiers>
</PropertyGroup>

<ItemGroup>
  <Content Include="lib\runtimes\win-x64\native\.exe">
    <PackagePath>lib/runtimes/win-x64/native/.exe</PackagePath>
    <Pack>true</Pack>
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
</ItemGroup>

The native resource is included in the NuGet package, but not restored properly.

edit 4: Other people have similar issues. Further links and rationale at https://github.com/NuGet/Home/issues/6645.

edit 5: With the aforementioned structure, one last thing needed to add is a file as follows to the root of lib

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Content Include="$(MSBuildThisFileDirectory)../../lib/runtimes/win-x64/native/.exe">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <Link>.exe</Link>
      <Visible>false</Visible>
    </Content>
  </ItemGroup>
</Project>

and then to Project.csproj inside the ItemGroup add

<Content Include="lib/{your_libraryname}.targets">
  <PackagePath>build/netstandard2.0/</PackagePath>
  <Pack>true</Pack>
</Content>

With these, this looks like being solved.

AeroX
  • 3,387
  • 2
  • 25
  • 39
Veksi
  • 3,556
  • 3
  • 30
  • 69
  • thank you for posting updates. I'm trying to accomplish the same thing (i'm trying to distribute rust binaries with C# bindings via nuget). Is your project publicly viewable? otherwise, I will try to follow your updates. thanks! – Jerahmeel Mar 21 '18 at 10:14
  • Wow, this is a long road. I'll try to follow your steps... tomorrow! – Patrick Stalph Jan 24 '19 at 16:16

0 Answers0