Files
elizaos--eliza/.github/workflows/build-llama-ffi-android.yml
T
wehub-resource-sync 426e9eeabd
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Waiting to run
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Waiting to run
Build Agent Image / build-and-push (push) Waiting to run
Chat shell gestures / Chat shell gesture + parity e2e (push) Waiting to run
ci / test (push) Waiting to run
ci / lint-and-format (push) Waiting to run
ci / build (push) Waiting to run
ci / dev-startup (push) Waiting to run
Cloud Gateway Discord / Test (push) Waiting to run
Cloud Gateway Webhook / Test (push) Waiting to run
Cloud Tests / lint-and-types (push) Waiting to run
Cloud Tests / unit-tests (push) Waiting to run
Cloud Tests / integration-tests (push) Waiting to run
Cloud Tests / e2e-tests (push) Blocked by required conditions
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Apps Worker (Product 2) / Determine environment (push) Waiting to run
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Blocked by required conditions
Deploy Eliza Provisioning Worker / Determine environment (push) Waiting to run
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Blocked by required conditions
Dev Smoke / Classify changed paths (push) Waiting to run
Dev Smoke / bun run dev onboarding chat (push) Blocked by required conditions
Dev Smoke / Vite HMR dependency-level smoke (push) Blocked by required conditions
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Waiting to run
gitleaks / gitleaks (push) Waiting to run
Markdown Links / Relative Markdown Links (push) Waiting to run
Publish @elizaos/example-code / check_npm (push) Waiting to run
Publish @elizaos/example-code / publish_npm (push) Blocked by required conditions
Publish @elizaos/plugin-elizacloud / verify_version (push) Waiting to run
Publish @elizaos/plugin-elizacloud / publish_npm (push) Blocked by required conditions
Quality (Extended) / Homepage Build (PR smoke) (push) Waiting to run
Quality (Extended) / Comment-only diff guard (push) Waiting to run
Quality (Extended) / Format + Type Safety Ratchet (push) Waiting to run
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Waiting to run
Quality (Extended) / Develop Gate (lint) (push) Waiting to run
Sandbox Live Smoke / Sandbox live smoke (push) Waiting to run
Snap Build & Test / Build Snap (amd64) (push) Waiting to run
Snap Build & Test / Build Snap (arm64) (push) Waiting to run
supply-chain / sbom (push) Waiting to run
supply-chain / vulnerability-scan (push) Waiting to run
Build, Push & Deploy to Phala Cloud / build-and-push (push) Waiting to run
Test Packaging / Validate Packaging Configs (push) Waiting to run
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Waiting to run
Test Packaging / Pack & Test JS Tarballs (push) Waiting to run
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Waiting to run
UI Fixture E2E / ui-fixture-e2e (push) Waiting to run
UI Fixture E2E / fixture-e2e (push) Waiting to run
UI Story Gate / story-gate (push) Waiting to run
vault-ci / test (macos-latest) (push) Waiting to run
vault-ci / test (ubuntu-latest) (push) Waiting to run
vault-ci / test (windows-latest) (push) Waiting to run
vault-ci / app-core wiring tests (push) Waiting to run
verify-patches / verify patches/CHECKSUMS.sha256 (push) Waiting to run
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Waiting to run
Voice Benchmark Smoke / voice bench smoke summary (push) Blocked by required conditions
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Waiting to run
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Waiting to run
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Waiting to run
Test Packaging / Build & Test PyPI Package (push) Waiting to run
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

