Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NuGet: references to assemblies in runtimes folder not added

Tags:

I have a project that targets two different operating systems/frameworks:

  1. net461 on Windows and
  2. netcoreapp2.0 on OSX

I'm trying to figure out how to correctly package this for NuGet. According to this post I should be able to package them like this:

/runtimes/win/lib/net461/myassembly.dll /runtimes/osx/lib/netcoreapp2.0/myassembly.dll 

By when I add the NuGet package to another project, the packaged assemblies aren't added as references to the target project.

Then I read somewhere that you also need to add reference libraries to the /ref folder so I tried this:

/runtimes/win/lib/net461/myassembly.dll /runtimes/osx/lib/netcoreapp2.0/myassembly.dll /ref/net461/myassembly.dll /ref/netcoreapp2.0/myassembly.dll 

In this case the assemblies get added as a reference to the target project and I can build it, but the required assemblies aren't copied to the output folder.

The documentation on all this is extremely vague and I'm fairly lost.

What am I missing?


Associated NuGet Issue: https://github.com/NuGet/Home/issues/7316


Update: I've put together a sample project that demonstrates what I'm trying to achieve. In particular see the bottom of the readme, titled "NuGet Packaging".

like image 807
Brad Robinson Avatar asked Sep 19 '18 03:09

Brad Robinson


People also ask

Where are NuGet packages references stored?

The location of the default global packages folder. The default is %userprofile%\. nuget\packages (Windows) or ~/. nuget/packages (Mac/Linux).

Can I delete .NuGet Packages folder?

Yes, the . nuget folder is used as a cache for packages downloaded to speed up project restore and compilation. It can safely be removed.


2 Answers

This is what I've finally figured out/guessed (because as best I can tell there's no official documentation for some of this)

  • Files added to the /runtimes folder aren't automatically added as references to the target project.
  • The /ref and /runtime folder should be used in conjunction with each other and only for the .NET Core target. As best I can .NET Framework targets apparently don't support these folders.
  • The /ref folder is for compile time references and anything added here will be added as a reference to the target project.
  • Assemblies in the /ref folder don't need to have an implementation - every public API could just throw a not implemented exception. In practice however you typically just take a copy of one of the implementation assemblies and declare it as the compile time API.
  • I've read (but haven't tested myself) that assemblies in the /ref folder must be "Any CPU" builds. You can use CorFlags utility to patch an implementation assembly for this if necessary.
  • The /runtimes folder is used to provide an implementation assemblies for any references included in the /ref folder. These assemblies are used at runtime and during deployment.
  • The /runtimes folder can include additional assemblies that are only required at runtime and don't need to be seen by the client project. These additional assemblies won't be included as references in the target project but will be available for run/deployment.
  • As mentioned by others, the files in the /runtimes folder aren't copied to the output folder of the build. Instead config files are placed there that tell the runtime how to locate the /runtimes files from the NuGet cache.
  • For .NET Framework targets (ie: net461) just use the /lib folder as there's no other runtimes for .NET aside from Windows anyway.

Putting this all together, my original example, should have looked like this:

/lib/net461/myassembly.dll                       (net461/Windows Compile and Runtime) /runtimes/osx/lib/netcoreapp2.0/myassembly.dll   (netcore/OSX Runtime) /runtimes/win/lib/netcoreapp2.0/myassembly.dll   (netcore/Win Runtime) /ref/netcoreapp2.0/myassembly.dll                (netcore/* Compile Time) 
like image 178
Brad Robinson Avatar answered Sep 19 '22 15:09

Brad Robinson


I spent a fair amount of time trying your project on OSX in both Visual Studio for Mac and VS Code. I'll try to stick with factual observations without getting into "why don't you do X instead".

  • The runtimes/{rid}/lib/{tfm}/*.dll paths look ok
  • target="lib/{tfm}/..." assemblies are automatically referenced, runtimes/... are not
  • Using target framework of netstandard seems like it would make your package work in both netcoreapp and netstandard projects (e.g. use target="lib/netstandard1.6/..."). Compare with this
  • runtimes/ seems to be intended for platform-dependent assemblies you'll load at runtime. For example, 32/64-bit native assemblies in runtimes/win-x64/native/ and runtimes/win-x86/native/) loaded with AssemblyLoadContext (another post by McMaster)
  • Using separate slns for Windows and OSX, or separate platform-specific projects that reference platform-agnostic projects (like Xamarin) would obviate some of the configuration wrangling
  • I found no documentation on target="ref/...", but you can add Explicit Assembly <references> (inside the nuspec <metadata> block)
  • Packaged assemblies won't appear in the output directory, but when prepared for distribution with dotnet publish they'll be included:
like image 43
Jake Avatar answered Sep 19 '22 15:09

Jake