Skip to content

joltc-sys: native Android cross-compile + host-vs-target /EHsc fix#12

Merged
LPGhatguy merged 2 commits into
SecondHalfGames:mainfrom
Solidor777:android-cross-compile-and-target-os-fix
May 11, 2026
Merged

joltc-sys: native Android cross-compile + host-vs-target /EHsc fix#12
LPGhatguy merged 2 commits into
SecondHalfGames:mainfrom
Solidor777:android-cross-compile-and-target-os-fix

Conversation

@Solidor777

Copy link
Copy Markdown
Contributor

Summary

Two coupled bugs surfaced while cross-compiling joltc-sys to Android (aarch64-linux-android via NDK r26d clang from a Windows host).

1. cfg!(windows) is a HOST-OS check, not a target-OS check

build.rs runs on the host. When the host is Windows and the target is Android, the existing if cfg!(windows) { config.cxxflag("/EHsc"); } unconditionally appends the MSVC-only /EHsc flag. NDK clang then receives /EHsc as a path argument and errors with no such file or directory: '/EHsc'.

Fix: read CARGO_CFG_TARGET_OS and gate /EHsc on the actual target.

2. Native Android cross-compile setup is missing

Building for Android via the standard cargo ndk --target <android-triple> check -p joltc-sys flow currently fails because joltc-sys does not set:

  • CMAKE_TOOLCHAIN_FILE (NDK's build/cmake/android.toolchain.cmake).
  • ANDROID_ABI (the toolchain reads it as a CMake -D variable; env var is ignored).
  • The CMake generator (cmake-rs defaults to MSBuild on Windows hosts; the NDK toolchain only supports Ninja / Makefiles).

Fix: when target_os == "android", derive ANDROID_ABI from CARGO_CFG_TARGET_ARCH (aarch64arm64-v8a, armarmeabi-v7a, x86 / x86_64 1:1), resolve the NDK from ANDROID_NDK_HOME / ANDROID_NDK_ROOT / ANDROID_NDK, force Ninja, and pin ANDROID_PLATFORM=android-21.

End-user contract after this change

export ANDROID_NDK_HOME=/path/to/ndk      # or ANDROID_NDK_ROOT / ANDROID_NDK
cargo ndk --target aarch64-linux-android check -p joltc-sys

The standard cargo-ndk + nttld/setup-ndk@v1 GitHub Action workflow Just Works.

Validation

  • Locally validated on Windows host → aarch64-linux-android with NDK r26d. Full JoltPhysics + JoltC + joltc-sys + rolt cross-compile completes in ~20s. Downstream Rust crate (Titan engine's titan-jolt-3d) builds against the cross-compiled libs.
  • armv7-linux-androideabi is not addressed by this PR — it hits an unrelated JoltC LAYOUT_COMPATIBLE static_assert (JPC_*Settings 16-byte alignment vs JPH::*Settings 8-byte alignment on 32-bit ARM). That looks like a JoltC-side ABI bug for 32-bit targets; happy to track separately.
  • Desktop targets (Win/Linux/macOS) are unaffected — Android branch is gated on target_os == "android", and the /EHsc change only narrows the existing condition (Windows targets still get it).

Test plan

  • cargo check -p joltc-sys on Windows host (default target, x86_64-pc-windows-msvc) — /EHsc still applied; existing behavior unchanged.
  • cargo ndk --target aarch64-linux-android check -p joltc-sys on Windows host — succeeds with only ANDROID_NDK_HOME set.
  • cargo ndk --target aarch64-linux-android check -p joltc-sys on Linux + macOS hosts — reviewer to validate; should be the simpler case (no /EHsc hot path).
  • cargo check -p joltc-sys on Linux/macOS — unaffected; existing CI covers.

Opened from the same Titan-engine fork that submitted SecondHalfGames/JoltC#23 (the JPC_PhysicsSystem_SetGravity export). Both PRs are independent — happy to address review feedback on either.

Two coupled bugs surfaced when cross-compiling joltc-sys to
Android (aarch64-linux-android via NDK r26d clang from a Windows
host):

1. `cfg!(windows)` is a HOST-OS check inside build.rs. When
   targeting Android from Windows, the conditional always fires
   and adds the MSVC-only `/EHsc` flag to the cmake config — NDK
   clang then receives `/EHsc` as a path argument and errors out
   ("error: no such file or directory: '/EHsc'").

   Fix: read `CARGO_CFG_TARGET_OS` and only add `/EHsc` when the
   actual target is windows.

2. Building for Android requires three CMake-side hints that
   joltc-sys does not currently set: `CMAKE_TOOLCHAIN_FILE`
   (NDK's `android.toolchain.cmake`), `ANDROID_ABI` (string the
   toolchain reads — env var alone is ignored), and the
   generator (Ninja, since cmake-rs defaults to MSBuild on
   Windows hosts).

   Fix: when `target_os == "android"`, derive ANDROID_ABI from
   `CARGO_CFG_TARGET_ARCH` (aarch64 → arm64-v8a, arm →
   armeabi-v7a, etc.), look up the NDK at
   `ANDROID_NDK_HOME` / `ANDROID_NDK_ROOT` / `ANDROID_NDK`,
   and force Ninja.

End-user contract after this change: set ANDROID_NDK_HOME,
run `cargo ndk --target aarch64-linux-android check -p joltc-sys`.
The standard cargo-ndk + nttld/setup-ndk@v1 flow Just Works.

Validated locally on Windows-host → aarch64-linux-android with
NDK r26d (full JoltPhysics + JoltC compiles in ~20s). 32-bit ARM
(armv7-linux-androideabi) hits an unrelated upstream JoltC
LAYOUT_COMPATIBLE static_assert (`JPC_*Settings` 16-byte
alignment vs `JPH::*Settings` 8-byte alignment on 32-bit ARM)
that this PR does not address.
Solidor777 added a commit to Solidor777/Titan that referenced this pull request May 8, 2026
Upstream PR for the joltc-sys/build.rs Android cross-compile +
host-vs-target /EHsc fix now has a URL:
SecondHalfGames/jolt-rust#12. Cross-referenced
from docs/VENDORING.md "Local patches" and docs/TODO.md so future syncs
find the trigger.

Pairs with SecondHalfGames/JoltC#23 (the SetGravity export PR opened
earlier today). Both are independent; either can merge first.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@Solidor777

Copy link
Copy Markdown
Contributor Author

Status update: the armv7 / 32-bit-ARM follow-up I mentioned (LAYOUT_COMPATIBLE static_assert on JPC_*Settings 16 vs JPH 8) turned out to be a clean upstream fix on the JoltC side. Filed as SecondHalfGames/JoltC#24: mirrors JPH's per-arch JPH_VECTOR_ALIGNMENT macro logic on the C-side typedefs (JPC_VECTOR_ALIGNMENT / JPC_DVECTOR_ALIGNMENT).

With both PRs applied, cargo ndk --target armv7-linux-androideabi check -p joltc-sys now succeeds end-to-end alongside aarch64-linux-android. Downstream verification: Titan engine's titan-jolt-3d plugin compiles + runs across both Android ABIs in CI (matrix entry was just promoted to include_jolt: true).

No code change needed on this PR — just a heads-up that the "track separately" item has a fix.

@LPGhatguy LPGhatguy merged commit b3e94cd into SecondHalfGames:main May 11, 2026
Solidor777 added a commit to Solidor777/Titan that referenced this pull request May 17, 2026
Upstream PR for the joltc-sys/build.rs Android cross-compile +
host-vs-target /EHsc fix now has a URL:
SecondHalfGames/jolt-rust#12. Cross-referenced
from docs/VENDORING.md "Local patches" and docs/TODO.md so future syncs
find the trigger.

Pairs with SecondHalfGames/JoltC#23 (the SetGravity export PR opened
earlier today). Both are independent; either can merge first.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Solidor777 added a commit to Solidor777/Titan that referenced this pull request Jun 4, 2026
Upstream PR for the joltc-sys/build.rs Android cross-compile +
host-vs-target /EHsc fix now has a URL:
SecondHalfGames/jolt-rust#12. Cross-referenced
from docs/VENDORING.md "Local patches" and docs/TODO.md so future syncs
find the trigger.

Pairs with SecondHalfGames/JoltC#23 (the SetGravity export PR opened
earlier today). Both are independent; either can merge first.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.

2 participants