【问题标题】:Relationship between PlatformTarget and RuntimeIdentifier in .NET 5.NET 5 中 PlatformTarget 和 RuntimeIdentifier 之间的关系
【发布时间】:2021-10-19 20:38:52
【问题描述】:

我对 .NET 5 中 RuntimeIdentifier 和 PlatformTarget 之间的关系感到困惑。 我的 .NET 5 C# 项目运行和发布正常,但 PlatformTarget 是“AnyCPU”,RuntimeIdentifier 是“win-x64”。

从微软的文档中,RuntimeIdentifier 是“用于识别应用程序运行的目标平台”。 https://docs.microsoft.com/en-us/dotnet/core/rid-catalog 这不是“PlatformTarget”应该做的吗?

我尝试使用我以前见过的 RuntimeIdentifers(复数)(可能是 .NET Core 3?),但该项目无法编译:

<RuntimeIdentifiers>win-x64;win-x86</RuntimeIdentifiers>

来自我当前的项目文件:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net5.0-windows</TargetFramework>
    <PublishSingleFile>true</PublishSingleFile>
    <SelfContained>true</SelfContained>
    <RuntimeIdentifier>win-x64</RuntimeIdentifier>   -> RuntimeIdentifier is required since SelfContained is 'true'
    ...
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    ...
    <PlatformTarget>AnyCPU</PlatformTarget>
  </PropertyGroup>
  ...
</Project>

【问题讨论】:

标签: c# .net-5 csproj


【解决方案1】:

确实,一堆属性很难理解(Platform、Platforms、PlatformTarget、TargetFramework(Moniker)和RuntimeIdentifier)。这是我目前对这些属性的看法 - 请记住,由于我的实验结果,我仍然有疑问)。

Platform、Platforms 和 PlatformTarget:这些属性是一种同义词(需要使用 Platforms 复数来保存多个平台说明符),并指的是位数/CPU 架构,例如 AnyCPU、x86、x64 和 Arm。我一直认为这个属性是“硬件”。

TargetFramework:这指定了应用程序打算在其上运行的 NET Framework API 版本(net48、net5.0、wp(Windows 手机)、netcore、netcoreapp2.1 等)。其中一些是跨平台的(跨硬件?)。

RuntimeIdentifier:运行时说明符是堆栈的跨​​平台粘合部分,位于抽象级别堆栈中:app->framework->runtime->platform。如果您的库同时配置为 x86 和 x64,msbuild 会将变体发布到 bin/debug/framework/win-x86/ 和 bin/debug/framework/win-x64/(以便 win-x86 和 win-64 以及其他运行时是输出文件夹树中的兄弟姐妹)。

您必须为您使用的每个运行时发布/构建一次项目(使用不同的属性值)。

对于最初的问题,您可以看到 AnyCPU 是平台说明符,RID 是运行时标识符。为了方便交流,RID 名字对象通常在其名称中包含 x86/x64,但这些字符串并未指定平台。只有平台说明符可以说明平台。

在操作中,可以指定Platform AnyCPU来构建应用程序(表示应用程序二进制适合x86、x64、arm等,然后在发布操作中使用特定的运行时(这将分配32/64位数等到已发布的二进制文件)。

如果没有提供 MSBuild 覆盖参数,我的 NET 5 项目文件需要同时定义 Platform 和 TargetFramework。 MSBuild 在我定义 Platform=AnyCPU 和 TargetFramework=net5.0-windows7.0 的项目上假定运行时为 win-x64。

值得一提的是,MSBuild 可以从三个地方获取其属性:MSBuild 项目文件; Visual Studio 对话框表(可能覆盖项目文件值;和 MSBuild 命令行(覆盖项目文件值)。

【讨论】:

    【解决方案2】:

    “AnyCPU”一词意味着它将具有兼容 32 位和 64 位的二进制文件。这意味着它并不特定于 32 位和 64 位,而且这个“AnyCPU”主要用于较旧的 .NET Framework 项目,不常用在主要用于 .NET Core 项目的 SDK 项目样式中。

    这些 .NET Core 项目包括单目标 .NET Core 项目或多目标 .NET Core 项目,例如具有多个目标的项目(通常称为 TFM)。

    从 .NET 5.0 开始,TFM 可以是跨平台 TFM,例如 net5.0 或具有特定操作系统的 .NET 5.0 目标,例如 net5.0-windows 或 net5.0-ios。如果要指定在 Windows 上运行 64 位的 .NET 5.0 类库,则必须同时指定 TFM 和 RuntimeIdentifier(通常称为 RID)。

    因此,我们不应将旧的“AnyCPU”与组合的条件“Release|AnyCPU”一起使用。默认情况下,任何没有 RID 的 TFM 始终与这些 SDK 项目模型中的 AnyCPU 相同。

    例如,针对 64 位和 32 位 Windows 上的 .NET 5.0:

    <PropertyGroup>
      <TargetFramework>net5.0-windows;</TargetFramework>
      <RuntimeIdentifier>win-x64;win-x86</RuntimeIdentifier>
      <PublishSingleFile>true</PublishSingleFile>
      <SelfContained>true</SelfContained>
    </PropertyGroup>
    
    

    SDK 项目在标头中有属性 Sdk="...",此 SDK 将为您的项目驱动参考分辨率。

    我建议您删除那些具有较旧的“Release|AnyCPU”或“Debug|AnyCPU”组合的 PropertyGroup,因为这些组合的 MSBuild 项目语法与任何 .NET Core SDK 项目模型都不相关。

    需要注意的一点是,当您拥有多个像上面示例中那样的 RID 时,您必须为您支持的每个 RID 运行发布。

    因此,为了同时拥有 64 位和 32 位,您必须为每个 RID 分别发布。

    所以你必须运行这些:

    dotnet publish yourproject.csproj -r win-x64 
    dotnet publish yourproject.csproj -r win-x86 
    

    另请参阅发布单个文件可执行文件的官方文档: https://docs.microsoft.com/en-us/dotnet/core/deploying/single-file

    【讨论】:

    • 现在我已经回答了一些 TL;DR 类型的答案,我冒着被其他 .NET Core 开发人员烧毁的风险,因为这可能是一个非常热门和敏感的话题。 :)
    • 那么为什么“AnyCPU”仍然是“平台目标”的 .NET 5 项目属性中的一个选项?
    • 另外,我使用命令行“upgrade-assistant”升级项目文件 - 为什么它会留在你提到的属性组中?
    • Eriawan:在 VS 2019 中打开一个全新的 .NET 5 WinForms C# 项目,不仅 AnyCPU 是一个选项,它还是“目标平台”的 默认 选项。跨度>
    • 并且“win-x64;win-x86”添加到项目文件时不会编译。 “win-x64;win-x86”也没有。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多