.NET Core distribution packaging

As .NET Core becomes available on more and more platforms, it's useful to learn how to package, name, and version it. This way, package maintainers can help ensure a consistent experience no matter where users choose to run .NET. This article is useful for users that are:

  • Attempting to build .NET Core from source.
  • Wanting to make changes to the .NET Core CLI that could impact the resulting layout or packages produced.

Disk layout

When installed, .NET Core consists of several components that are laid out as follows in the filesystem:

.
├── dotnet                       (1)
├── LICENSE.txt                  (8)
├── ThirdPartyNotices.txt        (8)
├── host
│   └── fxr
│       └── <fxr version>        (2)
├── sdk
│   ├── <sdk version>            (3)
│   └── NuGetFallbackFolder      (4)
└── shared
    ├── Microsoft.NETCore.App
    │   └── <runtime version>    (5)
    └── Microsoft.AspNetCore.App
        └── <aspnetcore version> (6)
    └── Microsoft.AspNetCore.All
        └── <aspnetcore version> (7)
/
├─usr/share/man/man1
│       └── dotnet.1.gz          (9)
└─usr/bin
        └── dotnet               (10)
  • (1) dotnet The host (also known as the "muxer") has two distinct roles: activate a runtime to launch an application, and activate an SDK to dispatch commands to it. The host is a native executable (dotnet.exe).

While there's a single host, most of the other components are in versioned directories (2,3,5,6). This means multiple versions can be present on the system since they're installed side by side.

  • (2) host/fxr/<fxr version> contains the framework resolution logic used by the host. The host uses the latest hostfxr that is installed. The hostfxr is responsible for selecting the appropriate runtime when executing a .NET Core application. For example, an application built for .NET Core 2.0.0 uses the 2.0.5 runtime when it's available. Similarly, hostfxr selects the appropriate SDK during development.

  • (3) sdk/<sdk version> The SDK (also known as "the tooling") is a set of managed tools that are used to write and build .NET Core libraries and applications. The SDK includes the .NET Core Command-line interface (CLI), the managed languages compilers, MSBuild, and associated build tasks and targets, NuGet, new project templates, and so on.

  • (4) sdk/NuGetFallbackFolder contains a cache of NuGet packages used by an SDK during the restore operation, such as when running dotnet restore or dotnet build /t:Restore.

The shared folder contains frameworks. A shared framework provides a set of libraries at a central location so they can be used by different applications.

  • (5) shared/Microsoft.NETCore.App/<runtime version> This framework contains the .NET Core runtime and supporting managed libraries.

  • (6,7) shared/Microsoft.AspNetCore.{App,All}/<aspnetcore version> contains the ASP.NET Core libraries. The libraries under Microsoft.AspNetCore.App are developed and supported as part of the .NET Core project. The libraries under Microsoft.AspNetCore.All are a superset that also contains third-party libraries.

  • (8) LICENSE.txt,ThirdPartyNotices.txt are the .NET Core license and licenses of third-party libraries used in .NET Core, respectively.

  • (9,10) dotnet.1.gz, dotnet dotnet.1.gz is the dotnet manual page. dotnet is a symlink to the dotnet host(1). These files are installed at well known locations for system integration.

.NET Core versioning is based on the runtime component [major].[minor] version numbers. The SDK version uses the same [major].[minor] and has an independent [patch] that combines feature and patch semantics for the SDK. For example: SDK version 2.2.302 is the second patch release of the third feature release of the SDK that supports the 2.2 runtime. For more information about how versioning works, see .NET Core versioning overview.

Some of the packages include part of the version number in their name. This allows you to install a specific version. The rest of the version isn't included in the version name. This allows the OS package manager to update the packages (for example, automatically installing security fixes). Supported package managers are Linux specific.

The following table shows the recommended packages:

