Skip to content

[native] Stop linking libc++ into the CoreCLR and NativeAOT runtimes - #12572

Open
simonrozsival wants to merge 2 commits into
dev/simonrozsival/clr-assembly-store-stringsfrom
dev/simonrozsival/clr-stop-linking-libcpp
Open

[native] Stop linking libc++ into the CoreCLR and NativeAOT runtimes#12572
simonrozsival wants to merge 2 commits into
dev/simonrozsival/clr-assembly-store-stringsfrom
dev/simonrozsival/clr-stop-linking-libcpp

Conversation

@simonrozsival

@simonrozsival simonrozsival commented Aug 28, 2026

Copy link
Copy Markdown
Member

Now that the CoreCLR host has zero references to the C++ standard library (#12571), we can stop linking it in entirely. This is the payoff PR for the CoreCLR half of #12533.

Changes

Stop linking libc++. A new hidden coreclr-default-common CMake preset sets ANDROID_STL=none. All six coreclr-default-{debug,release}-{armeabi-v7a,arm64-v8a,x86_64} presets now inherit from it instead of the shared default-common (which MonoVM still uses).

This drops -static-libstdc++ from the link line and replaces it with -nostdlib++. The libc++ headers remain available: every CMake target already lists ${SYSROOT_CXX_INCLUDE_DIR} in its include directories, so CMake now emits those -isystem flags explicitly instead of relying on the toolchain's implicit search path.

NativeAOT gets the same treatment. NativeAOT reached zero libc++ references back in #12523, so nativeaot-default-common switches to ANDROID_STL=none as well.

Stop building libunwind for CoreCLR. add_subdirectory(common/libunwind) ran for IS_MONO_RUNTIME OR IS_CLR_RUNTIME, but only mono/tracing ever links xa::unwind. The CoreCLR host built the whole thing and never used it.

Stop shipping the archives. libc++_static.a, libc++abi.a and libunwind.a are no longer copied into the CoreCLR runtime pack, and are removed from the archive list that LinkNativeRuntime consumes. KnownSets.CplusPlusRuntime now only holds the clang built-ins archive, so it is renamed to KnownSets.CompilerRuntime ("compiler-rt").

MonoVM is untouched and keeps ANDROID_STL=c++_static.

Why this matters beyond the size win

The 316 KB the CoreCLR host lost in #12571 came from reaching zero references, at which point the linker stops pulling members out of libc++_static.a. That state is fragile: a single std::string added later silently pulls the archive back in and the win evaporates.

With -nostdlib++, that regression becomes a link error instead.

A note on LinkNativeRuntime

LinkNativeRuntime (the "link the app's native runtime statically" feature, gated on _AndroidEnableNativeRuntimeLinking) also links libcoreclr_static.a, libbrotli*.a and the BCL PAL archives from dotnet/runtime. Those are C++ and very likely still need libc++.

That property is not set anywhere in the repo today, so the feature is dormant. Removing the archives now keeps the two code paths honest about what our own runtime needs; if the feature is ever turned on, libc++ can be reintroduced there specifically rather than being linked into everything by default.

Verification

android-arm64 Release, clean CMake configures at ANDROID_STL=none:

CoreCLR

  • The host compiles and links cleanly.
  • libunwind does not appear in the build graph.
  • libnet-android.release.so is unchanged at 203,776 bytes.
  • Zero undefined libc++ / libc++abi / _Unwind_* symbols.
  • DT_NEEDED unchanged; JNI_OnLoad and the Java_mono_android_Runtime_* entry points still exported.

NativeAOT

  • All three artifacts -- libnaot-android.release.so, libnaot-android.release-static-release.a and libxa-java-interop-release.a -- are byte-for-byte identical (matching SHA-1) to the c++_static build.

MonoVM still builds, and still builds libunwind 1.8.1.

Now that the CoreCLR host has zero references to the C++ standard
library, we can stop linking it in entirely.

* Add a `coreclr-default-common` CMake preset that sets
  `ANDROID_STL=none` (mirroring `nativeaot-default-common`, but
  without the STL).  This drops `-static-libstdc++` from the link
  line and replaces it with `-nostdlib++`.  Every CMake target
  already adds `${SYSROOT_CXX_INCLUDE_DIR}` explicitly, so the
  libc++ *headers* remain available.

* Stop building `common/libunwind` for CoreCLR.  Only `mono/tracing`
  links `xa::unwind`; the CoreCLR host built it and never used it.

* Stop shipping `libc++_static.a`, `libc++abi.a` and `libunwind.a`
  in the CoreCLR runtime pack, and drop them from the archive list
  used by `LinkNativeRuntime`.  `KnownSets.CplusPlusRuntime` now only
  holds the clang built-ins archive, so it is renamed to
  `KnownSets.CompilerRuntime`.

Verified on `android-arm64` Release: the host builds and links
cleanly with `ANDROID_STL=none`, `libnet-android.release.so` is
unchanged at 203,776 bytes, has zero undefined libc++/libunwind
symbols, and its `DT_NEEDED` list is unchanged.  MonoVM and NativeAOT
are unaffected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0a35a0db-502d-48c0-8468-e73b5dd0ab2e
@simonrozsival simonrozsival added the drop-libcpp Work to remove the libc++ dependency from Android NativeAOT label Aug 28, 2026
@simonrozsival
simonrozsival marked this pull request as ready for review August 28, 2026 14:00
Copilot AI lite review requested due to automatic review settings August 28, 2026 14:00
@simonrozsival
simonrozsival changed the base branch from dev/simonrozsival/clr-assembly-store-strings to dev/simonrozsival/fix-jstring-array-wrapper August 28, 2026 14:01
@simonrozsival simonrozsival reopened this Aug 28, 2026
@simonrozsival
simonrozsival changed the base branch from dev/simonrozsival/fix-jstring-array-wrapper to dev/simonrozsival/clr-assembly-store-strings August 28, 2026 14:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Lite
Findings: 1 Low severity

New issues introduced by this change (1)
Severity Finding
Low severity src/​native/​CMakePresets.json.in — 💡 Maintainabilitycoreclr-default-common duplicates ANDROID_CPP_FEATURES from…
What changed in this PR

Removes the C++ standard library (libc++/libc++abi) and libunwind from the CoreCLR native host build and runtime packs now that the host no longer references the C++ standard library, while keeping compiler built-ins available for linking.

Changes:

  • Stop shipping/linking libc++/libc++abi/libunwind for CoreCLR by pruning NDK redistributables and runtime pack asset lists.
  • Introduce a CoreCLR-specific CMake preset baseline (ANDROID_STL=none) and adjust CoreCLR presets to inherit from it.
  • Narrow libunwind build to MonoVM-only and rename the native archive set from CplusPlusRuntime to CompilerRuntime (clang builtins).
File Description
src/​Xamarin.Android.Build.Tasks/​Utilities/​NativeRuntimeComponents.cs Renames the “c++” archive set to “compiler-rt” and removes libc++/libc++abi/libunwind archives from the known archive list.
src/​Xamarin.Android.Build.Tasks/​Tasks/​LinkNativeRuntime.cs Updates the set used for the “compiler support” archive group when ordering link inputs.
src/​native/​native.targets Stops copying NDK “CplusPlus” redistributable archives into CoreCLR runtime packs.
src/​native/​CMakePresets.json.in Adds coreclr-default-common preset with ANDROID_STL=none and updates CoreCLR presets to inherit from it.
src/​native/​CMakeLists.txt Builds common/libunwind only for MonoVM (where it is actually linked).
build-tools/​scripts/​Ndk.targets Removes libc++/libc++abi/libunwind from the NDK redistributable item list.
build-tools/​scripts/​Ndk.projitems Removes now-unused UnwindArchDir metadata.
build-tools/​create-packs/​Microsoft.Android.Runtime.proj Stops including NDK “CplusPlus” redistributables in the CoreCLR runtime pack assets.

Comment on lines +70 to +74
"inherits": "common",
"cacheVariables": {
"ANDROID_STL": "none",
"ANDROID_CPP_FEATURES": "no-rtti no-exceptions"
}
NativeAOT already had zero references to the C++ standard library
after #12523, so switching `nativeaot-default-common` to
`ANDROID_STL=none` costs nothing and turns any future libc++ use into
a link error instead of silently pulling the archive back in.

Verified on `android-arm64` Release with a clean configure: all three
NativeAOT artifacts -- `libnaot-android.release.so`,
`libnaot-android.release-static-release.a` and
`libxa-java-interop-release.a` -- are byte-for-byte identical to the
`c++_static` build.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0a35a0db-502d-48c0-8468-e73b5dd0ab2e
@simonrozsival simonrozsival changed the title [native] Stop linking libc++ into the CoreCLR host [native] Stop linking libc++ into the CoreCLR and NativeAOT runtimes Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

drop-libcpp Work to remove the libc++ dependency from Android NativeAOT

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants