Wrestling with DNXCore Part One - Platform Targets

As many of you know, .Net Core is rapidly approaching. Microsoft has used the open sourcing of .Net and the CLR as a (needed) excuse to clean house a bit, start fresh, and tackle Oracle's Java head-on. Large developer base? C# has it. Quality language features, such as proper generics, closures, and a rich type system? C# has it. Portability? Well, that was a different question.

As Microsoft announced that they would port the CLR to *nix and OSX, I have to admit I was fairly giddy with excitement. Now, don't get me wrong. I come from a Window sysadmin background, so I'm certainly not anything resembling a Linux zealot. But on the flipside of that very Microsoft centric coin, I'm not really a Windows zealot either. I've used both plenty enough to know that there are strengths and weaknesses on either side of that religious argument.

Size (Kinda) Matters

One of the primary weaknesses with working with Windows servers has always been install weight. Although Linux is certainly catching-up in terms of install size on disk, Windows is the clear loser here in memory usage. Throwing up a Debian based distro with a base configuration on a 4GB VM usually leaves one with less than half a GB of that used on start. On the other hand, Server 2012 R2, even in its still-terribly-difficult-to-use-effectively Core configuration uses a fair bit more.

What does this mean for modern software architects? As everything becomes lighter with the move to distributed, modular, microservice type architectures, the platforms they are based on need the smallest possible overhead, because the tendency is to require a number of VMs or containers in order to keep a clean separation of deployment concerns. It is awfully nice when you can treat your microservices as appliances.

So, with that in mind, I decided to take a personal project of mine as a good opportunity to educate myself on the new world, and began the journey of porting a library to .Net Core.

Nomenclature Hell

Wait a second, wasn't there already something called .Net Core? Well, not exactly, but if you were targeting a Win 8 Store App, a Win 8.1 Store App, or Universal Windows Platform with a NuGet package, you were already targeting netcore45, netcore451, and netcore50 respectively, none of which has actually anything to do with .Net Core. To further complicate matters, the actual command line CLR toolset has gone through a number of naming revisions in the past year, from the K Runtime and kpm to (D)ot(N)et E(x)ecution Environment (DNX) with dnu and dnv, to just the simple command line tool dotnet. Confusing? You bet.

Unfortunately, because things have progressed so rapidly, finding up to date information is not an easy task. Information is spread across blog posts, GitHub issues, RC documentation, and just about anywhere else except where it seems like it should be. Showstopper bugs still exist, despite the Release Candidate status of the project. Even heavy hitters like Json.Net's James Newton-King and StackOverflow's Marc Gravell (who also has a great series on converting to .Net Core) are routinely found requesting information around GitHub. On the plus side, the team has so far been fairly responsive, even on contentious issues.

However, despite their best efforts, the NuGet package targeting story is still evolving and continues to be confusing.

What should I target?

This is one of the more confusing aspects of being a library author at current. Targeting is really a 2 or 3-axis issue, in which runtime, platform, and API all intersect to boil down to a single moniker, such as net45. These break down to the following combinations, which will list the platform/runtime in bold, with the possible targets listed underneath for non-PCL targets:

Full Desktop CLR Runtime
  • net20 - .Net 2.0 Framework
  • net35 - .Net 3.5 Framework
  • net40 - .Net 4.0 Framework
  • net45 - .Net 4.5 Framework
  • net451 - .Net 4.5.1 Framework
  • net46 - .Net 4.6 Framework
CoreCLR Runtime (DNX)
  • dnx451 - .Net 4.5.1 Framework (Win) Running on CoreCLR
  • dnx46 - .Net 4.6 Framework (Win) Running on CoreCLR
  • dnxcore50 - .Net Core Framework (CoreFX Linux, Win, OSX) on CoreCLR

Now, for PCLs, we have to flip the axes around, since the target is really an API, with a list of platforms it can run on. These replace the old portable+x+y+z type monikers that were previously in use (and currently a headache). The lowest numbers have the most restrictive API, but are compatible with the highest number of platforms. As the numbers go higher, the API surface becomes wider, but the number of platforms shrinks. Currently these are labeled in RC1 with the dotnet5.x moniker, but will become netstandard1.x some time in RC2 when the tooling catches up.

.Net Platform Standard 1.0 dotnet5.0 (netstandard1.0)
  • Windows Phone Silverlight 8
  • Windows Phone Silverlight 8.1
  • Windows Phone 8
  • Windows Phone 8.1
  • Full Desktop CLR on .Net Framework 4.5 - 4.6.1
  • Win8 Store App, Win8.1 Store App, and Universal Windows Platform
  • CoreCLR (DNX) on .Net 4.5.1 - 4.6 (Win)
  • CoreCLR (DNX) on .Net Core (CoreFX Linux, Win, OSX)
.Net Platform Standard 1.1 dotnet5.1 (netstandard1.1)
  • Windows Phone 8
  • Windows Phone 8.1
  • Full Desktop CLR on .Net Framework 4.5 - 4.6.1
  • Win8 Store App, Win8.1 Store App, and Universal Windows Platform
  • CoreCLR (DNX) on .Net 4.5.1 - 4.6 (Win)
  • CoreCLR (DNX) on .Net Core (CoreFX Linux, Win, OSX)
.Net Platform Standard 1.2 dotnet5.2 (netstandard1.2)
  • Windows Phone 8.1
  • Full Desktop CLR on .Net Framework 4.5.1 - 4.6.1
  • Win8.1 Store App and Universal Windows Platform
  • CoreCLR (DNX) on .Net 4.5.1 - 4.6 (Win)
  • CoreCLR (DNX) on .Net Core (CoreFX Linux, Win, OSX)
.Net Platform Standard 1.3 dotnet5.3 (netstandard1.3)
  • Full Desktop CLR on .Net Framework 4.6 - 4.6.1
  • Universal Windows Platform
  • CoreCLR (DNX) on .Net 4.6 (Win)
  • CoreCLR (DNX) on .Net Core (CoreFX Linux, Win, OSX)
.Net Platform Standard 1.4 dotnet5.4 (netstandard1.4)
  • Full Desktop CLR on .Net Framework 4.6.1
  • CoreCLR (DNX) on .Net Core (CoreFX Linux, Win, OSX)

The .Net Platform Standard information is available on the corefx repo, but I found the table they used a bit confusing at first (and I'm not the only one confused, judging by various GitHub issues, so hopefully the list of targets above helps out a bit.

Coming up in Part Two, I'll go in to the new project.json file, which replaces both csproj files (thank god) and packages.config files and lays them out in a very Node.js style dependency management system.