204 lines
9.7 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Build libelizainference (Android, FFI)
# Builds the Android NDK shared library `libelizainference.so` for the
# four supported ABIs and ships them as a per-ABI JNI bundle. The FFI
# streaming runner (`ffi-streaming-runner.ts`) dlopens this artifact
# from the APK's `lib/<abi>/` directory.
#
# Why FFI on Android: same reason as iOS — `child_process.spawn` is
# unavailable inside the app sandbox, the Play Store policy forbids
# downloading native binaries at runtime, and a 1030ms HTTP round-trip
# per token is unacceptable on a battery-constrained device. See
# `runtime-target.ts` for the decision rules.
#
# Builds in CI at build time (no eliza-archive prebuilt dependency). The fused
# lib is the real `libelizainference.so` produced by `compile-libllama.mjs` via
# the zig/musl cross-compile — NOT a renamed `libllama.so`, and NOT a bionic NDK
# build (bun's in-process FFI can only `dlopen` a musl-linked .so; see the header
# of `compile-libllama.mjs`). `workflow_call` lets the app build invoke this and
# consume the uploaded artifact directly instead of syncing from eliza-archive.
on:
workflow_call:
inputs:
abi_filter:
required: false
type: string
default: "arm64-v8a,x86_64"
workflow_dispatch:
inputs:
abi_filter:
description: "Comma-separated subset of ABIs to build (default: all)"
required: false
type: string
default: "arm64-v8a,x86_64"
push:
branches: [develop]
paths:
- "plugins/plugin-local-inference/native/llama.cpp/**"
- "packages/app-core/scripts/aosp/compile-libllama.mjs"
- ".github/workflows/build-llama-ffi-android.yml"
tags:
- "llama-ffi-android-*"
concurrency:
group: build-llama-ffi-android-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
NODE_VERSION: "24"
BUN_VERSION: "canary"
ANDROID_API: "26"
# Pinned to the NDK r26d-equivalent the rest of the app builds against;
# bumping this requires syncing with `packages/app/electrobun/android/`.
ANDROID_NDK_VERSION: "26.3.11579264"
jobs:
prepare-matrix:
runs-on: ${{ fromJSON(vars.HETZNER_FLEET_ONLINE == 'false' && '["ubuntu-24.04"]' || '["self-hosted","hetzner-robot"]') }}
outputs:
matrix: ${{ steps.set.outputs.matrix }}
steps:
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3
id: set
with:
script: |
const inputs = context.payload.inputs ?? {};
const filterRaw = (inputs.abi_filter ?? "arm64-v8a,x86_64").trim();
const filter = new Set(filterRaw.split(",").map((s) => s.trim()).filter(Boolean));
// compile-libllama.mjs fused targets: arm64 gets the Vulkan GPU
// backend (the QJL/Polar/Mali-FA-mitigation kernels live here),
// x86_64 (emulator/cuttlefish) is CPU-only. armeabi-v7a (32-bit)
// is unsupported by the fused build and dropped.
const all = [
{ abi: "arm64-v8a", target: "android-arm64-vulkan-fused" },
{ abi: "x86_64", target: "android-x86_64-cpu-fused" },
];
const include = all.filter((m) => filter.has(m.abi));
core.setOutput("matrix", JSON.stringify({ include }));
build:
name: ${{ matrix.abi }}
needs: prepare-matrix
runs-on: ${{ fromJSON(vars.HETZNER_FLEET_ONLINE == 'false' && '["ubuntu-24.04"]' || '["self-hosted","hetzner-robot"]') }}
timeout-minutes: 120
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.prepare-matrix.outputs.matrix) }}
steps:
- name: Checkout (with the llama.cpp fork submodule — the canonical source)
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
# The repo pins the fork via the submodule gitlink; build from that,
# not compile-libllama's LLAMA_CPP_COMMIT default (which can diverge
# from the gitlink and may not be a fetchable remote ref).
submodules: recursive
show-progress: false
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e
with:
node-version: ${{ env.NODE_VERSION }}
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: ${{ env.BUN_VERSION }}
- name: Install build deps (cmake, ninja, Vulkan-Hpp headers)
run: |
set -euo pipefail
# The runner image ships a packages.microsoft.com apt source that
# intermittently 403s / "is no longer signed", which fails apt-get
# update under pipefail even though this build needs nothing from it.
# Drop any MS apt source (filename varies by image) before updating.
for f in $(sudo grep -rliE 'packages\.microsoft\.com' /etc/apt/sources.list.d/ 2>/dev/null || true); do
sudo rm -f "$f"
done
sudo apt-get update -o Acquire::Retries=5 -o Acquire::http::Timeout=30
# libvulkan-dev provides /usr/include/vulkan/vulkan.hpp (arch-independent;
# compile-libllama searches /usr/include for it on Linux hosts).
sudo apt-get install -y cmake ninja-build build-essential git python3 libvulkan-dev
cmake --version
- name: Install zig 0.13 (the cross-compiler compile-libllama uses)
run: |
set -euo pipefail
# Pinned to 0.13 — the version the build is tested against; newer zig
# (0.16) regresses the musl lld link. See compile-libllama.mjs header.
curl -fsSL "https://ziglang.org/download/0.13.0/zig-linux-x86_64-0.13.0.tar.xz" -o /tmp/zig.tar.xz
mkdir -p "$HOME/.zig" && tar -xf /tmp/zig.tar.xz -C "$HOME/.zig" --strip-components=1
echo "$HOME/.zig" >> "$GITHUB_PATH"
"$HOME/.zig/zig" version
- name: Install Android NDK (sysroot + glslc for the Vulkan build)
uses: nttld/setup-ndk@ed92fe6cadad69be94a966a7ee3271275e62f779
id: setup-ndk
with:
ndk-version: r26d
add-to-path: false
- name: Build the real fused libelizainference.so (${{ matrix.target }})
env:
# compile-libllama's Vulkan resolver expects an SDK root with
# <ANDROID_HOME>/ndk/<numeric-version>/ (it lists ndk/, keeps dirs
# matching /^\d+\./, takes the highest, and treats it as the NDK root).
# nttld/setup-ndk (add-to-path:false, link-to-sdk:false) installs into
# the tool cache and exposes the NDK root via outputs.ndk-path — NOT in
# an <sdk>/ndk/<version> layout — so ${{ steps.setup-ndk.outputs.ndk-path }}/../..
# has no numeric ndk/ subdir and the resolver threw. Stitch a clean
# single-NDK SDK below and point ANDROID_HOME at it.
ANDROID_HOME: ${{ runner.temp }}/android-sdk
run: |
set -euo pipefail
# ndk/<numeric-version> -> the installed NDK root. r26d == 26.3.11579264
# (keep in sync with the ndk-version pin on the setup-ndk step above).
# A clean dir holding only this NDK guarantees the resolver's
# "highest numeric dir wins" picks r26d, independent of whatever NDK the
# runner image happens to preinstall.
mkdir -p "$ANDROID_HOME/ndk"
ln -sfn "${{ steps.setup-ndk.outputs.ndk-path }}" "$ANDROID_HOME/ndk/26.3.11579264"
# Builds the REAL fused FFI lib (libelizainference.so) via the
# zig/musl cross-compile — bun's in-process FFI can only dlopen a
# musl-linked .so, which the bionic NDK cmake path could not produce.
# --assets-dir redirects the staged output into
# artifacts/libelizainference/<target>/<abi>/libelizainference.so so the
# Verify + Upload steps below find it (the script otherwise defaults to
# packages/app/android/app/src/main/assets/agent/<abi>/).
# --src-dir builds from the in-repo fork submodule (the gitlink the
# repo pins + that `submodules: recursive` fetched) rather than
# compile-libllama's LLAMA_CPP_COMMIT default, which is a divergent
# local-only ref that is not fetchable in CI.
node packages/app-core/scripts/aosp/compile-libllama.mjs --target ${{ matrix.target }} --src-dir plugins/plugin-local-inference/native/llama.cpp --assets-dir artifacts/libelizainference/${{ matrix.target }}
- name: Verify fused artifact (FFI symbols + Mali FA mitigation on arm64)
run: |
set -euo pipefail
SO=$(find artifacts/libelizainference/${{ matrix.target }} -name "libelizainference.so" | head -1)
test -n "$SO" || { echo "no libelizainference.so produced"; find artifacts -name "*.so"; exit 1; }
file "$SO"; ls -lh "$SO"
# The fused FFI must export the eliza_inference_* voice ABI.
if ! nm -D "$SO" 2>/dev/null | grep -q "eliza_inference_"; then
echo "WARNING: eliza_inference_* symbols not visible via nm (stripped?)"
fi
if [ "${{ matrix.abi }}" = "arm64-v8a" ]; then
VK=$(find artifacts/libelizainference/${{ matrix.target }} -name "libggml-vulkan.so*" | head -1)
if [ -n "$VK" ] && strings "$VK" | grep -q GGML_VK_FA_ALLOW_SUBGROUPS; then
echo "OK: arm64 Vulkan lib carries the Mali flash-attn mitigation (#9508)"
else
echo "WARNING: GGML_VK_FA_ALLOW_SUBGROUPS marker not found in $VK"
fi
fi
- name: Upload libelizainference artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: libelizainference-${{ matrix.target }}
path: artifacts/libelizainference/${{ matrix.target }}/**
if-no-files-found: error
retention-days: 30