[native] Stop linking libc++ into the CoreCLR and NativeAOT runtimes - #12572
Open
simonrozsival wants to merge 2 commits into
Open
Conversation
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
marked this pull request as ready for review
August 28, 2026 14:00
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
changed the base branch from
dev/simonrozsival/fix-jstring-array-wrapper
to
dev/simonrozsival/clr-assembly-store-strings
August 28, 2026 14:05
Contributor
There was a problem hiding this comment.
Copilot review overview
Review tier: Lite
Findings: 1
New issues introduced by this change (1)
| Severity | Finding |
|---|---|
src/native/CMakePresets.json.in — 💡 Maintainability — coreclr-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
libunwindbuild to MonoVM-only and rename the native archive set fromCplusPlusRuntimetoCompilerRuntime(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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

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-commonCMake preset setsANDROID_STL=none. All sixcoreclr-default-{debug,release}-{armeabi-v7a,arm64-v8a,x86_64}presets now inherit from it instead of the shareddefault-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-isystemflags 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-commonswitches toANDROID_STL=noneas well.Stop building libunwind for CoreCLR.
add_subdirectory(common/libunwind)ran forIS_MONO_RUNTIME OR IS_CLR_RUNTIME, but onlymono/tracingever linksxa::unwind. The CoreCLR host built the whole thing and never used it.Stop shipping the archives.
libc++_static.a,libc++abi.aandlibunwind.aare no longer copied into the CoreCLR runtime pack, and are removed from the archive list thatLinkNativeRuntimeconsumes.KnownSets.CplusPlusRuntimenow only holds the clang built-ins archive, so it is renamed toKnownSets.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 singlestd::stringadded later silently pulls the archive back in and the win evaporates.With
-nostdlib++, that regression becomes a link error instead.A note on
LinkNativeRuntimeLinkNativeRuntime(the "link the app's native runtime statically" feature, gated on_AndroidEnableNativeRuntimeLinking) also linkslibcoreclr_static.a,libbrotli*.aand 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-arm64Release, clean CMake configures atANDROID_STL=none:CoreCLR
libunwinddoes not appear in the build graph.libnet-android.release.sois unchanged at 203,776 bytes.libc++/libc++abi/_Unwind_*symbols.DT_NEEDEDunchanged;JNI_OnLoadand theJava_mono_android_Runtime_*entry points still exported.NativeAOT
libnaot-android.release.so,libnaot-android.release-static-release.aandlibxa-java-interop-release.a-- are byte-for-byte identical (matching SHA-1) to thec++_staticbuild.MonoVM still builds, and still builds libunwind 1.8.1.