Creating NuGet packages for your Windows 10 UWP libraries

Tags: Windows 10, UWP, NuGet

The first time I had to create a package for Windows 8/8.1, it was quite a task. Once you knew not to forget the .pri and .xbf files it became a lot easier. Fast-forward to Windows 10 and NuGet v3 and you not only have the extra .rd.xml file that comes with your assembly, but your NuSpec file becomes a lot more complex because NuGet v3 requires you to build your part of the dependency graph.

Luckily we’ve got a great .NET community and Oren Novotny created NuSpec.ReferenceGenerator (NuGet / GitHub) to help us with this tedious task. Set up the NuSpec file as you’re used to do: set the id, description, files, … Then simply add this package to your project that should be packaged and build the solution. This tool will pick up your NuSpec file and add the necessary dependencies. More complex scenarios are described on GitHub, so be sure to read up on them if you got more than a single project to be packaged.

Now if it would be that straight-forward, I wouldn’t bother writing a post about it. Both Windows 10 UWP and NuGet v3 are still quite young and we’re still trying to find our way. During to process of creating packages for Prism, I ran into a few things worth mentioning.

Adding this package to your project will most likely create {projectname}.nuget.targets file similar to this (if another package didn’t add it yet).

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition="'$(NuGetPackageRoot)' == ''">
    <NuGetPackageRoot>C:\Users\MYUSERNAME\.nuget\packages\</NuGetPackageRoot>
  </PropertyGroup>
  <ImportGroup>
    <Import Project="$(NuGetPackageRoot)\NuSpec.ReferenceGenerator\1.3.3\build\dotnet\NuSpec.ReferenceGenerator.targets" 
        Condition="Exists('$(NuGetPackageRoot)\NuSpec.ReferenceGenerator\1.3.3\build\dotnet\NuSpec.ReferenceGenerator.targets')" />
  </ImportGroup>
</Project>

As you can see, there’s a path to your own user’s folder. This isn’t something you like to have on a project you work on with multiple users. Good news is that this is a file that will be regenerated by NuGet during package restore. So you should add this to your source control’s ignore list.

Next thing I ran into is somewhat more complex: the Prism solution consists out of several assemblies (Core, WPF, UWP, one for each IoC container per platform, …) that should each get its own package. You don’t want to drag in WPF specific code when doing UWP or a dependency on Unity when you’re using Autofac. So I added NuSpec files for each assembly and added the package to the different projects. But as of today, NuSpec.ReferenceGenerator doesn’t take into account that you’re actually creating multiple packages with dependencies onto each other and misses on adding these dependencies in your own solution. I knew this isn’t an easy fix to implement … so if you got a brilliant idea and are up for the task, head over to GitHub and help fix the issue (if it’s still open when you’re reading this).

Until this ‘bug’ (or feature request) is implemented, you should add your own package dependencies manually and not forget to update version numbers on new releases. The good news here is that those lines will not be removed when new dependencies are generated on the next build.

So it looks like my NuSpec files are done and I ran a quick ‘nuget pack’ command, uploaded the fresh new pre-release packages to MyGet for testing and … hit another wall. Consuming the core library went fine, but when I tried to consume one of the extension libraries in another test project, I got following build error:

Payload contains two or more files with the same destination path 'Prism.Windows\Properties\Prism.Windows.rd.xml'. 
Source files: 
C:\Users\MYUSERNAME\.nuget\packages\Prism.Unity.Windows\6.0.0-prerelease002\lib\uap10.0\Prism.Windows\Properties\Prism.Windows.rd.xml
C:\Users\MYUSERNAME\.nuget\packages\Prism.Windows\6.0.0-prerelease001\lib\uap10.0\Prism.Windows\Properties\Prism.Windows.rd.xml

Checking the path mentioned, I didn’t see the culprit file in the extension package’s path, but somehow Visual Studio thinks it’s there and it breaks my build. This is probably a bug that the Windows (or maybe NuGet) team will have to look into. My current fix is making sure that this file’s build action in your project is set to ‘None’ and remove it from the files being added to the package. I tested both in Debug and Release (.NET Native) and … ‘it works on my machine’ ™.

I hope this post doesn’t scare your away from supporting this platform and helps you with creating your packages for Windows 10 UWP.

You can find a sample project with above tries/issues on my Github.

Edit: Discussing the .rd.xml file issue with Unni Ravindranathan, he told me this file should be included as an Embedded resource instead of the default 'Content' build action. The result is that this file is no longer added seperatly to your project output and shouldn't be in your NuGet package as a seperate file either. This is also confirmed by following msdn article and in this build session (slide 15).

Comments

comments powered by Disqus