[Feature Request]: Implement support for native ARM64 enablement in NetFx AnyCPU executables
Summary
Windows is adding support for "arm64" as the supported architecture listed in the Win32 executable manifest. AnyCPU executables with such an element in the manifest will run natively on ARM64 Windows. This issue is about having MSBuild support the new thing by adding a new property called PreferNativeArm64.
Background and Motivation
The behavior on ARM64 Windows so far has been for AnyCPU executables to run emulated, out of the fear that the developer may not have anticipated such an architecture when they built the program. This is similar to the Prefer32Bit property, which was added some time ago to keep AnyCPU executables running in 32-bit WoW on x64 Windows.
Proposed Feature
A new property called PreferNativeArm64 is understood by common targets. Notable differences between PreferNativeArm64 and the existing Prefer32Bit prop are:
-
Prefer32Bitis true by default and the developer has to opt out by setting it to false.PreferNativeArm64is a false-by-default opt-in switch. -
Prefer32Bittranslates to a bit in the COR header whilePreferNativeArm64makes the toolchain add an element to the Win32 manifest embedded in the executable.
At high level, if the new property is set to true, MSBuild will generate a manifest file with the following contents:
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2024/WindowsSettings">
<supportedArchitectures>amd64 arm64</supportedArchitectures>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
The contents is combined from two sources. It is the new <supportedArchitectures> element merged with the contents of the file named default.win32manifest in the .NET Framework install folder (commonly C:\Windows\Microsoft.NET\Framework\v4.0.30319). This ensures that the manifest will be the same as what's embedded by the C#/VB compiler by default, other than the new element.
If the project already specifies a custom Win32 manifest using the ApplicationManifest property, this file is used as a source instead of default.win32manifest and the <supportedArchitectures> element is merged into it. That way the manifest will be the same as what's embedded by the C#/VB compiler when it's passed a -win32manifest, other than the new element.
Error conditions:
- If
PreferNativeArm64is true andPrefer32Bitis explicitly set to true, a build error is reported. These two options are mutually exclusive. - If
PreferNativeArm64is true and theNoWin32Manifestis true, a build error is reported. These two options are mutually exclusive. - If
PreferNativeArm64is true, a custom manifest is specified usingApplicationManifest, and the manifest already contains the<supportedArchitectures>element with something else than "amd64 arm64", a build error is reported. - If
PreferNativeArm64is true and the project does not target .NET Framework, a build warning is reported. This is similar to how the build already warns aboutPrefer32Bitwhen not targeting .NET Framework. - If
PreferNativeArm64is true and the project targets other platform than AnyCPU, a build warning is reported.Prefer32Bitdoes not seem to implement this validation in common targets.
Alternative Designs
We could alternatively add a new flag to the C#/VB compiler, pushing the work of injecting the <supportedArchitectures> element to the default or user-specified manifest down to the compiler. However, MSBuild is better positioned for this work because it is a single choking point for potentially multiple compilers.
cc @rainersigwald @tmeschter
The project system in VS will likely expose the new prop as a check box with some of the validation specified above, e.g. enabled only when targeting NetFx AnyCPU.
The supportedArchitectures documentation https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests#supportedarchitectures says
For IL-only .NET executables, specifies a list of native processor architectures the application is compatible with.
Which seems to mean that the element applies only to .NET and not to .NET Framework. Is it actually the other way around? This text came from https://github.com/MicrosoftDocs/win32/pull/1803.
It's the other way round - Windows is not involved with activating the runtime for .NET (Core) executables.
@KalleOlaviNiemitalo thank you for pointing it out. Documentation update: https://github.com/MicrosoftDocs/win32/pull/1855