112 lines
4.7 KiB
Markdown
112 lines
4.7 KiB
Markdown
<!-- file: docs/development/006-ANDROID_RUST_NATIVE_BUILD.md -->
|
|
<!-- version: 5 -->
|
|
|
|
# Build Rust Android natif
|
|
|
|
## Contrat SDL
|
|
|
|
`SDLActivity` charge `SDL3`, puis `game_android_entrypoint`, et invoque le symbole `SDL_main`.
|
|
|
|
Le crate Rust `game-android-entrypoint` est un `cdylib`. Il est compilé avec exactement une feature métier lors du packaging d'une application :
|
|
|
|
- `reflex` ;
|
|
- `snake`.
|
|
|
|
Le même nom de bibliothèque native peut être utilisé dans les deux APK puisque chaque module Android possède son propre ensemble de `jniLibs` générés.
|
|
|
|
## SDL3 AAR et Prefab
|
|
|
|
L'AAR officiel SDL3 expose ses bibliothèques natives avec Prefab. Pour chaque ABI, la logique Gradle commune cherche d'abord :
|
|
|
|
```text
|
|
prefab/modules/SDL3/libs/android.<abi>/libSDL3.so
|
|
```
|
|
|
|
Elle accepte aussi `jni/<abi>/libSDL3.so`, puis un fallback Prefab univoque. Pour chaque ABI elle :
|
|
|
|
1. extrait `libSDL3.so` depuis l'AAR dans un répertoire temporaire de linkage ;
|
|
2. stage `libSDL3.so` dans les `jniLibs` générés du variant ;
|
|
3. lance `cargo ndk` avec exactement une feature jeu ;
|
|
4. stage `libgame_android_entrypoint.so` dans le même arbre généré ;
|
|
5. vérifie la présence des deux bibliothèques avant de rendre l'output au variant AGP.
|
|
|
|
Les `jniLibs` générés sont déclarés à la Variant API via `variant.sources.jniLibs.addGeneratedSourceDirectory`. Gradle possède ainsi la dépendance entre le packaging Android et le build natif au lieu d'exiger une commande préalable séparée.
|
|
|
|
## Toolchain
|
|
|
|
Le contrat projet utilise :
|
|
|
|
```text
|
|
AGP 9.4.0
|
|
Gradle minimum 9.6.0
|
|
JDK runtime >= 17, fourni par l'environnement
|
|
Java source/target 17
|
|
compileSdk 36
|
|
minSdk 21
|
|
NDK 28.2.13676358 / r28c
|
|
SDL3 AAR 3.4.16
|
|
cargo-ndk requis côté développeur
|
|
```
|
|
|
|
`Android/settings.gradle` compare `GradleVersion.current()` au minimum projet `9.6.0`. Le projet n'épingle donc pas une distribution Gradle : un Gradle local plus récent est accepté tant qu'il satisfait le minimum.
|
|
|
|
Le projet Android natif n'impose pas `JAVA_HOME`. Le JDK courant du shell/IDE exécute Gradle ; `java -version` et `gradle --version` sont relevés pendant les gates. Le niveau de bytecode/source Java de la glue reste explicitement `17`, indépendamment du JDK de build.
|
|
|
|
`cargo-ndk` détecte le NDK désigné pour le sous-processus via `ANDROID_NDK_HOME`. La tâche Gradle résout cette valeur à partir de `ANDROID_HOME` ou `ANDROID_SDK_ROOT` et de `androidNdkVersion`; aucun `ANDROID_NDK_HOME` global n'est requis.
|
|
|
|
## État 0.3.3-0-pre.4
|
|
|
|
La preuve mono-ABI de `0-pre.2` a validé que `assembleDebug` déclenche correctement le build Rust/SDL3 ARM64 sans orchestrateur Python préalable.
|
|
|
|
`0-pre.3` a validé le graphe sur les deux ABI 64 bits. `0-pre.4` élargit le même mécanisme à la matrice Android complète encore supportée :
|
|
|
|
```text
|
|
arm64-v8a
|
|
armeabi-v7a
|
|
x86_64
|
|
x86
|
|
```
|
|
|
|
pour Snake et Reflex :
|
|
|
|
```text
|
|
:<game>:assembleDebug
|
|
-> buildDebugSasedevRustArm64V8a
|
|
-> buildDebugSasedevRustArmeabiV7a
|
|
-> buildDebugSasedevRustX8664
|
|
-> buildDebugSasedevRustX86
|
|
-> quatre sources jniLibs générées
|
|
-> APK Debug universal
|
|
```
|
|
|
|
Chaque arbre ABI contient :
|
|
|
|
```text
|
|
build/generated/sasedevNative/debug/<abi>/jniLibs/<abi>/
|
|
├── libSDL3.so
|
|
└── libgame_android_entrypoint.so
|
|
```
|
|
|
|
Depuis la racine :
|
|
|
|
```bash
|
|
java -version
|
|
(cd Android && gradle --version)
|
|
(cd Android && gradle :game-snake-poc:assembleDebug)
|
|
(cd Android && gradle :game-reflex-poc:assembleDebug)
|
|
```
|
|
|
|
Il ne faut pas appeler `scripts/build_android_rust.py` avant ces tâches. Le script Python historique reste temporairement versionné jusqu'à la fermeture complète du chemin natif en `0-pre.5`, après preuve du chemin release/AAB.
|
|
|
|
Les outputs natifs restent sous `Android/<module>/build/` et ne sont jamais versionnés.
|
|
|
|
## Smoke appareil
|
|
|
|
L'APK universal doit être inspecté mécaniquement avant installation. Il doit contenir les deux bibliothèques natives pour chacune des quatre ABI : `arm64-v8a`, `armeabi-v7a`, `x86_64` et `x86`.
|
|
|
|
Le smoke réel reste effectué sur les architectures matériellement disponibles : AVD x86_64 et appareil ARM64. Les ABI 32 bits sont néanmoins exigées au build et dans l'APK ; leur exécution réelle dépend de la disponibilité d'un appareil/AVD 32 bits. Ces smokes ne changent pas le `minSdk`, qui reste un axe séparé et sera consolidé avec l'AAB/compatibilité dans `0-pre.5`.
|
|
|
|
## Exception FFI Rust
|
|
|
|
Rust 2024 exige un attribut unsafe pour imposer un nom de symbole d'export. Le projet autorise donc exclusivement `#[unsafe(export_name = "SDL_main")]` dans `game-android-entrypoint`. Cette exception ne permet ni bloc `unsafe`, ni fonction `unsafe`, ni déréférencement des pointeurs `argc/argv`.
|