How do I package a .NET library that has the following properties in a modern general-purpose way?
- Offers some shared functionality to both .NET Framework 4.6 and Universal Windows Platform.
- Offers some platform-specific functionality to each (e.g. specialized classes or APIs, including XAML user controls for UWP) with potential platform-specific dependencies on external libraries.
- Is architecture-agnostic (AnyCPU).
- The portable subset of which can be used by other portable libraries that target a compatible API surface.
This is a series of questions and answers that document my findings on the topic of modern NuGet package authoring, focusing especially on the changes introduced with NuGet 3. You may also be interested in some related questions:
- How to package a .NET Framework library?
- How to package a .NET library targeting the Universal Windows Platform?
- How to package a portable .NET library targeting .NET Core?
- How to package a multi-architecture .NET library that targets the Universal Windows Platform?
- How to package a .NET library that targets the Universal Windows Platform and depends on Visual Studio extension SDKs?
This answer builds upon the principles used to package .NET Framework libraries, the principles used to package Universal Windows Platform libraries and the principles used to package portable libraries. Read the linked answers first to better understand the following.
To serve the described set of platforms, you need to structure your solution accordingly into multiple class library projects:
You will want to achieve the following NuGet package structure:
If you have familiarized yourself with the other answers linked above, this should seem relatively familiar to you. The only special part is that the portable library exists in three copies since its contents are to be offered for all target platforms.
The desired package structure can be achieved by using a nuspec file based on the following template:
Note that two separate sets of dependencies are defined: one general-purpose group and one specific to Universal Windows Platform, as the UWP library has an extra dependency on the Newtonsoft.Json package. You can extend the same pattern to any number of platforms with platform-specific dependencies.
That's it - this NuGet package can now be installed into .NET Framework 4.6 projects, Universal Windows Platform projects and portable library projects that target a compatible API surface. The functionality of the portable library will be exported on all platforms, with the platform-specific libraries also used on the appropriate platforms.
Remember to build your solution using the Release configuration before creating the NuGet package.
A sample library and the relevant packaging files are available on GitHub. The solution corresponding to this answer is MultiSurfaceLibrary.