Pace Pace -3 years ago 122
C# Question

What does the win/any runtime mean in .NET Core

I'm building a C# .NET core application and it is targeting the

net452
framework. When I publish I can specify a runtime (--runtime), if I don't specify any runtime it uses
win7-x64
(I assume that is because that is what my machine is running). However, I can also manually specify the runtime and it seems to accept any string I give it. However, the RID catalog seems to suggest both
win
as well as
any
are valid.

UPDATE: I don't have any good answers so I'm going to clarify my questions and add a bounty. I've also asked on the ASP.NET core forums but gotten no response.


  1. If I specify a RID of
    win7-x32
    will my code also run on a 64 bit Windows OS?

  2. If I specify a RID of
    win7
    , what does it build, will it build the 32 bit version or the 64 bit version?

  3. If I specify a RID of
    win7
    , will my program run in Windows 8, 8.1, or 10?

  4. What does the
    any
    RID do? I understand how the portable deployment can be used on multiple platforms but how can the standalone deployment (built with a RID of
    any
    ) work on Linux as well as Windows? Am I misunderstanding this RID?

  5. If I specify a RID of
    blah
    I expected an error. Instead my application was built in the
    bin/Release/blah
    directory. Did it simply default to some other runtime?


Answer Source

RIDs are used with .NET Core to resolve dependencies on packages. The root for this process of resolving dependencies is your project, which you explicitly tag with one or more RIDs. When building the project, you indicate which RID you are building against.

RIDs are defined in a forest of compatibility trees, where any node in a tree represents an execution environment that can support all of its children. Each RID is the root of such a tree.

Here is an example RID compatibility tree:

win10-x64
|- win10
|  `- win81
|     `- win8
|        `- win7
|           `- win
|              `- any
|                 `- base
`- win81-x64
   |- win81 (already included above)
   `- win8-x64
      |- win8 (already included above)
      `- win7-x64
         |- win7 (already included above)
         `- win-x64
            `- win (already included above)

The full graph of RID compatibility trees is defined here:

https://github.com/dotnet/corefx/blob/master/pkg/Microsoft.NETCore.Platforms/runtime.json

A package can supply a different implementation for every RID if necessary. When building, if I have a dependency on that package, the build process will select the implementation closest to the root of the tree. If the tree doesn't contain any RIDs supplied by the package, then the build will fail.

There is a special kind of package called a "runtime package". Runtime packages contain native binaries that be directly loaded and executed by the host operating system. As such, these packages only supply implementations for concrete OS versions: "win7-x64", for instance, but not "win7" or "win-x64", and, say, "ubuntu.16.04-x64", but not "ubuntu.16.04", "ubuntu-x64" or "linux".

Runtime packages come into play when bundling stand-alone projects. With a stand-alone project, everything needed to run the project must be included in the build output. This means the build output must include a native binary as the entrypoint for the application. That native binary is supplied by the runtime package.

So, to address your questions:

  1. If I specify a RID of win7-x32 will my code also run on a 64 bit Windows OS?

Yes it will, but it will run in a 32-bit process. I have verified this with an app built & published from an Ubuntu dev VM and subsequently run on Windows 10 64-bit; if the app is published against win7-x32, then IntPtr.Size is 4, and if it is published against win7-x64, then IntPtr.Size is 8. It runs either way.

The win7-x32 runtime package includes a 32-bit EXE file that hosts the .NET Core runtime and then loads & runs your project, which is bundled alongside it in a DLL file with the same name.

  1. If I specify a RID of win7, what does it build, will it build the 32 bit version or the 64 bit version?

If you specify a RID of win7, it will try to find native binary builds tagged with that RID, or a compatible RID, but it won't find any. The build will fail, because there is no "win7" version of the main entrypoint EXE. You must specify either 32-bit or 64-bit (and it looks like all other platforms are 64-bit only).

I have tested this specific detail, and have found that:

  • The dotnet restore step does not fail, but also does not install a runtime for win7 (or win10).

  • The dotnet build step succeeds in compiling the test application, but then emits this error:

    Failed to make the following project runnable: helloworld (.NETCoreApp,Version=v1.1) reason: Expected coreclr library not found in package graph. Please try running dotnet restore again.

  1. If I specify a RID of win7, will my program run in Windows 8, 8.1, or 10?

Assuming you specify either win7-x86 or win7-x64, then yes. The win7-x86 or win7-x64 runtime package will supply an EXE entrypoint that is a 32-bit or 64-bit EXE, respectively, and those EXEs are native binaries that will run on any Windows version starting with Windows 7.

Note that there is no runtime package currently for Windows 8, Windows 8.1 or Windows 10 specifically. The compatibility graphs for newer Windows versions includes either win7-x86 or win7-x64, as appropriate, and so that particular runtime package ends up being used in the build, even if you target a newer RID such as win10-x64.

  1. What does the any RID do? I understand how the portable deployment can be used on multiple platforms but how can the standalone deployment (built with a RID of any) work on Linux as well as Windows? Am I misunderstanding this RID?

The any RID allows a package to supply an implementation for any RID further up the chain, because all other RIDs ultimately include any (and base) in their compatibility tree. Runtime packages, though, do not supply any implementation for any, and thus any cannot be used to build stand-alone packages.

  1. If I specify a RID of blah I expected an error. Instead my application was built in the bin/Release/blah directory. Did it simply default to some other runtime?

Your project must be configured with "type": "platform" in the dependency on Microsoft.NETCore.App. As such, no stand-alone package was built, and the resolution of supporting libraries is left to runtime, at which point the RID is supplied by the actual runtime you are using to run your app, rather than by your application's build configuration.

If your project is a library, then when you try to reference it from another project, you may encounter problems because your library is only supplying an implementation for the "blah" platform, which won't be in the compatibility tree for the RID the other project is building against. If your project is an application, then blah is being ignored.

If you reconfigure your project to produce a stand-alone package (by removing or commenting out the "type": "platform" line in project.json), you will find that it no longer builds, because it now has a dependency on the runtime packages, and there is no package for RID blah.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download