diff --git a/.gitea/workflows/build-and-test.yml b/.gitea/workflows/build-and-test.yml index 50d9f8d..bf129dc 100644 --- a/.gitea/workflows/build-and-test.yml +++ b/.gitea/workflows/build-and-test.yml @@ -138,7 +138,7 @@ jobs: # Cheap invariants that a compiler cannot see. Both failures are silent: # the app builds, installs, launches, and then finds no trainer. - - name: Check the Android source layout and the JNI symbol + - name: Check the Android source layout and the JNI symbols run: | set -e # gen/ is generated and must stay untracked, or a `tauri android init` @@ -152,20 +152,35 @@ jobs: KT=src-tauri/android/src/main/java/paris/tourolle/bikecontrol/MainActivity.kt [ -f "$KT" ] || { echo "❌ $KT is missing"; exit 1; } - # The JNI symbol in android.rs is matched by the *runtime*, by name. - # Rename the Kotlin package or the method and nothing fails to - # compile — btleplug simply never gets initialised. - SYM=$(sed -n 's/.*pub extern "system" fn \(Java_[A-Za-z0-9_]*\).*/\1/p' src-tauri/src/android.rs) + # JNI symbols are matched by the *runtime*, by name. Rename the + # Kotlin package, add a native without its Rust half, or drop a Rust + # export, and nothing fails to compile — the method simply is not + # there when Java calls it. So compare the two sets, both ways. + # + # Sets, not a single pair: there are three natives now, and matching + # `external fun name()` on empty parens missed the two that take + # arguments. Parameters do not appear in the symbol name, so stop at + # the opening paren. + TMP="${RUNNER_TEMP:-/tmp}" PKG=$(sed -n 's/^package \(.*\)$/\1/p' "$KT" | tr -d '\r') - METHOD=$(sed -n 's/.*external fun \([A-Za-z0-9_]*\)().*/\1/p' "$KT") - EXPECTED="Java_$(echo "$PKG" | tr '.' '_')_MainActivity_$METHOD" - if [ "$SYM" != "$EXPECTED" ]; then - echo "❌ JNI symbol mismatch:" - echo " android.rs exports: $SYM" - echo " MainActivity needs: $EXPECTED" + PREFIX="Java_$(echo "$PKG" | tr '.' '_')_MainActivity_" + + sed -n 's/.*pub extern "system" fn \(Java_[A-Za-z0-9_]*\).*/\1/p' \ + src-tauri/src/android.rs | sort -u > "$TMP/jni-rust" + sed -n "s/.*external fun \([A-Za-z0-9_]*\)(.*/$PREFIX\1/p" \ + "$KT" | sort -u > "$TMP/jni-kotlin" + + [ -s "$TMP/jni-rust" ] || { echo "❌ No JNI exports found in android.rs"; exit 1; } + + if ! diff -u "$TMP/jni-kotlin" "$TMP/jni-rust" > "$TMP/jni-diff"; then + echo "❌ JNI symbols differ between MainActivity.kt and android.rs:" + echo " - declared in MainActivity.kt, not exported by android.rs" + echo " + exported by android.rs, not declared in MainActivity.kt" + tail -n +4 "$TMP/jni-diff" exit 1 fi - echo "✅ JNI symbol $SYM matches $PKG.MainActivity.$METHOD" + echo "✅ $(wc -l < "$TMP/jni-rust") JNI symbols match $PKG.MainActivity:" + sed 's/^/ /' "$TMP/jni-rust" - name: Cargo check (aarch64-linux-android) run: |