Skip to content

[Android NDK] Make API level configurable#124461

Open
grendello wants to merge 2 commits intomainfrom
dev/grendel/android-naot-dont-hardcode-api-level
Open

[Android NDK] Make API level configurable#124461
grendello wants to merge 2 commits intomainfrom
dev/grendel/android-naot-dont-hardcode-api-level

Conversation

@grendello
Copy link
Contributor

Context: dotnet/android#9926
Context: dotnet/android@bef768d

.NET for Android recently switched CoreCLR and NativeAOT NDK API levels from 21 to 24, which uncovered an issue in the NativeAOT Microsoft.NETCore.Native.Unix.targets SetupOSSpecificProps target, where the target hardcodes the Android API level to 21.

This causes the following link error when trying to build an Android NativeAOT application:

ld.lld : error : undefined symbol: __gnu_strerror_r
ld.lld : error : undefined symbol: stderr

The reason for this is that API 24 libc.so contains these two symbols, while the one from API 21 does not. Since .NET for Android runtime is built with API 24, and NativeAOT build forces the API 21 level by passing the --target=${ARCH}-linux-android21 argument to the linker, we get the above error.

This PR makes the API level configurable and default to 24. The default value is merely the
current API level .NET for Android targets, it doesn't need to be updated in the future - the .NET for Android targets will take care of setting the property to the appropriate value, should the default change.

Copilot AI review requested due to automatic review settings February 16, 2026 11:23
@github-actions github-actions bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Feb 16, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Makes the Android NDK API level used by NativeAOT’s Unix build integration configurable, addressing link failures caused by hardcoding API level 21 when the runtime is built against a higher NDK level.

Changes:

  • Introduce CrossCompileAndroidApiLevel MSBuild property with a default of 24.
  • Replace hardcoded android21 / androideabi21 target triple components with android$(CrossCompileAndroidApiLevel) / androideabi$(CrossCompileAndroidApiLevel).

@MichalStrehovsky
Copy link
Member

If we're bumping this to 24, there's more places to update:

<!--
Minimum target OS versions, keep in sync with:
- eng/native/configurecompiler.cmake
- eng/native/build-commons.sh
- eng/native/gen-buildsys.cmd
- src/native/libs/build-native.sh
- src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/MachObjectWriter.cs
- src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets
- src/mono/mono/tools/offsets-tool/offsets-tool.py
- src/mono/msbuild/apple/build/AppleBuild.targets
- src/installer/pkg/sfx/bundle/shared-framework-distribution-template-x64.xml
- src/installer/pkg/sfx/bundle/shared-framework-distribution-template-arm64.xml
- src/mono/msbuild/common/MonoAOTCompiler.props
- src/tasks/AppleAppBuilder/Xcode.cs
- src/tasks/MobileBuildTasks/Apple/AppleProject.cs
- src/tasks/Crossgen2Tasks/Microsoft.NET.CrossGen.targets
- https://github.com/dotnet/sdk repo > src/Installer/redist-installer/targets/GeneratePKG.targets
-->
<AndroidApiLevelMin>21</AndroidApiLevelMin>

Should the dotnet/android repo rev this in sync with dotnet/runtime? Looks like that's what happens on the Apple side from what I see.

Cc @sbomer

@MichalStrehovsky MichalStrehovsky added area-NativeAOT-coreclr and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Feb 16, 2026
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib
See info in area-owners.md if you want to be subscribed.

@grendello
Copy link
Contributor Author

@MichalStrehovsky I'll modify the PR to set it back to 21, there's no need to make the bump right now across the entire runtime, it was just a "by the way" change.

With regards to syncing, we should in general keep the levels compatible between what dotnet/runtime uses and what's used by .NET for Android, but this is not to say they have to be set to the same value. API 21 and 24 aren't compatible on the binary level, so this is a situation where we need to be in agreement and use 24 on the NativeAOT linking side (CoreCLR host in .NET for Android will be fine, even though we build against 24 and libcoreclr.so is built against 21). I wouldn't make using the same API level on both sides a matter of policy, I'd recommend we keep the two compatible, even if they would differ. Tests we have on the Android side will be able to tell us if there are incompatibilities.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants