Skip to content

Android: scripts/build-android.sh — single-cmd plug-in build#13

Open
leaiss wants to merge 6 commits into
mainfrom
feat/android-cnsdk-dp-build-script
Open

Android: scripts/build-android.sh — single-cmd plug-in build#13
leaiss wants to merge 6 commits into
mainfrom
feat/android-cnsdk-dp-build-script

Conversation

@leaiss
Copy link
Copy Markdown
Collaborator

@leaiss leaiss commented May 27, 2026

Summary

Stacks on PRs #5 + #6. New `scripts/build-android.sh` wrapping the multi-arg cmake invocation needed to produce `libdxrp050_leia_cnsdk.so` for Android arm64-v8a.

Before this script, a bring-up dev had to type 8 lines of cmake args, with values that drift across machines:

```bash
cmake -S . -B build-android -G Ninja
-DCMAKE_TOOLCHAIN_FILE=$LOCALAPPDATA/Android/Sdk/ndk/26.3.11579264/build/cmake/android.toolchain.cmake
-DCMAKE_MAKE_PROGRAM=$LOCALAPPDATA/Android/Sdk/cmake/3.22.1/bin/ninja.exe
-DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-29
-DCNSDK_ROOT=/c/openxr-3d-display/cnsdk
-DDXR_RUNTIME_SOURCE_DIR=/c/openxr-3d-display
-DEigen3_DIR=/c/openxr-3d-display/src/xrt/targets/openxr_android/build/intermediates/eigen/eigen-3.4.0/cmake
cmake --build build-android --target dxrp050_leia_cnsdk
```

After:

```bash
scripts/build-android.sh
```

Behavior

  • Auto-resolves `ANDROID_SDK_ROOT` / `ANDROID_HOME`, NDK version (default 26.3.11579264), Ninja binary location (under SDK's bundled cmake), CNSDK_ROOT (default `../openxr-3d-display/cnsdk`), `DXR_RUNTIME_SOURCE_DIR` (default `../openxr-3d-display`), `Eigen3_DIR` (default the gradle-fetched dir under the runtime tree).
  • Each can be explicitly overridden via env var.
  • Hard failure with actionable error messages if any dep is missing.
  • One `[target]` arg supports `dxrp050_leia_cnsdk` (default) and `clean` (wipe `build-android/`).
  • Trailing message tells the dev exactly what `cp` command to run to drop the .so into the runtime APK's `jniLibs//`.

Mirrors the existing `scripts/build-windows.bat` shape so a dev who knows one immediately knows the other.

Verification

```
$ scripts/build-android.sh clean
Wiping build-android/

$ scripts/build-android.sh dxrp050_leia_cnsdk
ANDROID_SDK_ROOT: ...
NDK: ...
Ninja: ...
Runtime: ...
CNSDK: ...
Eigen3: ...
=== Configuring ===
[...]
=== Building dxrp050_leia_cnsdk ===
[...]
[147/147] Linking CXX shared library src\drv_leia_android\libdxrp050_leia_cnsdk.so
=== Built: build-android/src/drv_leia_android/libdxrp050_leia_cnsdk.so ===
-rw-r--r-- 1.7M libdxrp050_leia_cnsdk.so
Drop into the runtime APK's jniLibs//:
cp build-android/.../libdxrp050_leia_cnsdk.so ../openxr-3d-display/.../jniLibs/arm64-v8a/
```

Test plan

🤖 Generated with Claude Code

leaiss and others added 3 commits June 2, 2026 08:46
…me PR #268)

Companion to displayxr-runtime PR #268, which splits the Android POC
along the post-#263 plug-in boundary. Runtime side keeps the cross-
cutting infrastructure (is_self_submitting vtable flag, vk_native
Android plumbing, audit fixes); CNSDK + drv-side audit fixes live
here.

Adds `src/drv_leia_android/` as a sibling of the Windows drv_leia/,
sharing the same plug-in entry contract (xrtPluginNegotiate) but
selected at CMake configure time by `if(WIN32)` / `elseif(ANDROID)`.

Source files
  leia_cnsdk.{cpp,h}                       — CNSDK C-ABI wrapper:
                                              core init (worker thread),
                                              interlacer lifecycle,
                                              atlas weave, face-tracking
                                              snapshot. Audit fixes
                                              B2/B4/B5/B10/B11/B12.
  leia_display_processor_cnsdk.{cpp,h}     — xrt_display_processor vtable.
                                              is_self_submitting=true,
                                              atlas-mode only (no per-
                                              tile blit), DXR_HW_DBG +
                                              DXR_ATRACE blocks gated
                                              on XRT_DEBUG_ANDROID_VERBOSE.
                                              Audit B7 / B8 / B14.
  leia_plugin_android.c                    — entry point + iface. Only
                                              create_dp_vk is non-NULL
                                              (no D3D/Metal/GL on Android).
                                              id = "leia-cnsdk",
                                              probe always succeeds (POC
                                              pattern, async device init).

Build wiring
  CMakeLists.txt (top-level)              — relax `if(NOT WIN32) FATAL_ERROR`
                                              into `if(NOT WIN32 AND NOT
                                              ANDROID)`; branch
                                              add_subdirectory between
                                              src/drv_leia (Windows) and
                                              src/drv_leia_android (Android).
                                              Skip the NSIS installer on
                                              Android (APK is the install).
  src/drv_leia_android/CMakeLists.txt     — new. find_package(CNSDK CONFIG
                                              REQUIRED) on CNSDK_ROOT;
                                              builds libdxrp050_leia_cnsdk.so
                                              matching the runtime's plug-in
                                              filename convention; symbol-
                                              hidden except xrtPluginNegotiate.

Docs
  docs/cnsdk-android-calibration.md       — moved from displayxr-runtime
                                              docs/cnsdk-axis-calibration
                                              branch per PR #271 plan, with
                                              file-path refs rewritten to
                                              point at src/drv_leia_android/.

Status: compiles in the standalone repo; not yet wired into the runtime
APK's Gradle (manual jniLibs/ drop per README until the multi-module
gradle setup lands). First hardware install gated on Lume Pad arrival.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ndroid

The Android NDK toolchain (android.toolchain.cmake) defaults
CMAKE_FIND_ROOT_PATH_MODE_PACKAGE to ONLY, which restricts find_package()
to NDK sysroot dirs and silently ignores anything we add to
CMAKE_PREFIX_PATH outside that. Result:

  find_package(CNSDK CONFIG REQUIRED)

found nothing even with CNSDK_ROOT set + appended to CMAKE_PREFIX_PATH,
breaking the standalone NDK build with "Could not find a package
configuration file provided by 'CNSDK'".

Flip the mode to BOTH at the top of src/drv_leia_android/CMakeLists.txt
so the CNSDK install at CNSDK_ROOT becomes searchable. Mirrors what the
runtime APK's gradle does via cmake.arguments
"-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH".

Also widen .gitignore to cover build-*/ so out-of-tree builds like
build-android/ don't end up staged.

Verified end-to-end:
  cmake -B build-android -G Ninja \
    -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
    -DCMAKE_MAKE_PROGRAM=$NDK_CMAKE/bin/ninja.exe \
    -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-29 \
    -DCNSDK_ROOT=$RUNTIME/cnsdk \
    -DDXR_RUNTIME_SOURCE_DIR=$RUNTIME \
    -DEigen3_DIR=$RUNTIME/.../intermediates/eigen/eigen-3.4.0/cmake
  cmake --build build-android --target dxrp050_leia_cnsdk

  Output: libdxrp050_leia_cnsdk.so (1.8 MB, xrtPluginNegotiate exported)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Android CNSDK display-processor factory wired six optional vtable
slots (on_pause, on_resume, is_self_submitting, get_predicted_eye_positions,
get_display_dimensions, get_display_pixel_info) but never set the
struct_size header introduced by ABI v2. The impl is calloc'd, so it
stayed 0 — under the v2 runtime, XRT_DP_HAS_SLOT bounds every optional
slot against struct_size and reads them all as absent. Most damaging:
is_self_submitting=true would be ignored, regressing the self-submitting
atlas path into a per-frame double submit.

Mirrors the drv_leia (Windows) migration in a6c0d7d.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@leaiss leaiss force-pushed the feat/android-cnsdk-dp-build-script branch from adb4fa7 to 6ccb557 Compare June 2, 2026 15:51
leaiss and others added 3 commits June 2, 2026 09:46
… mono NULL-guard

Post-ABI-v2 review pass:
- leia_plugin_android.c: make the probe_displays omission deliberate with an
  explicit `.probe_displays = NULL` + rationale. struct_size spans the full v2
  iface, so the runtime's gate sees the slot, finds NULL, and uses the
  synthesized primary claim — correct for a single-panel Android device with no
  monitor enumeration (Windows arm implements it over EDID; Android has none).
- leia_display_processor_cnsdk.h: fix stale doc that described the obsolete
  per-tile-blit path; current code is atlas mode (SBS VkImage handed straight to
  leia_cnsdk_weave, no per-view blit).
- leia_display_processor_cnsdk.cpp: NULL-guard vk / vk->main_queue in the mono
  1x1 passthrough fallback before dereferencing main_queue->queue, mirroring the
  atlas-weave path's existing guard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Plug-in discovery contract §4 ("single-symbol export discipline"):
plug-ins must expose only xrtPluginNegotiate via the dynamic symbol
table. The existing C_/CXX_VISIBILITY_PRESET=hidden setting only hides
symbols compiled from THIS target's own sources — symbols pulled in
from linked static libs (aux_util, aux_vk, aux_android jni glue, etc.)
keep whatever visibility they had when compiled, which defaults to
"default" everywhere.

Result before this commit:
  $ llvm-nm -D --defined-only --extern-only libdxrp050_leia_cnsdk.so | wc -l
  1233   (one intentional + 1232 leaked from static libs)

After:
  $ llvm-nm -D --defined-only --extern-only libdxrp050_leia_cnsdk.so | wc -l
  1
  $ llvm-nm -D --defined-only --extern-only libdxrp050_leia_cnsdk.so
  0000000000036970 T xrtPluginNegotiate

LINKER:--exclude-libs,ALL applies a "hidden" visibility filter to every
archive linked into the .so, so static-lib symbols stay private even
when compiled with default visibility. The XRT_PLUGIN_EXPORT macro on
xrtPluginNegotiate marks it as explicitly visible so the runtime
loader's dlsym still resolves it.

Gated on (ANDROID OR UNIX) since --exclude-libs,ALL is a GNU ld /
lld flag. Windows uses /EXPORT def-file discipline elsewhere.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wraps the multi-arg cmake invocation needed to produce
libdxrp050_leia_cnsdk.so for Android arm64-v8a. Without this script,
a bring-up dev has to remember:
  - NDK toolchain file path
  - Ninja binary path inside the SDK's bundled cmake (not on PATH)
  - CNSDK_ROOT (extracted release tree, not the source checkout)
  - DXR_RUNTIME_SOURCE_DIR (sibling runtime checkout)
  - Eigen3_DIR (gradle-fetched stub config under the runtime tree)
  - ABI + platform settings

All of these drift across machines. The script auto-resolves each from
sensible defaults relative to the script's location, with explicit env-
var overrides documented at the top. Hard failure with actionable error
messages if any required dep is missing (NDK version not installed,
CNSDK not extracted, runtime checkout not next to the plug-in, etc.).

Mirrors scripts/build-windows.bat's shape — same one-line usage pattern,
same env-var convention. Adds a [target] arg supporting:
  - dxrp050_leia_cnsdk (default) — build the plug-in .so
  - clean                       — wipe build-android/

Verified end-to-end:
  $ scripts/build-android.sh clean
  Wiping build-android/
  $ scripts/build-android.sh dxrp050_leia_cnsdk
  ...
  === Built: build-android/src/drv_leia_android/libdxrp050_leia_cnsdk.so ===
  -rw-r--r-- 1.7M libdxrp050_leia_cnsdk.so
  Drop into the runtime APK's jniLibs/<ABI>/:
    cp build-android/src/drv_leia_android/libdxrp050_leia_cnsdk.so ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@leaiss leaiss force-pushed the feat/android-cnsdk-dp-build-script branch from 6ccb557 to 70e45db Compare June 2, 2026 16:46
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.

1 participant