Relationship between PlatformTarget and RuntimeIdentifier in .NET 5
Asked Answered
O

2

7

I'm confused about the relationship between RuntimeIdentifier and PlatformTarget in .NET 5. My .NET 5 C# project runs and publishes fine, but PlatformTarget is 'AnyCPU' and RuntimeIdentifier is 'win-x64'.

From Microsoft's documentation, RuntimeIdentifier is "used to identify target platforms where the application runs". https://learn.microsoft.com/en-us/dotnet/core/rid-catalog Isn't this what 'PlatformTarget' is supposed to do?

I tried using RuntimeIdentifers (plural) which I've seen before (perhaps .NET Core 3?), but the project doesn't compile with this:

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

From my current project file:

<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>
Oleta answered 18/8, 2021 at 2:7 Comment(4)
Does this help #43520190Evensong
Unfortunately not - that question doesn't even mention PlatformTarget.Oleta
I found a page that mentions PlatformTarget. It's a little dated and doesn't mention SDK style projects. learn.microsoft.com/en-us/visualstudio/msbuild/…Among
And here's a doc on PlatformTarget as it relates to the C# compiler. learn.microsoft.com/en-us/dotnet/csharp/language-reference/…Among
J
4

It's true that the pile of properties is difficult to understand (Platform, Platforms, PlatformTarget, TargetFramework (Moniker), and RuntimeIdentifier). Here is my current take on the properties - keep in mind that I have still have questions because of the results of my experiments).

Platform, Platforms, and PlatformTarget: These properties are kind of synonyms (Platforms plural is required to hold multiple platform specifiers) and refer to the bitness/CPU architectures such as AnyCPU, x86, x64, and Arm. I always think "hardware" for this property.

TargetFramework: This specifies a NET Framework API version that the app is intended to run on (net48, net5.0, wp (windows phone), netcore, netcoreapp2.1, etc). Some of these are cross-platform (cross-hardware?).

RuntimeIdentifier: The runtime specifier is the cross-platform glue part of the stack and sits here in the abstraction level stack: app->framework->runtime->platform. If your library was configured for both x86 and x64, msbuild publishes the variations to bin/debug/framework/win-x86/ and bin/debug/framework/win-x64/ (so that win-x86 and win-64 and other runtimes are siblings in the output folder tree).

You must publish/build your project once (with different property values) for each runtime that you use.

To the original question, you can see that AnyCPU is a platform specifier and RIDs are runtime identifiers. The RID monikers often include x86/x64 in their names for communication convenience, but those strings do not specify the platform. Only the Platform specifier can specifier the platform.

In operation, you can specify Platform AnyCPU for building the app (indicating the app binary is appropriate for x86, x64, arm, etc., and then use a specific runtime in the publication operation (which will assign the 32/64 bitness etc. to the published binary).

My NET 5 project files require the definition of both a Platform and a TargetFramework if no MSBuild override arguments are provided. MSBuild assumes win-x64 for the runtime on my projects that define Platform=AnyCPU and TargetFramework=net5.0-windows7.0.

It's worth saying that MSBuild can get its properties from three places: the MSBuild project file; the Visual Studio dialog sheets (probably override the project file values; and the MSBuild command line (override the project file values).

Jannjanna answered 6/2, 2022 at 5:38 Comment(0)
E
2

The term of "AnyCPU" means that it will have binaries that is compatible for both 32bit and 64bit. This means it is not meant to be specific for either 32bit and 64bit, and this "AnyCPU" is mostly used in older .NET Framework project, not commonly used in SDK project style that is mainly used in .NET Core projects.

These .NET Core projects include single targeted .NET Core project or multi targeted .NET Core projects, such as those that has with multiple target (usually known as TFM).

Since .NET 5.0, the TFM can be cross platform TFM such as net5.0 or .NET 5.0 target with specific OS, such as net5.0-windows or net5.0-ios. IF you want to specify .NET 5.0 class libraries that runs on Windows for 64bit, you have to specify both TFM and RuntimeIdentifier (usually called RID).

Therefore we should not use the older "AnyCPU" with combined Conditional "Release|AnyCPU". By default, any TFM without RID is always the same as having AnyCPU in these SDK project model.

For example, for targeting .NET 5.0 on Windows on both 64bit and 32bit:

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

The SDK projects has attribute Sdk="..." in the header, and this SDK will drive the reference resolutions for your project.

I recommend you to remove those PropertyGroup that has older "Release|AnyCPU" or "Debug|AnyCPU" combinations, because these combined MSBuild project syntax is not relevant for any .NET Core SDK project model.

One thing to be noted is when you have more than one RID like those in the sample above, you have to run publish for each RID you support.

Therefore, in order to have both 64bit and 32bit, you have to publish separately for each RID.

SO you have to run these:

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

See also the official doc on publishing single file executable: https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file

Ellord answered 18/8, 2021 at 14:31 Comment(6)
Now that I have answered with a bit TL;DR kind of answer, I'm risking myself to be burnt by other .NET Core developers since this might be quite hot and sensitive topic. :)Ellord
Then why is "AnyCPU" still an option in .NET 5 project properties for "Platform target"?Oleta
Also, I used the command line "upgrade-assistant" to upgrade the project file - why would it leave in the property groups you mentioned?Oleta
about this: "why is "AnyCPU" still an option in .NET 5 project properties for "Platform target"?" it is not true. If you correctly use SDK project, there will be no AnyCPU.Ellord
Eriawan: Open a brand new .NET 5 WinForms C# project in VS 2019 and not only is AnyCPU an option, it's the default option for "Target platform".Oleta
And "<RuntimeIdentifier>win-x64;win-x86</RuntimeIdentifier>" doesn't compile when added to the project file. And neither does "<RuntimeIdentifiers>win-x64;win-x86</RuntimeIdentifiers>".Oleta

© 2022 - 2024 — McMap. All rights reserved.