Name Example Use case: Install ... Contains Dependencies Version
dotnet-sdk-[major] dotnet-sdk-2 Latest sdk for runtime major dotnet-sdk-[major].[latestminor] <sdk version>
dotnet-sdk-[major].[minor] dotnet-sdk-2.1 Latest sdk for specific runtime dotnet-sdk-[major].[minor].[latest sdk feat]xx <sdk version>
dotnet-sdk-[major].[minor].[sdk feat]xx dotnet-sdk-2.1.3xx Specific sdk feature release (3),(4) aspnetcore-runtime-[major].[minor] <sdk version>
aspnetcore-runtime-[major].[minor] aspnetcore-runtime-2.1 Specific ASP.NET Core runtime (6),[(7)] dotnet-runtime-[major].[minor] <runtime version>
dotnet-runtime-[major].[minor] dotnet-runtime-2.1 Specific runtime (5) host-fxr:<runtime version>+ <runtime version>
dotnet-host-fxr dotnet-host-fxr dependency (2) host:<runtime version>+ <runtime version>
dotnet-host dotnet-host dependency (1),(8),(9),(10) <runtime version>

Most distributions require all artifacts to be built from source. This has some impact on the packages:

  • The third-party libraries under shared/Microsoft.AspNetCore.All can't be easily built from source. So that folder is omitted from the aspnetcore-runtime package.

  • The NuGetFallbackFolder is populated using binary artifacts from nuget.org. It should remain empty.

Multiple dotnet-sdk packages may provide the same files for the NuGetFallbackFolder. To avoid issues with the package manager, these files should be identical (checksum, modification date, and so on).

Preview versions

Package maintainers may decide to provide preview versions of the shared framework and SDK. Preview releases may be provided using the dotnet-sdk-[major].[minor].[sdk feat]xx, aspnetcore-runtime-[major].[minor], or dotnet-runtime-[major].[minor] packages. For preview releases, the package version major must be set to zero. This way, the final release is installed as an upgrade of the package.

Patch packages

Since a patch version of a package may cause a breaking change, a package maintainer may want to provide patch packages. These packages allow you to install a specific patch version that isn't automatically upgraded. Only use patch packages in rare circumstances as they aren't upgraded with (security) fixes.

The following table shows the recommended packages and patch packages:

Name Example Contains Dependencies
dotnet-sdk-[major] dotnet-sdk-2 dotnet-sdk-[major].[latest sdk minor]
dotnet-sdk-[major].[minor] dotnet-sdk-2.1 dotnet-sdk-[major].[minor].[latest sdk feat]xx
dotnet-sdk-[major].[minor].[sdk feat]xx dotnet-sdk-2.1.3xx dotnet-sdk-[major].[minor].[latest sdk patch]
dotnet-sdk-[major].[minor].[patch] dotnet-sdk-2.1.300 (3),(4) aspnetcore-runtime-[major].[minor].[sdk runtime patch]
aspnetcore-runtime-[major].[minor] aspnetcore-runtime-2.1 aspnetcore-runtime-[major].[minor].[latest runtime patch]
aspnetcore-runtime-[major].[minor].[patch] aspnetcore-runtime-2.1.0 (6),[(7)] dotnet-runtime-[major].[minor].[patch]
dotnet-runtime-[major].[minor] dotnet-runtime-2.1 dotnet-runtime-[major].[minor].[latest runtime patch]
dotnet-runtime-[major].[minor].[patch] dotnet-runtime-2.1.0 (5) host-fxr:<runtime version>+
dotnet-host-fxr dotnet-host-fxr (2) host:<runtime version>+
dotnet-host dotnet-host (1),(8),(9),(10)

An alternative to using patch packages is pinning the packages to a specific version using the package manager. To avoid affecting other applications/users, such applications can be built and deployed in a container.

Building packages

The dotnet/source-build repository provides instructions on how to build a source tarball of the .NET Core SDK and all its components. The output of the source-build repository matches the layout described in the first section of this article.