[android] Enable android-arm CoreCLR with softfp ABI handling#127578
[android] Enable android-arm CoreCLR with softfp ABI handling#127578simonrozsival wants to merge 6 commits intodotnet:mainfrom
Conversation
Enable the softfp ABI for Android ARM native/CoreCLR builds. Teach Crossgen2 to accept android as a target OS and choose the armel ABI for android-arm before normalizing the target OS to Linux for existing object and runtime behavior. Update the CoreLib, library test, SDK, and in-tree Android R2R callers to pass android/arm directly so linux-bionic RIDs keep their existing behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restore the android-arm CoreCLR runtime pack and CI enablement from dotnet#127225 now that the ABI handling is fixed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR re-enables android-arm (armeabi-v7a) CoreCLR runtime pack production and CI by ensuring Crossgen2/JIT agree on Android ARM32’s required softfp call-boundary ABI (modeled as armel in the type system), while keeping the rest of Crossgen2’s behavior on existing Linux/Bionic paths.
Changes:
- Teach Crossgen2 to accept
--targetos:android, and forandroid-armselect the softfp (armel) ABI then normalize the OS to Linux for the remaining pipeline. - Update Android build/plumbing to pass the real
$(TargetOS)to Crossgen2 (instead of remapping Android to Linux at the caller). - Re-enable
android_armCoreCLR runtime pack support and restore CI/Helix coverage, including Android ARM queue mapping.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/tasks/Crossgen2Tasks/ResolveReadyToRunCompilers.cs | Allows the Crossgen2 task logic to resolve android as a target OS from RID graph matching. |
| src/mono/msbuild/android/build/AndroidBuild.InTree.targets | Passes $(TargetOS) through to Crossgen2 for Android in-tree builds. |
| src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.CoreCLR.sfxproj | Stops remapping Android to Linux for Crossgen2 invocation; passes $(TargetOS) directly. |
| src/coreclr/tools/Common/TypeSystem/Common/TargetDetails.cs | Adds TargetOS.Android to represent Android explicitly in target selection. |
| src/coreclr/tools/Common/CommandLineHelpers.cs | Enables parsing --targetos:android into TargetOS.Android. |
| src/coreclr/tools/aot/crossgen2/Program.cs | Implements Android normalization: select softfp (NativeAotArmel) for Android ARM32, then treat as Linux for the remaining Crossgen2 logic. |
| src/coreclr/tools/aot/crossgen2/Crossgen2RootCommand.cs | Updates extended help to include android as a valid --targetos value. |
| src/coreclr/crossgen-corelib.proj | Always passes --targetos:$(TargetOS) (removes Android→Linux remap at the caller). |
| src/coreclr/clrdefinitions.cmake | Defines ARM_SOFTFP for Android ARM32 targets so native/JIT compilation agrees on softfp. |
| eng/testing/tests.readytorun.targets | Passes $(TargetOS) to Crossgen2 for test R2R flows (removes Android→Linux remap). |
| eng/Subsets.props | Re-enables CoreCLR support gating for Android ARM32 (still excludes Android x86). |
| eng/pipelines/runtime.yml | Re-adds android_arm CoreCLR functional test coverage in the main pipeline matrix. |
| eng/pipelines/extra-platforms/runtime-extra-platforms-android.yml | Adds android_arm CoreCLR coverage in the extra-platforms Android pipeline. |
| eng/pipelines/coreclr/templates/helix-queues-setup.yml | Adds Helix queue mapping for the android_arm platform. |
| eng/native/configureplatform.cmake | Sets ARM_SOFTFP for Android ARM32 at CMake configuration time. |
|
/azp run runtime-extra-platforms |
|
Azure Pipelines successfully started running 1 pipeline(s). |
| TargetOS targetOS = Get(_command.TargetOS); | ||
| TargetAbi targetAbi = Crossgen2RootCommand.IsArmel ? TargetAbi.NativeAotArmel : TargetAbi.NativeAot; | ||
|
|
||
| if (targetOS == TargetOS.Android) |
There was a problem hiding this comment.
Android is handled in the target files for nativeaot currently:
. If we are going to promote it to a first class OS for crossgen2, we should do the same for NativeAOT too.There was a problem hiding this comment.
It seems the special casing of armel needs to duplicated in number of files. I think it would be fine to add Android to TargetOS enum if it made things easier.
My point was that both crossgen2 and nativeaot should do it the same way.
There was a problem hiding this comment.
I'm for making things easier via an enum. The pushback has always been if there's nothing special about Android in naot/r2r, handle it in the targets. I still think that's true.
There was a problem hiding this comment.
Centralizing the normalization of android -> linux and android-arm -> linux-armel makes the most sense to me. At the same time, I want to avoid making more changes than necessary in this PR. I wonder if we should do the refactoring later if needed.
There was a problem hiding this comment.
Note
This reply was generated with GitHub Copilot.
I went back to the centralized approach. TargetOS.Android is now recognized by the shared AOT command-line handling, and both Crossgen2 and NativeAOT ILCompiler normalize it internally: Android is treated as Linux for the effective target OS, and Android ARM selects the NativeAotArmel / softfp ABI.
I also updated the Crossgen2 call sites to pass the real Android target identity instead of duplicating the Android-to-Linux remap in MSBuild. NativeAOT now passes --targetos:android through to ILCompiler as well; its existing bionic ARM armel architecture mapping remains, and both compilers accept --targetos:android --targetarch:armel.
|
Note This CI analysis comment was drafted with Copilot. I compared the current CI on #127578 with the original Android ARM runtime-pack enablement PR, #127225, and the first softfp follow-up, #127527. My read is that the original Android ARM ABI mismatch is not manifesting in the current run: the exact smoke job that exposed it before now passes.
Current Android pass/fail breakdown:
Failure classification:
I also searched the current downloaded Android AzDO/Helix logs for the old ABI signatures: So I would not treat the current red CI as evidence that the original Android ARM ABI mismatch is still present. The important ABI validation signal passed; the remaining Android failures are later library/test-suite issues, mostly already represented by known mobile issues, with the NativeAOT |
Keep Android as Linux for Crossgen2 and pass armel from in-tree MSBuild callers so the compiler selects the softfp ABI without making Android a first-class Crossgen2 OS. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Align the Android ARM Crossgen2 remap with the existing _CrossGenTargetOS naming pattern and use _CrossGenTargetArch for the architecture remap. Keep the Android in-tree target simpler by hardcoding Crossgen2 TargetOS metadata to linux. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Re-enables CoreCLR support and CI coverage for android-arm by aligning Android ARM32 builds with the required softfp calling convention and updating Crossgen2 invocation plumbing to avoid ABI mismatches that can corrupt floating-point arguments/returns.
Changes:
- Enable softfp behavior for Android ARM32 in native/CoreCLR build configuration (ARM_SOFTFP).
- Adjust Crossgen2 target OS/arch arguments for Android ARM32 so R2R payloads use the softfp (
armel) ABI. - Re-enable
android_armCoreCLR runtime pack gating and add CI/Helix coverage forandroid_arm.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/tests/readytorun/multifolder/multifolder.csproj | Remaps Crossgen2 target OS/arch for Android ARM32 when generating the response file. |
| src/tests/Common/CLRTest.CrossGen.targets | Normalizes Crossgen2 --targetos/--targetarch for Android ARM32 in common test script generation. |
| src/mono/msbuild/android/build/AndroidBuild.InTree.targets | Forces Crossgen2 target arch to armel for ARM32 R2R compilation in Android in-tree builds. |
| src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.CoreCLR.sfxproj | Adjusts runtime-pack Crossgen2 tool item to use normalized target OS/arch (incl. armel for Android ARM32). |
| src/coreclr/crossgen-corelib.proj | Normalizes Crossgen2 target OS/arch for CoreLib crossgen on Android ARM32. |
| src/coreclr/clrdefinitions.cmake | Defines ARM_SOFTFP for Android+ARM in CoreCLR target definitions. |
| eng/testing/tests.readytorun.targets | Ensures Crossgen2 uses armel when running R2R tests for Android ARM32. |
| eng/Subsets.props | Unblocks CoreCLR support for Android ARM32 (still blocks Android x86). |
| eng/pipelines/runtime.yml | Adds android_arm to the main CoreCLR Android CI matrix. |
| eng/pipelines/extra-platforms/runtime-extra-platforms-android.yml | Adds android_arm to extra-platforms CoreCLR Android jobs. |
| eng/pipelines/coreclr/templates/helix-queues-setup.yml | Adds Helix queue mapping for the android_arm platform. |
| eng/native/configureplatform.cmake | Sets ARM_SOFTFP for Android ARM32 native builds. |
Teach the shared AOT command-line target handling to accept Android, normalize it to Linux inside Crossgen2 and NativeAOT, and select the armel ABI for Android ARM. Pass the real Android target OS through Crossgen2 and NativeAOT call sites instead of duplicating Android-to-Linux remaps in MSBuild. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run runtime-extra-platforms |
|
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
This PR re-enables CoreCLR android-arm support and aligns the build / codegen pipeline on Android ARM’s softfp (armel) ABI so native/CoreCLR builds, Crossgen2 (R2R), and NativeAOT agree on argument/return-value calling conventions.
Changes:
- Reintroduces Android as a first-class
--targetosvalue for Crossgen2 and ILCompiler, while normalizing the effective OS behavior to Linux and selecting armel/softfp ABI forandroid + arm. - Updates MSBuild integration so Crossgen2/ILCompiler are invoked with the real Android target identity (instead of remapping Android→Linux in MSBuild).
- Re-enables Android ARM legs in CI and adds Helix queue selection for
android_arm, plus setsARM_SOFTFPfor Android ARM native builds.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/tests/Common/CLRTest.CrossGen.targets | Formatting-only change (blank line). |
| src/tasks/Crossgen2Tasks/ResolveReadyToRunCompilers.cs | Allows resolving android as a Crossgen2 TargetOS from RIDs. |
| src/mono/msbuild/android/build/AndroidBuild.InTree.targets | Passes through TargetOS (Android) to Crossgen2 tool invocation. |
| src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.CoreCLR.sfxproj | Removes Android→Linux remap and forwards TargetOS to Crossgen2. |
| src/coreclr/tools/Common/TypeSystem/Common/TargetDetails.cs | Adds TargetOS.Android to the shared type system model. |
| src/coreclr/tools/Common/CommandLineHelpers.cs | Parses android, adds Android→Linux normalization, and selects armel ABI for android+arm. |
| src/coreclr/tools/aot/ILCompiler/Program.cs | Computes target ABI before normalizing Android→Linux effective OS. |
| src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs | Extends help text to include android target OS. |
| src/coreclr/tools/aot/crossgen2/Program.cs | Same normalization/ABI selection pattern as ILCompiler. |
| src/coreclr/tools/aot/crossgen2/Crossgen2RootCommand.cs | Extends help text to include android target OS. |
| src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets | Passes --targetos:android through to ILCompiler (no MSBuild remap). |
| src/coreclr/crossgen-corelib.proj | Always forwards --targetos:$(TargetOS) to Crossgen2 (includes android). |
| src/coreclr/clrdefinitions.cmake | Defines ARM_SOFTFP for Android ARM builds (aligning with softfp ABI need). |
| eng/testing/tests.readytorun.targets | Removes Android→Linux remap for Crossgen2 test-time tool metadata. |
| eng/Subsets.props | Re-enables CoreCLR support gating for Android ARM (keeps x86 excluded). |
| eng/pipelines/runtime.yml | Adds android_arm CoreCLR platform to CI matrix. |
| eng/pipelines/extra-platforms/runtime-extra-platforms-android.yml | Adds android_arm to extra-platform Android CoreCLR legs. |
| eng/pipelines/coreclr/templates/helix-queues-setup.yml | Adds Helix queue selection for android_arm. |
| eng/native/configureplatform.cmake | Sets ARM_SOFTFP when targeting Android ARM in native builds. |
Keep accepting android as an AOT command-line target OS, but normalize it to Linux instead of adding Android to the internal TargetOS enum. Preserve Android ARM softfp ABI handling by carrying the original Android command-line token alongside the existing armel parser normalization. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
|
/azp run runtime-extra-platforms |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
If Android is armel, does it mean the bionic RIDs should also be armel? We ship It still feels like we should just normalize both to not just Linux but also to armel instead of adding (If the bug was that we named the RID android-arm instead of android-armel and bionic-arm instead of bionic-armel, then fixing the bug should be as close to when we're done with the RID as possible) |
|
So for Bionic, we already do the softfp normalization here: The question is really whether we think the original bug was that we named there RIDs arm instead of the the established armel, in which case we should normalize as close as possible to where the bug is, instead of propagating the bug into the compilers. |
I do not think that's a bug. We have number of cases where you need both OS and Architecture to figure out the ABI. RIDs are a different beast than GNU triplets. To me, the question is what's the least painful way to go from the OS + arch in the RID to ABI details. I think it is best to keep most of it in the compiler. It is fine to keep it in the compiler frontend, it does not need to be spread through the compiler like the PR does in the current state. BTW: TargetOS looks too fine grained today. I think it would be fine to have a single Apple TargetOS instead of the different Apple TargetOS we have currently. Similarly, different Unix forks could be a single TargetOS. If we were to do that, I think we would still want to do the normalization in the compiler front-end. (Outside of scope of this PR.) |
| @@ -161,6 +161,7 @@ internal class Crossgen2RootCommand : RootCommand | |||
| public ParseResult Result { get; private set; } | |||
|
|
|||
| public static bool IsArmel { get; private set; } | |||
There was a problem hiding this comment.
These statics are not pretty. Can we delay the parsing of the OS and Architecture to later, similar to how instructionset is handled?
| <IlcArg Condition="'$(_targetOS)' == 'android'" Include="--targetos:linux" /> | ||
| <IlcArg Condition="'$(_targetOS)' != '' and '$(_targetOS)' != 'android'" Include="--targetos:$(_targetOS)" /> | ||
| <IlcArg Condition="'$(_targetOS)' != ''" Include="--targetos:$(_targetOS)" /> | ||
| <IlcArg Condition="$(_targetArchitectureWithAbi) != ''" Include="--targetarch:$(_targetArchitectureWithAbi)" /> |
There was a problem hiding this comment.
I think it would be fine to push the normalization of linux- into the compiler as well. If we were to do that, we can drop armel as recognized --arch for the compiler (we would figure out armel from linux-bionic).
Nice to have, does not need to be done in this PR.
We already have to deal with ABI details in the .targets that cannot be moved to the compiler, including the EABI detail so I don't see much point in doing the last small detail of "android arm actually means linux armel" in the compiler. If we really want to deal with this in .target and in the compiler just so the compiler can generate a byte identical output to linux-armel, I guess it's fine. It's totally unnecessary, but fine. I would be more opposed if we wanted actual TargetOS enum and spread it through the entire compiler. |
I agree with you if ilc was the only concern. The motivation is doing it the same way for both crossgen and ilc. We want to avoid crossgen2 and ilc command lines and overall setup diverging. If this normalization was done outside crossgen/ilc, it would need to be replicated in number of places (8?) or we would have to invent another layer of msbuild that the compiler invocations go through to share the normalization. |
|
Tagging subscribers to this area: @dotnet/runtime-infrastructure |
Note
This PR description was updated with GitHub Copilot.
Fixes #127500.
Description
This re-enables the
android-armCoreCLR runtime pack and CI coverage, and fixes the Android ARM softfp ABI handling needed for native code, ReadyToRun/Crossgen2-generated code, and NativeAOT target handling.Android
armmaps to thearmeabi-v7aABI. That ABI can use VFP instructions internally, but floating-point arguments and return values cross function-call boundaries through core registers/stack rather than VFP argument registers. In .NET target terminology, the matching AOT/JIT ABI isarmel.The original enablement exposed runtime crashes caused by parts of the build and code-generation pipeline disagreeing on that ABI. Native/CoreCLR builds needed
ARM_SOFTFP, and AOT compiler target handling needed to treat Android ARM as Linux/Bionic with the softfp ABI.Changes
Re-enable
android-armas a supported CoreCLR runtime pack target.Re-enable Android ARM CoreCLR legs in the runtime and extra-platform CI pipelines.
Add Android ARM Helix queue selection.
Set
ARM_SOFTFPfor Android ARM native/CoreCLR builds.Treat Android ARM compile definitions as softfp when setting CoreCLR target definitions.
Keep Android as an accepted AOT command-line target OS without extending the internal
TargetOSenum.Centralize Android command-line normalization in both Crossgen2 and NativeAOT ILCompiler:
Update Crossgen2 call sites to pass the real Android target identity instead of duplicating Android-to-Linux remaps in MSBuild.
Update NativeAOT build integration to pass
--targetos:androidthrough to ILCompiler while preserving the existing bionic ARMarmeltarget-architecture handling.Validation
Built Android ARM locally:
Result:
Validated on a physical Android device with
armeabi-v7asupport.The following Android ARM test runs completed with zero failures with both
TestReadyToRun=trueandTestReadyToRun=false:System.Runtime.TestsSystem.Runtime.Numerics.TestsSystem.Numerics.Vectors.TestsSystem.Numerics.Tensors.TestsMicrosoft.Bcl.Numerics.TestsAdditional validation for the centralized AOT target handling:
Also smoke-tested that both Crossgen2 and ILCompiler accept Android target arguments, including
--targetos:android --targetarch:armand--targetos:android --targetarch:arm64, and that the existing--targetos:linux --targetarch:armelnormalization still works.