From d2e39933985407be79babcaa41ee2555c22c9ba3 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Fri, 27 Feb 2026 20:57:35 -0800 Subject: [PATCH] feat: cross-compile for android (! for termux users) (#264) * feat: cross-compile for android (! for termux users) * chore: Update docs for - feat: cross-compile for android (! for termux users) --- .cargo/config.toml | 11 +++----- .github/workflows/release.yaml | 48 +++++++++++++++++++++++++++++++--- Cargo.lock | 4 +-- Cargo.toml | 2 +- doc/fff.nvim.txt | 2 +- lua/fff/utils/system.lua | 24 ++++++++++------- 6 files changed, 67 insertions(+), 24 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 1d8997d..74e8438 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -10,12 +10,7 @@ rustflags = ["-C", "target-feature=-crt-static"] [target.aarch64-unknown-linux-musl] rustflags = ["-C", "target-feature=-crt-static"] +# Android/Termux: no hardcoded linker so native Termux builds use the system cc. +# For CI cross-compilation the linker is set via CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER env var. [target.aarch64-linux-android] -rustflags = [ - "-C", - "linker=aarch64-linux-android-clang", - "-C", - "link-args=-rdynamic", - "-C", - "default-linker-libraries", -] +rustflags = ["-C", "link-args=-rdynamic"] diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index e69fe77..419124d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -2,7 +2,7 @@ name: Prebuild on: push: - branches: [main, feat/interchangable-ffi] + branches: [main, feat/interchangable-ffi, feat/termux] pull_request: jobs: @@ -36,6 +36,12 @@ jobs: artifact_name: target/aarch64-unknown-linux-musl/release/libfff_nvim.so ext: so + ## Android (Termux) + - os: ubuntu-latest + target: aarch64-linux-android + artifact_name: target/aarch64-linux-android/release/libfff_nvim.so + ext: so + ## macOS builds - os: macos-latest target: x86_64-apple-darwin @@ -73,11 +79,25 @@ jobs: run: cargo install cargo-zigbuild - name: Build for Linux - if: contains(matrix.os, 'ubuntu') + if: contains(matrix.os, 'ubuntu') && !contains(matrix.target, 'android') run: | cargo zigbuild --release --target ${{ matrix.zigbuild_target || matrix.target }} -p fff-nvim mv "${{ matrix.artifact_name }}" "${{ matrix.target }}.${{ matrix.ext }}" + - name: Build for Android (Termux) + if: contains(matrix.target, 'android') + run: | + NDK_BIN="$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin" + + # NDK clang for C deps (libgit2, lmdb, blake3) that need Bionic sysroot headers + export CC_aarch64_linux_android="$NDK_BIN/aarch64-linux-android24-clang" + export CXX_aarch64_linux_android="$NDK_BIN/aarch64-linux-android24-clang++" + export AR_aarch64_linux_android="$NDK_BIN/llvm-ar" + export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="$NDK_BIN/aarch64-linux-android24-clang" + + cargo build --release --target ${{ matrix.target }} -p fff-nvim + mv "${{ matrix.artifact_name }}" "${{ matrix.target }}.${{ matrix.ext }}" + - name: Build for macOS if: contains(matrix.os, 'macos') run: | @@ -137,6 +157,13 @@ jobs: lib_filename: libfff_c.so ext: so + ## Android (Termux) + - os: ubuntu-latest + target: aarch64-linux-android + artifact_name: target/aarch64-linux-android/release/libfff_c.so + lib_filename: libfff_c.so + ext: so + ## macOS builds - os: macos-latest target: x86_64-apple-darwin @@ -183,11 +210,24 @@ jobs: run: cargo install cargo-zigbuild - name: Build for Linux - if: contains(matrix.os, 'ubuntu') + if: contains(matrix.os, 'ubuntu') && !contains(matrix.target, 'android') run: | cargo zigbuild --release --target ${{ matrix.zigbuild_target || matrix.target }} -p fff-c mv "${{ matrix.artifact_name }}" "c-lib-${{ matrix.target }}.${{ matrix.ext }}" + - name: Build for Android (Termux) + if: contains(matrix.target, 'android') + run: | + NDK_BIN="$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin" + + export CC_aarch64_linux_android="$NDK_BIN/aarch64-linux-android24-clang" + export CXX_aarch64_linux_android="$NDK_BIN/aarch64-linux-android24-clang++" + export AR_aarch64_linux_android="$NDK_BIN/llvm-ar" + export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="$NDK_BIN/aarch64-linux-android24-clang" + + cargo build --release --target ${{ matrix.target }} -p fff-c + mv "${{ matrix.artifact_name }}" "c-lib-${{ matrix.target }}.${{ matrix.ext }}" + - name: Build for macOS if: contains(matrix.os, 'macos') run: | @@ -206,6 +246,7 @@ jobs: mv "${{ matrix.artifact_name }}" "c-lib-${{ matrix.target }}.${{ matrix.ext }}" - name: Prepare npm package + if: "!contains(matrix.target, 'android')" shell: bash run: | # Copy the built binary into the platform npm package directory @@ -218,6 +259,7 @@ jobs: path: c-lib-${{ matrix.target }}.* - name: Upload npm package artifact + if: "!contains(matrix.target, 'android')" uses: actions/upload-artifact@v4 with: name: npm-${{ matrix.npm_package }} diff --git a/Cargo.lock b/Cargo.lock index 200ff30..2612098 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2509,9 +2509,9 @@ dependencies = [ [[package]] name = "zlob" -version = "1.2.9" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "674f4e74544c0a00887c0dff7862fe13742de8c5dbcf6db9eac0643362554d44" +checksum = "07934fb13f0f4e14281bab6b0e984cfc03891d2cf5b0a8bd0ab14fd240e21106" dependencies = [ "bindgen", "bitflags 2.9.1", diff --git a/Cargo.toml b/Cargo.toml index 7495581..deca33c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ heed = "0.22.0" ignore = "0.4.22" memmap2 = "0.9" mimalloc = "0.1.47" -zlob = "1.2.9" +zlob = "1.3.0" mlua = { version = "0.11.1", features = ["module", "luajit"] } neo_frizbee = "0.8.1" diff --git a/doc/fff.nvim.txt b/doc/fff.nvim.txt index d08bbb6..0271993 100644 --- a/doc/fff.nvim.txt +++ b/doc/fff.nvim.txt @@ -1,4 +1,4 @@ -*fff.nvim.txt* For Neovim >= 0.10.0 Last change: 2026 February 26 +*fff.nvim.txt* For Neovim >= 0.10.0 Last change: 2026 February 28 ============================================================================== Table of Contents *fff.nvim-table-of-contents* diff --git a/lua/fff/utils/system.lua b/lua/fff/utils/system.lua index bf49a91..418b417 100644 --- a/lua/fff/utils/system.lua +++ b/lua/fff/utils/system.lua @@ -11,18 +11,24 @@ function M.get_triple() if os_name == 'darwin' then os_name = 'apple-darwin' elseif os_name == 'linux' then - -- Detect if we're on musl or glibc - local handle = io.popen('ldd --version 2>&1') - if handle then - local output = handle:read('*a') - handle:close() - if output and output:match('musl') then - os_name = 'unknown-linux-musl' + -- Detect Android/Termux before checking musl/glibc. + -- Termux uses Bionic libc (not glibc or musl) and has no ldd. + if os.getenv('TERMUX_VERSION') or os.getenv('ANDROID_ROOT') then + os_name = 'linux-android' + else + -- Detect if we're on musl or glibc + local handle = io.popen('ldd --version 2>&1') + if handle then + local output = handle:read('*a') + handle:close() + if output and output:match('musl') then + os_name = 'unknown-linux-musl' + else + os_name = 'unknown-linux-gnu' + end else os_name = 'unknown-linux-gnu' end - else - os_name = 'unknown-linux-gnu' end elseif os_name:match('windows') or os_name:match('mingw') or os_name:match('msys') then os_name = 'pc-windows-msvc'