Skip to content

[NativeAOT] Enable workload-provided linker for NDK-free builds#11303

Open
sbomer wants to merge 8 commits intomainfrom
dev/sbomer/nativelink-workload
Open

[NativeAOT] Enable workload-provided linker for NDK-free builds#11303
sbomer wants to merge 8 commits intomainfrom
dev/sbomer/nativelink-workload

Conversation

@sbomer
Copy link
Copy Markdown
Member

@sbomer sbomer commented May 7, 2026

[NativeAOT] Enable workload-provided linker for NDK-free builds

Adds an opt-in _AndroidUseWorkloadNativeLinker property that allows NativeAOT builds to use the linker and sysroot files from the workload runtime pack instead of requiring the Android NDK. This is the foundation for removing the NDK dependency from NativeAOT builds (issue #10697).

What changed

Workload linker opt-in (Microsoft.Android.Sdk.NativeAOT.targets)

  • When _AndroidUseWorkloadNativeLinker=true, the NativeAOT link step resolves CRT objects, system lib stubs, and toolchain libraries from the runtime pack instead of the NDK.
  • When false (default), behavior is unchanged — NDK paths are used as before.

NativeAOT-specific redist directory (Step_Android_SDK_NDK.cs)

  • Copies a second set of CRT objects and system lib stubs from NDK API level 24 into redist-nativeaot/ during make prepare.
  • NativeAOT needs API 24+ stubs because dotnet/runtime's libSystem.Native.a references symbols introduced at that level (__gnu_strerror_r, __write_chk, preadv, pwritev, stderr).
  • Mono/CoreCLR continue using the API 21 stubs from redist/.

Runtime pack contents (Microsoft.Android.Runtime.proj)

  • NativeAOT pack now includes CRT objects (crtbegin_so.o, crtend_so.o) and system lib stubs from redist-nativeaot/ (API 24).
  • Added toolchain libraries (libc++_static.a, libc++abi.a, libclang_rt.builtins, libunwind.a) that were previously only in the CoreCLR pack.

Tests (NativeAotBuildTests.cs)

  • BuildNativeAot_WithoutNdk_Fails: Verifies that NativeAOT builds fail without NDK when the workload linker is not enabled.
  • BuildNativeAot_WithWorkloadLinker_WithoutNdk: Verifies that NativeAOT builds succeed with the workload linker and no NDK installed.

Context

This is the third step in the NDK-free NativeAOT linking series:

  1. [NativeAOT] Take over native linker invocation from ILC targets #11148 — Take over native linker invocation from ILC (NativeLib=static)
  2. [NativeAOT] Use NativeLinker and invoke lld directly for linking #11256 — Replace clang with direct lld invocation via LinkNativeAotSharedLibrary task
  3. This PR — Source all linker dependencies from the workload pack

The _AndroidUseWorkloadNativeLinker property is underscore-prefixed (internal) for now. A future PR will make it the default.

Contributes to #10697.

sbomer and others added 6 commits May 7, 2026 10:03
Add NativeAotBuildTests as the dedicated test class for NativeAOT-specific
build tests. First test verifies that NativeAOT builds fail when the NDK
is not available, by clearing AndroidNdkDirectory via build parameters.

This test will be flipped to assert success when the workload pack ships
its own linker and sysroot files, removing the NDK dependency.

Context: #10697

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add crtbegin_so.o and crtend_so.o to the NativeAOT runtime pack. These
were only included for CoreCLR. They are needed for NDK-free linking
where the workload pack provides all linker dependencies.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
NativeAOT links dotnet/runtime's libSystem.Native.a which was compiled
against API 24 and references symbols like __gnu_strerror_r (API 23+)
and __write_chk (API 24+). The existing redist/ directory has API 21
stubs which lack these symbols.

Add a separate redist-nativeaot/ directory with CRT objects and system
lib stubs from the API 24 sysroot. The NativeAOT runtime pack sources
from this directory instead of the shared redist/ (which stays at API 21
for Mono/CoreCLR compatibility).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add libc++_static.a, libc++abi.a, libclang_rt.builtins, and libunwind.a
to the NativeAOT pack. These were only in the CoreCLR pack but NativeAOT
needs them for the workload linker path (no NDK).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 7, 2026 18:40
Copy link
Copy Markdown
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

Adds an internal opt-in path for NativeAOT builds to link using workload/runtime-pack-provided native artifacts (CRT, sysroot stubs, toolchain libs) so NativeAOT can build without a locally installed Android NDK, and updates pack/prep and tests to support this.

Changes:

  • Introduces _AndroidUseWorkloadNativeLinker in Microsoft.Android.Sdk.NativeAOT.targets to source linker inputs from the runtime pack and to disable debug-section compression when using the workload linker.
  • Extends make prepare/pack creation to include NativeAOT-specific API-24 CRT + system stub libs (redist-nativeaot/) and additional toolchain libraries in the NativeAOT runtime pack.
  • Adds NativeAOT build tests to validate behavior with and without NDK depending on the opt-in flag, plus a builder switch to skip injecting AndroidNdkDirectory in test response files.
Show a summary per file
File Description
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs Adds a test-only switch to skip emitting AndroidNdkDirectory into the generated response file.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/NativeAotBuildTests.cs Adds coverage for NativeAOT builds with no NDK (expected fail by default; expected success with workload linker opt-in).
src/Xamarin.Android.Build.Tasks/Tasks/LinkNativeAotSharedLibrary.cs Plumbs a new task property to control --compress-debug-sections based on linker capabilities.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets Implements the opt-in workload-linker path and runtime-pack-based resolution for CRT/stubs/toolchain libs.
build-tools/xaprepare/xaprepare/Steps/Step_Android_SDK_NDK.cs Copies API-24 CRT + system stubs into a new redist-nativeaot/ directory for NativeAOT runtime pack consumption.
build-tools/create-packs/Microsoft.Android.Runtime.proj Includes redist-nativeaot/ assets and additional toolchain libraries in the NativeAOT runtime pack.

Copilot's findings

  • Files reviewed: 7/7 changed files
  • Comments generated: 2

sbomer and others added 2 commits May 7, 2026 11:52
Neither ILC nor the CoreCLR/Mono link paths pass --compress-debug-sections.
This was added without justification and created unnecessary complexity
for the workload linker path (whose LLD lacks zlib support).

Tracked in #11304 for future enablement across all runtimes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add XML doc comment for SkipNdkDirectory property
- Clarify test comment: default path still requires NDK

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

2 participants