You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[native] Replace the AndroidSystem path statics with a POD buffer (#12552)
Part of #12533 (drop the `libc++` dependency), stacked on #12551.
`AndroidSystem` kept five of its members in `std::string` / `std::array<std::string, 1>`: `primary_override_dir`, `native_libraries_dir`, `app_code_cache_dir`, `single_app_lib_directory` and `override_dirs`.
Because they are `inline static` with dynamic initialization, the compiler emits a guard variable **and** an `atexit` registration for them in *every* translation unit that includes `android-system.hh` — even in ones that never touch them. `logger.cc`, `internal-pinvokes-clr.cc`, `internal-pinvokes-shared.cc` and `android-system-shared.cc` each paid four libc++ references (`~basic_string`, `operator delete`, `__cxa_guard_acquire`, `__cxa_guard_release`) without using a single one of these directories:
```
$ llvm-nm --undefined-only logger.cc.o | llvm-cxxfilt
std::__ndk1::basic_string<...>::~basic_string()
operator delete(void*)
__cxa_guard_acquire
__cxa_guard_release
$ llvm-objdump -r logger.cc.o | grep _ZGV | llvm-cxxfilt
guard variable for xamarin::android::AndroidSystem::override_dirs
guard variable for xamarin::android::AndroidSystem::app_code_cache_dir
guard variable for xamarin::android::AndroidSystem::native_libraries_dir
guard variable for xamarin::android::AndroidSystem::primary_override_dir
guard variable for xamarin::android::AndroidSystem::single_app_lib_directory
```
## What changed
All five become plain pointers. The three path members are `const char*` initialized to `""` and assigned once, early during startup, with a copy made by a new `Util::duplicate_string()` helper that aborts if the allocation fails. Pointers to a string literal are **constant-initialized**, so neither a guard variable nor an `atexit` registration is emitted.
The two directory arrays become plain `const char*` arrays whose entries are `malloc`ed, which also drops an `operator new[]` from the non-split-APK path.
Since there is no longer a fixed-size buffer anywhere, there is also no hard limit on the path length and no abort when it is exceeded — which is what NativeAOT's `char[SENSIBLE_PATH_MAX]` `primary_override_dir` used to do. That lets `primary_override_dir` be shared by all three hosts, removing three `#if defined (XA_HOST_NATIVEAOT)` blocks and `determine_primary_override_dir()` entirely.
## Results
Undefined libc++ references in the three CoreCLR archives — **58 → 31**:
| object | before | after |
|---|---:|---:|
| `assembly-store.cc.o` | 13 | 11 |
| `host.cc.o` | 11 | 11 |
| `android-system.cc.o` | 11 | 5 |
| `timing-internal.cc.o` | 5 | 2 |
| `logger.cc.o` | 4 | **0** |
| `internal-pinvokes-shared.cc.o` | 4 | **0** |
| `internal-pinvokes-clr.cc.o` | 4 | **0** |
| `android-system-shared.cc.o` | 4 | **0** |
| `typemap.cc.o` | 2 | 2 |
Every `__cxa_guard_*` reference coming from this header is gone; the only ones left are `host.cc`'s own function-local statics.
`libnet-android.release.so`: **539,464 → 536,368 bytes (−3,096)**.
The DEBUG-only code paths were compile-checked separately (there is no Debug ninja directory) and go from 12 to 7 references; `llvm-nm` confirms `add_system_property`, `find_bundled_property` and `setup_environment_from_override_file` are genuinely emitted rather than silently `#if`'d out.
CoreCLR, NativeAOT and MonoVM all build clean.
0 commit comments