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

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

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

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

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

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

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

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

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/corefx/blob/master/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开发虚拟机构建和发布的应用程序validation了这一点,随后在Windows 10 64位上运行; 如果应用程序是针对win7-x32 ,则IntPtr.Size为4,如果是针对win7-x64 ,则IntPtr.Size为8.它以任一方式运行。

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

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

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

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

  • dotnet restore步骤不会失败,但也不会为win7 (或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吗?

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

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

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

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

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

我相信与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 

因此,最佳RID,在评估win7-x64时将是: win7-x64win7win-x64winany同样,在评估win-x64win-x64winany注意win7win-x64之前出现win-x64因为在文档顺序导入win-x64之前导入win7

也就是说,并在CoreFX repo上引用runtime.json

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

仅提取相关部分,

1)如果我指定一个win7-x32的RID,我的代码也可以在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) any RID做什么?

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

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

引用表单文档:

所有RID最终都会映射回any RID的根。

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

虽然它们看起来很容易使用,但是在使用它们时你必须记住一些关于RID的特殊事项:

  • 它们是不透明的字符串,应该被视为黑盒子
    • 您不应该以编程方式构造RID
  • 您需要使用已为平台定义的RID,本文档将显示该RID
  • RID确实需要具体,所以不要假设实际的RID值; 请参阅此文档以确定给定平台所需的RID

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

  • linux-x64,linux-arm
  • win-x64,win-x86
  • OSX-64

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