Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions android/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ The odrcore build is a normal one — `ODR_JNI=ON`, static core linked into
`libodr_jni.so` — driven by the `android-<arch>` conan profiles in
`.github/config/conan/profiles`, which pin the NDK and API 26.

The libraries ship unstripped — 60-72 MB per ABI, most of the AAR — so that a
consuming app's `ndk.debugSymbolLevel` can hand play what it needs to symbolicate
a crash inside the core. Devices never see it: play serves APKs built from the
stripped copies, so the weight is on maven central and developer builds only.

It takes both `build_native.py` not stripping and the
`packaging.jniLibs.keepDebugSymbols` rule in `build.gradle.kts`. Without the
second the first is invisible.

## Testing

```bash
Expand Down
9 changes: 9 additions & 0 deletions android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,15 @@ android {
targetCompatibility = JavaVersion.VERSION_17
}

packaging {
jniLibs {
// AGP strips the libraries on their way into the AAR unless told not
// to, silently — the published AAR comes out byte-identical to a
// fully stripped one however `build_native.py` built it.
keepDebugSymbols += "**/*.so"
}
}

// pushing the instrumented apk onto a cold emulator outlasts ddmlib's
// default timeout, which surfaces as a ShellCommandUnresponsiveException
// rather than as a failing test
Expand Down
15 changes: 7 additions & 8 deletions android/build_native.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

`libc++_shared.so` has to be shipped because the android profiles build against
the shared c++ runtime and nothing else in a consuming app pulls it in.

Neither is stripped: the NDK's unconditional `-g` is what a consumer's
`ndk.debugSymbolLevel` turns into symbolicated play crash reports. Costs 60-72 MB
per ABI, and needs the `keepDebugSymbols` rule in `build.gradle.kts` to survive.
"""

import argparse
Expand Down Expand Up @@ -65,13 +69,8 @@ def libcxx_shared(ndk: Path, triple: str) -> Path:
return matches[0]


def strip(ndk: Path, library: Path) -> None:
"""The NDK compiles with `-g` in every configuration, so a release build of
the bindings is ~70 MB until it is stripped."""
matches = sorted(ndk.glob("toolchains/llvm/prebuilt/*/bin/llvm-strip"))
if not matches:
raise SystemExit(f"no llvm-strip under {ndk}")
run([matches[0], "--strip-unneeded", library])
def report(library: Path) -> None:
print(f" {library.name}: {library.stat().st_size // 1024} KiB", flush=True)


def build(architecture: str, conan: str, build_profile: str, output: Path) -> None:
Expand Down Expand Up @@ -106,7 +105,7 @@ def build(architecture: str, conan: str, build_profile: str, output: Path) -> No
for source in (cmake_dir / "jni" / "libodr_jni.so", libcxx_shared(ndk, triple)):
target = jni_libs / source.name
shutil.copy2(source, target)
strip(ndk, target)
report(target)


def main() -> int:
Expand Down
Loading