Skip to content

Use android-native-tools for NativeAOT linking instead of Android NDK#10704

Draft
sbomer wants to merge 6 commits intomainfrom
dev/sbomer/workload-aot
Draft

Use android-native-tools for NativeAOT linking instead of Android NDK#10704
sbomer wants to merge 6 commits intomainfrom
dev/sbomer/workload-aot

Conversation

@sbomer
Copy link
Member

@sbomer sbomer commented Jan 21, 2026

This eliminates the NDK dependency for NativeAOT builds by using our custom LLVM build (android-native-tools) that ships with the Android workload.

Changes:

  • Add LinkNativeAotLibrary task that invokes ld.lld from android-native-tools
  • Set NativeCompilationDuringPublish=false and NativeLib=Static so ILC produces only object files, then we link them ourselves
  • Add -z nostart-stop-gc linker flag for __start/__stop symbols
  • Include sysroot libraries (libc++_static.a, libunwind.a, etc.) in NativeAOT runtime pack
  • Fix duplicate assembly error by removing items before re-adding them to ResolvedFileToPublish
  • Keep legacy NDK path behind AndroidNativeAotUseNdk=true flag

This eliminates the NDK dependency for NativeAOT builds by using our
custom LLVM build (android-native-tools) that ships with the Android
workload.

Changes:
- Add LinkNativeAotLibrary task that invokes ld.lld from android-native-tools
- Set NativeCompilationDuringPublish=false and NativeLib=Static so ILC
  produces only object files, then we link them ourselves
- Add -z nostart-stop-gc linker flag for __start/__stop symbols
- Include sysroot libraries (libc++_static.a, libunwind.a, etc.) in
  NativeAOT runtime pack
- Fix duplicate assembly error by removing items before re-adding them
  to ResolvedFileToPublish
- Keep legacy NDK path behind AndroidNativeAotUseNdk=true flag
NativeAOT's DWARF-based stack unwinder (LLVM libunwind) requires the
.eh_frame_hdr section to locate Frame Description Entries during GC
stack walking. Without this section, the runtime crashes with SIGSEGV
when attempting to read unwind information from invalid memory.
Quote the soname argument to handle project names containing spaces.
Without this fix, a project named 'Test Me' would cause the linker to
fail with 'cannot open Me: No such file or directory' because the
unquoted soname would be split into separate arguments.
The sysroot libraries (libc.so, libdl.so, liblog.so, libm.so, libz.so)
are needed by ld.lld for symbol resolution during linking, but should
not be packaged in the APK - the real implementations are provided by
the Android system at runtime.

For Mono/CoreCLR, these are removed in _ResolveAssemblies via
ProcessRuntimePackLibraryDirectories, but NativeAOT was excluded from
that logic. Remove the exclusion so all runtimes use the same removal
logic in the outer build.

The inner build still runs ProcessRuntimePackLibraryDirectories to get
_RuntimePackLibraryDirectory for linking, but doesn't need to handle
the removal - that's done by the outer build after it receives the
ResolvedFileToPublish items.
The _CopyToPackDirs target was only copying *.a files for NativeAOT,
but crtbegin_so.o and crtend_so.o are required for linking.

Add *.o glob pattern to NativeAOT section, matching CoreCLR behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant