win/any 运行时在 .NET Core 中意味着什么

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

我正在构建一个 C# .NET 核心应用程序,它针对 net452 框架。当我发布时,我可以指定一个 运行 时间(--运行 时间),如果我没有指定任何 运行 时间它使用 win7-x64(我假设这是因为这就是我的机器 运行ning)。但是,我也可以手动指定 运行time,它似乎可以接受我给它的任何字符串。但是,RID catalog 似乎表明 winany 都是有效的。

更新:我没有任何好的答案,所以我要澄清我的问题并增加赏金。我也在 ASP.NET 核心论坛上询问过,但没有得到任何回复。

  1. 如果我指定 win7-x32 的 RID,我的代码是否也会 运行 在 64 位 Windows OS?

  2. 如果我指定 win7 的 RID,它会构建什么,它会构建 32 位版本还是 64 位版本?

  3. 如果我指定 win7 的 RID,我的程序 运行 会在 Windows 8、8.1 或 10 中吗?

  4. any RID 有什么作用?我了解可移植部署如何在多个平台上使用,但独立部署(使用 any 的 RID 构建)如何在 Linux 和 Windows 上工作?我对这个 RID 有误解吗?

  5. 如果我指定 blah 的 RID,我预计会出现错误。相反,我的应用程序是在 bin/Release/blah 目录中构建的。它只是默认为其他 运行 时间吗?

我相信 OP 中链接的 official documentation 提供了所有必要的信息。

要事第一

What are RIDs?

RID is short for Runtime IDentifier. RIDs are used to identify target operating systems where an application or asset (that is, assembly) will run.

It is important to note that RIDs are really opaque strings. This means that they have to match exactly for operations using them to work.

这也引自GitHub

A RID is an opaque string that identifies a platform. RIDs have relationships to other RIDs by "importing" the other RID. In that way a RID is a directed graph of compatible RIDs.

Best RID Consider the partial RID-graph:

"any": {},

"win": {
    "#import": [ "any" ]
},
"win-x86": {
    "#import": [ "win" ]
},
"win-x64": {
    "#import": [ "win" ]
},
"win7": {
    "#import": [ "win" ]
},
"win7-x86": {
    "#import": [ "win7", "win-x86" ]
},
"win7-x64": {
    "#import": [ "win7", "win-x64" ]
}

This can be visualized as a directed graph, as follows:

win7-x64    win7-x86
   |   \   /    |
   |   win7     |
   |     |      |
win-x64  |  win-x86
      \  |  /
        win
         |
        any

As such, best RID, when evaluating for win7-x64 would be:win7-x64, win7, win-x64, win, any Similarly, when evaluating for win-x64: win-x64, win, any Note that win7 comes before win-x64 due to the import for win7 appearing before the import for win-x64 in document order.

也就是说,引用 runtime.json on the CoreFX repo.

If you use this file, you will notice that some of the RIDs have an "#import" statement in them. These statements are compatibility statements. That means that a RID that has an imported RID in it can be a target for restoring packages for that RID.

只提取相关部分,

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

"base": {
},

"any": {
    "#import": [ "base" ]
},
...
"win": {
    "#import": [ "any" ]
},
...
"win7": {
        "#import": [ "win" ]
    },
"win7-x86": {
    "#import": [ "win7", "win-x86" ]
},
"win7-x64": {
    "#import": [ "win7", "win-x64" ]
},
...

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?

是的。基于引用版本的导入。

"win8": {
    "#import": [ "win7" ]
},
"win8-x86": {
    "#import": [ "win8", "win7-x86" ]
},
"win8-x64": {
    "#import": [ "win8", "win7-x64" ]
},
"win8-arm": {
    "#import": [ "win8" ]
},

"win81": {
    "#import": [ "win8" ]
},
"win81-x86": {
    "#import": [ "win81", "win8-x86" ]
},
"win81-x64": {
    "#import": [ "win81", "win8-x64" ]
},
"win81-arm": {
    "#import": [ "win81", "win8-arm" ]
},

"win10": {
    "#import": [ "win81" ]
},
"win10-x86": {
    "#import": [ "win10", "win81-x86" ]
},
"win10-x64": {
    "#import": [ "win10", "win81-x64" ]
},

4) What does the any RID do?

这意味着构建与 any 支持的平台兼容,它可以作为任何 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?

引用表单文档:

All RIDs eventually map back to the root any RID.

最后,再次从文档中注意

Although they look easy enough to use, there are some special things about RIDs that you have to keep in mind when working with them:

  • They are opaque strings and should be treated as black boxes
    • You should not construct RIDs programmatically
  • You need to use the RIDs that are already defined for the platform and this document shows that
  • The RIDs do need to be specific so don't assume anything from the actual RID value; please consult this document to determine which RID(s) you need for a given platform

RID 与 .NET Core 一起使用来解决对包的依赖性。这一解决依赖关系过程的根源是您的项目,您用一个或多个 RID 明确标记了该项目。构建项目时,指明要针对哪个 RID 进行构建。

RID 是在兼容树的森林中定义的,其中树中的任何节点都代表可以支持其所有子节点的执行环境。每个RID都是这样一棵树的根。

这是一个 RID 兼容性树示例:

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)

此处定义了 RID 兼容性树的完整图表:

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

如有必要,软件包可以为每个 RID 提供不同的实现。构建时,如果我对该包有依赖性,构建过程将 select 最接近树根的实现。如果树不包含包提供的任何 RID,则构建将失败。

有一种特殊的包叫做 "runtime package"。运行时包包含由主机操作系统直接加载和执行的本机二进制文件。因此,这些包仅提供具体 OS 版本的实现:例如 "win7-x64",但不提供 "win7" 或 "win-x64",以及 "ubuntu.16.04-x64",但不是 "ubuntu.16.04"、"ubuntu-x64" 或 "linux".

[更新: 从 .NET Core 2.0 开始,您可以为 Linux-x64 构建目标 "all" x64 版本的 Linux 与一个单一的构建。参见 https://blogs.msdn.microsoft.com/dotnet/2017/08/14/announcing-net-core-2-0/]

运行时包在捆绑 stand-alone 项目时发挥作用。对于 stand-alone 项目,运行 项目所需的一切都必须包含在构建输出中。这意味着构建输出必须包含一个本机二进制文件作为应用程序的入口点。本机二进制文件由 运行time 包提供。

所以,为了解决您的问题:

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

是的,但它会 运行 在 32 位进程中。我已经使用从 Ubuntu dev VM 构建和发布的应用程序验证了这一点,随后在 Windows 10 64 位上 运行;如果应用是针对 win7-x32 发布的,那么 IntPtr.Size 是 4,如果它是针对 win7-x64 发布的,那么 IntPtr.Size 是 8。它 运行 要么方式。

win7-x32运行time 包包含一个 32 位 EXE 文件,该文件托管 .NET Core 运行time,然后加载并 运行s 您的项目,它与它一起捆绑在同名的 DLL 文件中。

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

如果您指定 win7 的 RID,它将尝试查找标有该 RID 或兼容 RID 的本机二进制构建,但它不会找到任何内容。构建将失败,因为没有 "win7" 版本的主入口点 EXE。您必须指定 32 位或 64 位(看起来所有其他平台都只有 64 位)。

我测试了这个具体细节,发现:

  • dotnet restore步骤没有失败,但也没有为win7(或win10)安装运行时间。

  • dotnet build 步骤成功编译测试应用程序,但随后出现此错误:

    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?

假设您指定 win7-x86win7-x64,那么可以。 win7-x86win7-x64 运行time 包将分别提供 32 位或 64 位 EXE 的 EXE 入口点,这些 EXE 是本机二进制文件,将 运行 在以 Windows 7.

开头的任何 Windows 版本上

请注意,目前没有针对 Windows 8、Windows 8.1 或 Windows 10 的 运行 时间包。较新 Windows 版本的兼容性图表包括 win7-x86win7-x64,视情况而定,因此特定的 运行time 包最终会在构建中使用,即使您以更新的 RID 为目标,例如 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?

any RID 允许包为链上游的任何 RID 提供实现,因为所有其他 RID 最终都在其兼容性树中包含 any(和 base) .但是,运行时包不为 any 提供任何实现,因此 any 不能用于构建 stand-alone 包。

  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?

您的项目必须在 Microsoft.NETCore.App 的依赖项中配置 "type": "platform"。因此,没有构建 stand-alone 包,支持库的分辨率留给 运行 时间,此时 RID 由您使用的实际 运行 时间提供 运行 您的应用程序,而不是应用程序的构建配置。

如果您的项目是一个库,那么当您尝试从另一个项目引用它时,您可能会遇到问题,因为您的库仅提供 "blah" 平台的实现,而该平台不会在另一个项目正在构建的 RID 的兼容性树。如果您的项目是一个应用程序,那么 blah 将被忽略。

如果您重新配置项目以生成 stand-alone 包(通过删除或注释掉 project.json 中的 "type": "platform" 行),您会发现它不再构建,因为它现在依赖于 运行time 包,我在那里没有 RID blah.

的软件包

在 .NET Core 2.0 下,足以构建以下目标:

  • linux-x64,linux-手臂
  • win-x64, win-x86
  • osx-x64

参见 https://blogs.msdn.microsoft.com/dotnet/2017/08/14/announcing-net-core-2-0/