39

我正在构建一个 C# .NET 核心应用程序,它以net452框架为目标。当我发布时,我可以指定一个运行时(--runtime),如果我不指定它使用的任何运行时win7-x64(我假设这是因为我的机器正在运行)。但是,我也可以手动指定运行时,它似乎接受我给它的任何字符串。但是,RID 目录似乎表明两者win都是any有效的。

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

  1. 如果我指定一个 RID,win7-x32我的代码是否也可以在 64 位 Windows 操作系统上运行?

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

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

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

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

4

3 回答 3

37

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 提供不同的实现。构建时,如果我对该包有依赖关系,则构建过程将选择最接近树根的实现。如果树不包含包提供的任何 RID,则构建将失败。

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

[更新:从 .NET Core 2.0 开始,您可以针对 Linux-x64 进行构建,以通过单个构建来定位“所有”x64 版本的 Linux。见https://blogs.msdn.microsoft.com/dotnet/2017/08/14/announcing-net-core-2-0/ ]

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

因此,为了解决您的问题:

  1. 如果我指定 win7-x32 的 RID,我的代码是否也可以在 64 位 Windows 操作系统上运行?

是的,它会,但它将在 32 位进程中运行。我已经使用从 Ubuntu 开发虚拟机构建和发布的应用程序验证了这一点,随后在 Windows 10 64 位上运行;如果应用程序针对 发布win7-x32IntPtr.Size则为 4,如果针对 发布win7-x64IntPtr.Size则为 8。它以任一方式运行。

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

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

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

我已经测试了这个特定的细节,并发现:

  • dotnet restore步骤不会失败,但也不会为win7(or win10) 安装运行时。

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

    无法使以下项目可运行:helloworld (.NETCoreApp,Version=v1.1) 原因:在包图中找不到预期的 coreclr 库。请尝试再次运行 dotnet restore。

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

假设您指定win7-x86win7-x64,那么是的。win7-x86win7-x64运行时包将分别提供一个 32 位或 64 位 EXE 的 EXE 入口点,这些 EXE 是本机二进制文件,可在从 Windows 7 开始的任何 Windows 版本上运行。

请注意,目前没有专门针对 Windows 8、Windows 8.1 或 Windows 10 的运行时包。较新 Windows 版本的兼容性图包括win7-x86win7-x64(视情况而定),因此特定运行时包最终会在构建中使用,即使您针对较新的 RID,例如win10-x64.

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

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

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

您的项目必须配置"type": "platform"为依赖于Microsoft.NETCore.App. 因此,没有构建独立包,支持库的解析留给运行时,此时 RID 由您用于运行应用程序的实际运行时提供,而不是由应用程序的构建配置提供。

如果您的项目是一个库,那么当您尝试从另一个项目中引用它时,您可能会遇到问题,因为您的库只为“blah”平台提供了一个实现,它不会在 RID 的兼容性树中其他项目正在建设中。如果您的项目是应用程序,则将blah被忽略。

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

于 2017-01-25T23:20:58.650 回答
17

我相信 OP 中链接的官方文档提供了所有必要的信息。

第一件事

什么是 RID?

RID 是 Runtime IDentifier 的缩写。RID 用于识别应用程序或资产(即程序集)将运行的目标操作系统。

需要注意的是,RID 确实是不透明的字符串。这意味着它们必须与使用它们的操作完全匹配才能工作

这也是从GitHub引用的

RID 是标识平台的不透明字符串。RID 通过“导入”另一个 RID 与其他 RID 建立关系。这样,RID 就是兼容 RID 的有向图。

最佳 RID 考虑部分 RID 图:

"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" ]
}

这可以可视化为有向图,如下所示:

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

因此,在评估 win7-x64 时,最佳 RID 将是:win7-x64, win7, win-x64, win,any类似地,在评估 win-x64: win-x64,时winany请注意,由于导入出现 在文档顺序中的导入win7之前 ,因此出现在之前。win-x64win7win-x64

也就是说,并参考runtime.jsonCoreFX 回购。

如果您使用此文件,您会注意到某些 RID 中包含“#import”语句。这些陈述是兼容性陈述。这意味着其中具有导入的 RID 的 RID 可以成为恢复该 RID 的包的目标。

仅提取相关部分,

1) 如果我指定 RID,win7-x32我的代码是否也可以在 64 位 Windows 操作系统上运行?

"base": {
},

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

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

它将构建一个可以在两个平台上运行的通用版本。参考上面的可视化。

3) 如果我指定 win7 的 RID,我的程序会在 Windows 8、8.1 或 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) anyRID 做什么?

这意味着该构建与any支持的平台兼容,并且它可以成为为任何 RID 恢复包的目标。

5) 如果我指定一个 RID,blah我预计会出错。相反,我的应用程序是在bin/Release/blah directory. 它只是默认为其他一些运行时吗?

报价单文件:

所有 RID 最终都映射回根anyRID。

最后,再次从文档中,注意

尽管它们看起来很容易使用,但在使用它们时,您必须牢记一些关于 RID 的特殊事项:

  • 它们是不透明的字符串,应该被视为黑盒子
    • 不应以编程方式构造 RID
  • 您需要使用已为平台定义的 RID,本文档显示
  • RID 确实需要具体,因此不要从实际的 RID 值中假设任何内容;请查阅本文档以确定给定平台所需的 RID
于 2017-01-25T19:16:23.013 回答
4

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

  • linux-x64, linux-arm
  • 赢x64,赢x86
  • osx-x64

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

于 2017-08-16T04:46:23.357 回答