From 0b091444f25cc56fd7a7a34c482e888c953df5a3 Mon Sep 17 00:00:00 2001 From: "Sindri P. Ingimundarson" Date: Wed, 25 Feb 2026 23:53:53 +0100 Subject: [PATCH 1/7] Test --- .github/workflows/ci.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c8c3b9c..160780d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,3 +75,33 @@ jobs: - uses: Swatinem/rust-cache@v2 - run: rustup target add aarch64-apple-ios aarch64-apple-ios-sim - run: cargo xtask generate-bindings + + build-ios: + needs: bindings + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - uses: Swatinem/rust-cache@v2 + - uses: actions/setup-node@v4 + with: + node-version-file: .node-version + cache: npm + - run: npm ci + - run: rustup target add aarch64-apple-ios aarch64-apple-ios-sim + - run: cargo xtask generate-bindings + - name: Prebuild + working-directory: packages/app-mobile/example + run: npx expo prebuild --clean + - name: Build iOS simulator app + working-directory: packages/app-mobile/example + run: xcodebuild -workspace ios/appmobileexample.xcworkspace -scheme appmobileexample -configuration Release -sdk iphonesimulator -derivedDataPath build + - name: Package .app + working-directory: packages/app-mobile/example + run: | + mkdir -p artifact + cp -r build/Build/Products/Release-iphonesimulator/appmobileexample.app artifact/ + cd artifact && zip -r appmobileexample.zip appmobileexample.app + - uses: actions/upload-artifact@v4 + with: + name: appmobileexample-ios-simulator + path: packages/app-mobile/example/artifact/appmobileexample.zip From 310ef7bdb3761a963f8b765c814f18a63a6e0c6f Mon Sep 17 00:00:00 2001 From: "Sindri P. Ingimundarson" Date: Thu, 26 Feb 2026 00:09:36 +0100 Subject: [PATCH 2/7] arm --- .github/workflows/ci.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 160780d..17b21b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,7 +69,7 @@ jobs: - run: npm --workspaces run format bindings: - runs-on: macos-latest + runs-on: macos-26 steps: - uses: actions/checkout@v4 - uses: Swatinem/rust-cache@v2 @@ -77,8 +77,7 @@ jobs: - run: cargo xtask generate-bindings build-ios: - needs: bindings - runs-on: macos-latest + runs-on: macos-26 steps: - uses: actions/checkout@v4 - uses: Swatinem/rust-cache@v2 @@ -94,12 +93,12 @@ jobs: run: npx expo prebuild --clean - name: Build iOS simulator app working-directory: packages/app-mobile/example - run: xcodebuild -workspace ios/appmobileexample.xcworkspace -scheme appmobileexample -configuration Release -sdk iphonesimulator -derivedDataPath build + run: xcodebuild -workspace ios/appmobileexample.xcworkspace -scheme appmobileexample -configuration Debug -sdk iphonesimulator -arch arm64 -derivedDataPath build - name: Package .app working-directory: packages/app-mobile/example run: | mkdir -p artifact - cp -r build/Build/Products/Release-iphonesimulator/appmobileexample.app artifact/ + cp -r build/Build/Products/Debug-iphonesimulator/appmobileexample.app artifact/ cd artifact && zip -r appmobileexample.zip appmobileexample.app - uses: actions/upload-artifact@v4 with: From 48cee9358cfec2feb479afb01d6bcef7ac0bca4f Mon Sep 17 00:00:00 2001 From: "Sindri P. Ingimundarson" Date: Sat, 28 Feb 2026 22:44:20 +0100 Subject: [PATCH 3/7] Cache test --- .github/workflows/ci.yml | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 17b21b6..4d900ce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,17 +88,46 @@ jobs: - run: npm ci - run: rustup target add aarch64-apple-ios aarch64-apple-ios-sim - run: cargo xtask generate-bindings + - name: Cache CocoaPods + uses: actions/cache@v4 + with: + path: | + ~/Library/Caches/CocoaPods + ~/.cocoapods + key: pods-${{ runner.os }}-${{ github.ref_name }} + restore-keys: | + pods-${{ runner.os }}-main + pods-${{ runner.os }}- + - name: Cache iOS build + uses: actions/cache@v4 + with: + path: packages/app-mobile/example/ios + key: ios-${{ runner.os }}-${{ github.ref_name }}-${{ github.sha }} + restore-keys: | + ios-${{ runner.os }}-${{ github.ref_name }}- + ios-${{ runner.os }}-main- + ios-${{ runner.os }}- - name: Prebuild working-directory: packages/app-mobile/example - run: npx expo prebuild --clean + run: npx expo prebuild -p ios - name: Build iOS simulator app working-directory: packages/app-mobile/example - run: xcodebuild -workspace ios/appmobileexample.xcworkspace -scheme appmobileexample -configuration Debug -sdk iphonesimulator -arch arm64 -derivedDataPath build + run: | + xcodebuild \ + -workspace ios/appmobileexample.xcworkspace \ + -scheme appmobileexample \ + -configuration Release \ + -sdk iphonesimulator \ + -arch arm64 \ + -derivedDataPath ios/build \ + -parallelizeTargets \ + -quiet \ + CODE_SIGNING_ALLOWED=NO - name: Package .app working-directory: packages/app-mobile/example run: | mkdir -p artifact - cp -r build/Build/Products/Debug-iphonesimulator/appmobileexample.app artifact/ + cp -r ios/build/Build/Products/Release-iphonesimulator/appmobileexample.app artifact/ cd artifact && zip -r appmobileexample.zip appmobileexample.app - uses: actions/upload-artifact@v4 with: From a2649a72bf2373a1f07e4abab733f16938ab0bb9 Mon Sep 17 00:00:00 2001 From: "Sindri P. Ingimundarson" Date: Sat, 28 Feb 2026 23:18:57 +0100 Subject: [PATCH 4/7] Split tasks --- .github/workflows/ci.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4d900ce..97f03ee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,19 +75,25 @@ jobs: - uses: Swatinem/rust-cache@v2 - run: rustup target add aarch64-apple-ios aarch64-apple-ios-sim - run: cargo xtask generate-bindings + - uses: actions/upload-artifact@v4 + with: + name: ios-bindings + path: packages/app-mobile/ios/uniffi/ build-ios: runs-on: macos-26 + needs: bindings steps: - uses: actions/checkout@v4 - - uses: Swatinem/rust-cache@v2 + - uses: actions/download-artifact@v4 + with: + name: ios-bindings + path: packages/app-mobile/ios/uniffi/ - uses: actions/setup-node@v4 with: node-version-file: .node-version cache: npm - run: npm ci - - run: rustup target add aarch64-apple-ios aarch64-apple-ios-sim - - run: cargo xtask generate-bindings - name: Cache CocoaPods uses: actions/cache@v4 with: From b712fc1cc67a1589c6be6b32194cddf53b8d9cf8 Mon Sep 17 00:00:00 2001 From: "Sindri P. Ingimundarson" Date: Sun, 1 Mar 2026 17:39:47 +0100 Subject: [PATCH 5/7] Split up bindings and artifact generation --- .cargo/config.toml | 1 + .github/workflows/ci.yml | 14 +- .gitignore | 1 + Cargo.lock | 7 + Cargo.toml | 1 + crates/app-mobile/Cargo.toml | 2 +- packages/app-mobile/ios/AppMobile.podspec | 7 +- packages/app-mobile/ios/AppMobileModule.swift | 10 +- tools/uniffi-bindgen-swift/Cargo.toml | 11 ++ tools/uniffi-bindgen-swift/src/main.rs | 3 + xtask/src/main.rs | 146 +++++++++--------- 11 files changed, 116 insertions(+), 87 deletions(-) create mode 100644 tools/uniffi-bindgen-swift/Cargo.toml create mode 100644 tools/uniffi-bindgen-swift/src/main.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index 979d277..11d205d 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,3 +1,4 @@ [alias] xtask = "run -p xtask --bin xtask --" uniffi-bindgen = "run -p uniffi-bindgen --" +uniffi-bindgen-swift = "run -p uniffi-bindgen-swift --" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 97f03ee..6a5f490 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,11 +69,10 @@ jobs: - run: npm --workspaces run format bindings: - runs-on: macos-26 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: Swatinem/rust-cache@v2 - - run: rustup target add aarch64-apple-ios aarch64-apple-ios-sim - run: cargo xtask generate-bindings - uses: actions/upload-artifact@v4 with: @@ -85,10 +84,13 @@ jobs: needs: bindings steps: - uses: actions/checkout@v4 + - uses: Swatinem/rust-cache@v2 + - run: rustup target add aarch64-apple-ios aarch64-apple-ios-sim - uses: actions/download-artifact@v4 with: name: ios-bindings path: packages/app-mobile/ios/uniffi/ + - run: cargo xtask build-ios - uses: actions/setup-node@v4 with: node-version-file: .node-version @@ -104,15 +106,13 @@ jobs: restore-keys: | pods-${{ runner.os }}-main pods-${{ runner.os }}- - - name: Cache iOS build + - name: Cache iOS prebuild uses: actions/cache@v4 with: path: packages/app-mobile/example/ios - key: ios-${{ runner.os }}-${{ github.ref_name }}-${{ github.sha }} + key: prebuild-ios-${{ runner.os }}-${{ hashFiles('packages/app-mobile/ios/AppMobile.podspec', 'packages/app-mobile/example/app.json', 'packages/app-mobile/example/package.json') }}-${{ github.sha }} restore-keys: | - ios-${{ runner.os }}-${{ github.ref_name }}- - ios-${{ runner.os }}-main- - ios-${{ runner.os }}- + prebuild-ios-${{ runner.os }}-${{ hashFiles('packages/app-mobile/ios/AppMobile.podspec', 'packages/app-mobile/example/app.json', 'packages/app-mobile/example/package.json') }}- - name: Prebuild working-directory: packages/app-mobile/example run: npx expo prebuild -p ios diff --git a/.gitignore b/.gitignore index cc59166..71cab8f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ target/ ### Generated bindings ### packages/app-mobile/ios/uniffi/ +packages/app-mobile/ios/AppMobile.xcframework/ packages/app-mobile/android/src/main/java/uniffi/ .vscode \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 7acca24..862fab7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1526,6 +1526,13 @@ dependencies = [ "uniffi", ] +[[package]] +name = "uniffi-bindgen-swift" +version = "0.1.0" +dependencies = [ + "uniffi", +] + [[package]] name = "uniffi_bindgen" version = "0.31.0" diff --git a/Cargo.toml b/Cargo.toml index d099391..1be5908 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "crates/app-mobile", "crates/app-web", "tools/uniffi-bindgen", + "tools/uniffi-bindgen-swift", "xtask", ] default-members = [ diff --git a/crates/app-mobile/Cargo.toml b/crates/app-mobile/Cargo.toml index 46534ac..e25192f 100644 --- a/crates/app-mobile/Cargo.toml +++ b/crates/app-mobile/Cargo.toml @@ -5,7 +5,7 @@ edition.workspace = true rust-version.workspace = true [lib] -crate-type = ["cdylib", "staticlib", "lib"] +crate-type = ["cdylib", "staticlib"] [dependencies] app-core.workspace = true diff --git a/packages/app-mobile/ios/AppMobile.podspec b/packages/app-mobile/ios/AppMobile.podspec index 2dfeae3..995d664 100644 --- a/packages/app-mobile/ios/AppMobile.podspec +++ b/packages/app-mobile/ios/AppMobile.podspec @@ -25,6 +25,9 @@ Pod::Spec.new do |s| 'DEFINES_MODULE' => 'YES', } - s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}" - s.vendored_frameworks = "uniffi/AppMobile.xcframework" + s.source_files = [ + "*.swift", + "uniffi/**/*.{swift,h}" + ] + s.vendored_frameworks = "AppMobile.xcframework" end diff --git a/packages/app-mobile/ios/AppMobileModule.swift b/packages/app-mobile/ios/AppMobileModule.swift index c91106d..12d0876 100644 --- a/packages/app-mobile/ios/AppMobileModule.swift +++ b/packages/app-mobile/ios/AppMobileModule.swift @@ -33,17 +33,21 @@ public class AppMobileModule: Module { Function("stopBackgroundTask") { stopBackgroundTask() } + + OnDestroy { + stopBackgroundTask() + } } } -class AppMobileBackgroundCallback: BackgroundTaskCallback { - private weak var module: AppMobileModule? +final class AppMobileBackgroundCallback: BackgroundTaskCallback { + nonisolated(unsafe) private let module: AppMobileModule init(module: AppMobileModule) { self.module = module } func onTick(count: UInt64) { - module?.sendEvent("onTick", ["count": Int(count)]) + module.sendEvent("onTick", ["count": Int(count)]) } } diff --git a/tools/uniffi-bindgen-swift/Cargo.toml b/tools/uniffi-bindgen-swift/Cargo.toml new file mode 100644 index 0000000..5da2115 --- /dev/null +++ b/tools/uniffi-bindgen-swift/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "uniffi-bindgen-swift" +version.workspace = true +edition.workspace = true +rust-version.workspace = true + +[dependencies] +uniffi = { workspace = true, features = ["cli"] } + +[lints] +workspace = true diff --git a/tools/uniffi-bindgen-swift/src/main.rs b/tools/uniffi-bindgen-swift/src/main.rs new file mode 100644 index 0000000..b1b0d73 --- /dev/null +++ b/tools/uniffi-bindgen-swift/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + uniffi::uniffi_bindgen_swift(); +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index ae1d5e2..d624fec 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,8 +1,18 @@ +use std::path::{Path, PathBuf}; use std::process::Command; +use std::sync::LazyLock; use anyhow::{Context, Result, bail}; use clap::{Parser, Subcommand}; +static ROOT: LazyLock = LazyLock::new(|| { + #[allow(clippy::expect_used)] + Path::new(env!("CARGO_MANIFEST_DIR")) + .parent() + .expect("xtask must be in a subdirectory of the workspace root") + .to_path_buf() +}); + const PKG: &str = "packages/app-mobile"; const LIB: &str = "libapp_mobile"; @@ -15,8 +25,10 @@ struct Cli { #[derive(Subcommand)] enum Commands { - /// Generate Swift and Kotlin bindings for app-mobile + /// Generate Swift and Kotlin bindings from the host library (works on Linux) GenerateBindings, + /// Build iOS libraries and create xcframework (requires macOS) + BuildIos, } fn main() -> Result<()> { @@ -24,95 +36,81 @@ fn main() -> Result<()> { match cli.command { Commands::GenerateBindings => generate_bindings(), + Commands::BuildIos => build_ios(), } } fn generate_bindings() -> Result<()> { - let ios_device = format!("target/aarch64-apple-ios/debug/{LIB}.a"); - let ios_sim = format!("target/aarch64-apple-ios-sim/debug/{LIB}.a"); - - // Build for host (dylib for Kotlin binding generation) - run("cargo", &["build", "-p", "app-mobile"])?; - - // Build for iOS device - run( - "cargo", - &["build", "-p", "app-mobile", "--target", "aarch64-apple-ios"], - )?; - - // Build for iOS simulator - run( - "cargo", - &[ - "build", - "-p", - "app-mobile", - "--target", - "aarch64-apple-ios-sim", - ], - )?; + let host_lib = ROOT.join(format!("target/debug/{LIB}")); - // Generate Kotlin bindings from host dylib - let kotlin_out = format!("{PKG}/android/src/main/java"); - run( - "cargo", - &[ - "uniffi-bindgen", - "generate", - "--library", - &format!("target/debug/{LIB}.dylib"), - "--language", - "kotlin", - "--out-dir", - &kotlin_out, - "--no-format", - ], - )?; - - // Clean old artifacts - let swift_out = format!("{PKG}/ios/uniffi"); + // Build for host (staticlib for Swift, dylib for Kotlin) + run(Command::new("cargo") + .arg("build") + .arg("-p") + .arg("app-mobile"))?; + + // Generate Swift bindings from host staticlib + let swift_out = ROOT.join(format!("{PKG}/ios/uniffi")); let _ = std::fs::remove_dir_all(&swift_out); + run(Command::new("cargo") + .arg("uniffi-bindgen-swift") + .arg(host_lib.with_extension("a")) + .arg(&swift_out) + .arg("--swift-sources") + .arg("--headers"))?; + + // Generate Kotlin bindings from host dylib + let kotlin_out = ROOT.join(format!("{PKG}/android/src/main/java")); + run(Command::new("cargo") + .arg("uniffi-bindgen") + .arg("generate") + .arg("--library") + .arg(host_lib.with_extension(std::env::consts::DLL_EXTENSION)) + .arg("--language") + .arg("kotlin") + .arg("--out-dir") + .arg(&kotlin_out) + .arg("--no-format"))?; + + Ok(()) +} + +fn build_ios() -> Result<()> { + let ios_device = ROOT.join(format!("target/aarch64-apple-ios/debug/{LIB}.a")); + let ios_sim = ROOT.join(format!("target/aarch64-apple-ios-sim/debug/{LIB}.a")); - // Generate Swift bindings from iOS simulator library - run( - "cargo", - &[ - "uniffi-bindgen", - "generate", - "--library", - &ios_sim, - "--language", - "swift", - "--out-dir", - &swift_out, - ], - )?; + // Build for iOS device and simulator + run(Command::new("cargo") + .arg("build") + .arg("-p") + .arg("app-mobile") + .arg("--target") + .arg("aarch64-apple-ios") + .arg("--target") + .arg("aarch64-apple-ios-sim"))?; // Create xcframework combining device and simulator libraries - run( - "xcodebuild", - &[ - "-create-xcframework", - "-library", - &ios_device, - "-library", - &ios_sim, - "-output", - &format!("{PKG}/ios/uniffi/AppMobile.xcframework"), - ], - )?; + let xcframework = ROOT.join(format!("{PKG}/ios/AppMobile.xcframework")); + let _ = std::fs::remove_dir_all(&xcframework); + run(Command::new("xcodebuild") + .arg("-create-xcframework") + .arg("-library") + .arg(&ios_device) + .arg("-library") + .arg(&ios_sim) + .arg("-output") + .arg(&xcframework))?; Ok(()) } -fn run(cmd: &str, args: &[&str]) -> Result<()> { - let status = Command::new(cmd) - .args(args) +fn run(cmd: &mut Command) -> Result<()> { + let status = cmd .status() - .with_context(|| format!("failed to execute: {cmd} {}", args.join(" ")))?; + .with_context(|| format!("failed to execute: {cmd:?}"))?; if !status.success() { - bail!("{cmd} {} exited with {status}", args.join(" ")); + bail!("{cmd:?} exited with {status}"); } Ok(()) From d843aa4125b271bc4a75d8c0e4d1705afb2345ce Mon Sep 17 00:00:00 2001 From: "Sindri P. Ingimundarson" Date: Sun, 1 Mar 2026 21:10:16 +0100 Subject: [PATCH 6/7] Add android build --- .github/workflows/ci.yml | 46 +++++++++++++++++++ justfile | 4 ++ packages/app-mobile/android/build.gradle | 4 ++ .../expo/modules/appmobile/AppMobileModule.kt | 3 +- xtask/src/main.rs | 19 ++++++++ 5 files changed, 75 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a5f490..4c74662 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,8 +78,13 @@ jobs: with: name: ios-bindings path: packages/app-mobile/ios/uniffi/ + - uses: actions/upload-artifact@v4 + with: + name: android-bindings + path: packages/app-mobile/android/src/main/java/uniffi/ build-ios: + if: false runs-on: macos-26 needs: bindings steps: @@ -139,3 +144,44 @@ jobs: with: name: appmobileexample-ios-simulator path: packages/app-mobile/example/artifact/appmobileexample.zip + + build-android: + runs-on: ubuntu-latest + needs: bindings + steps: + - uses: actions/checkout@v4 + - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@v2 + with: + tool: cargo-ndk + - run: >- + rustup target add + aarch64-linux-android + armv7-linux-androideabi + x86_64-linux-android + i686-linux-android + - uses: actions/download-artifact@v4 + with: + name: android-bindings + path: packages/app-mobile/android/src/main/java/uniffi/ + - run: cargo xtask build-android + - uses: actions/setup-node@v4 + with: + node-version-file: .node-version + cache: npm + - run: npm ci + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + - uses: gradle/actions/setup-gradle@v4 + - name: Prebuild + working-directory: packages/app-mobile/example + run: npx expo prebuild -p android + - name: Build Android APK + working-directory: packages/app-mobile/example/android + run: ./gradlew assembleDebug + - uses: actions/upload-artifact@v4 + with: + name: appmobileexample-android + path: packages/app-mobile/example/android/app/build/outputs/apk/debug/app-debug.apk diff --git a/justfile b/justfile index ab3dc2e..6922da0 100644 --- a/justfile +++ b/justfile @@ -1,5 +1,6 @@ setup: rustup target add aarch64-apple-ios aarch64-apple-ios-sim + rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android i686-linux-android run *args: cargo run -p server {{ args }} @@ -16,3 +17,6 @@ verify-js: generate-bindings: cargo xtask generate-bindings + +build-android: + cargo xtask build-android diff --git a/packages/app-mobile/android/build.gradle b/packages/app-mobile/android/build.gradle index 0bbba14..8b721e2 100644 --- a/packages/app-mobile/android/build.gradle +++ b/packages/app-mobile/android/build.gradle @@ -16,3 +16,7 @@ android { abortOnError false } } + +dependencies { + implementation "net.java.dev.jna:jna:5.18.1@aar" +} diff --git a/packages/app-mobile/android/src/main/java/expo/modules/appmobile/AppMobileModule.kt b/packages/app-mobile/android/src/main/java/expo/modules/appmobile/AppMobileModule.kt index 038314d..f2658f4 100644 --- a/packages/app-mobile/android/src/main/java/expo/modules/appmobile/AppMobileModule.kt +++ b/packages/app-mobile/android/src/main/java/expo/modules/appmobile/AppMobileModule.kt @@ -1,5 +1,6 @@ package expo.modules.appmobile +import expo.modules.kotlin.functions.Coroutine import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition import uniffi.app_mobile.BackgroundTaskCallback @@ -33,7 +34,7 @@ class AppMobileModule : Module() { divide(left.toULong(), right.toULong())?.toLong() } - AsyncFunction("delayedAdd") { left: Long, right: Long, delayMs: Long -> + AsyncFunction("delayedAdd") Coroutine { left: Long, right: Long, delayMs: Long -> delayedAdd(left.toULong(), right.toULong(), delayMs.toULong()).toLong() } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index d624fec..99d7a3a 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -29,6 +29,8 @@ enum Commands { GenerateBindings, /// Build iOS libraries and create xcframework (requires macOS) BuildIos, + /// Build Android shared libraries via cargo-ndk + BuildAndroid, } fn main() -> Result<()> { @@ -37,6 +39,7 @@ fn main() -> Result<()> { match cli.command { Commands::GenerateBindings => generate_bindings(), Commands::BuildIos => build_ios(), + Commands::BuildAndroid => build_android(), } } @@ -104,6 +107,22 @@ fn build_ios() -> Result<()> { Ok(()) } +fn build_android() -> Result<()> { + let jni_libs = ROOT.join(format!("{PKG}/android/src/main/jniLibs")); + let _ = std::fs::remove_dir_all(&jni_libs); + + run(Command::new("cargo") + .arg("ndk") + .args(["--output-dir", &jni_libs.to_string_lossy()]) + .args(["--target", "aarch64-linux-android"]) + .args(["--target", "armv7-linux-androideabi"]) + .args(["--target", "x86_64-linux-android"]) + .args(["--target", "i686-linux-android"]) + .args(["build", "--package", "app-mobile"]))?; + + Ok(()) +} + fn run(cmd: &mut Command) -> Result<()> { let status = cmd .status() From 60426f9d6f86c71da8e5bf799a4fe39947948899 Mon Sep 17 00:00:00 2001 From: "Sindri P. Ingimundarson" Date: Sun, 1 Mar 2026 22:58:59 +0100 Subject: [PATCH 7/7] Gradle cache? --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c74662..63373e5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -175,6 +175,8 @@ jobs: distribution: temurin java-version: 17 - uses: gradle/actions/setup-gradle@v4 + with: + cache-read-only: false - name: Prebuild working-directory: packages/app-mobile/example run: npx expo prebuild -p android