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
462 lines
18 KiB
Diff
462 lines
18 KiB
Diff
diff --git a/android/build.gradle b/android/build.gradle
|
|
--- a/android/build.gradle
|
|
+++ b/android/build.gradle
|
|
@@ -5,6 +5,44 @@
|
|
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
|
|
}
|
|
|
|
+def resolveElizaRepoRoot = { ->
|
|
+ return rootProject.projectDir.toPath().resolve('../../..').normalize().toFile().absolutePath
|
|
+}
|
|
+
|
|
+// Per-ABI resolver for the MTP cross-compile output produced by
|
|
+// `packages/app-core/scripts/build-llama-cpp-mtp.mjs` and
|
|
+// `packages/app-core/scripts/aosp/compile-libllama.mjs`. Each ABI has
|
|
+// its own gradle property (`eliza.mtp.android.libdir.<abi>`) and env
|
|
+// var (`ELIZA_MTP_ANDROID_LIBDIR_<ABI>`). For arm64-v8a the legacy
|
|
+// unsuffixed names are still honored for backwards compatibility.
|
|
+// riscv64 has no Vulkan path yet (Wave 2 ships CPU-only), so only the
|
|
+// `cpu` backend is searched on that ABI.
|
|
+def resolveElizaMtpAndroidLibDir = { String abi ->
|
|
+ def propSuffix = abi == 'arm64-v8a' ? '' : ".${abi}"
|
|
+ def envSuffix = abi == 'arm64-v8a' ? '' : "_${abi.replace('-', '_').toUpperCase()}"
|
|
+ def fromProp = project.findProperty("eliza.mtp.android.libdir${propSuffix}")
|
|
+ if (fromProp) return fromProp.toString()
|
|
+ def fromEnv = System.getenv("ELIZA_MTP_ANDROID_LIBDIR${envSuffix}")
|
|
+ if (fromEnv) return fromEnv
|
|
+ def stateDir = System.getenv('ELIZA_STATE_DIR') ?: "${System.getProperty('user.home')}/.eliza"
|
|
+ def abiToken = [
|
|
+ 'arm64-v8a': 'android-arm64',
|
|
+ 'x86_64' : 'android-x86_64',
|
|
+ 'riscv64' : 'android-riscv64',
|
|
+ ][abi]
|
|
+ if (abiToken == null) return ''
|
|
+ def backends = abi == 'riscv64' ? ['cpu'] : ['vulkan', 'cpu']
|
|
+ def candidates = backends.collect { backend ->
|
|
+ "${stateDir}/local-inference/bin/mtp/${abiToken}-${backend}"
|
|
+ }
|
|
+ return candidates.find { new File(it).isDirectory() } ?: ''
|
|
+}
|
|
+
|
|
+def resolveElizaSkipMtpAndroidLib = { ->
|
|
+ return project.findProperty('elizaSkipForkLlamaLib') == 'true' ||
|
|
+ System.getenv('ELIZA_ANDROID_SKIP_FORK_LLAMA_LIB') == '1'
|
|
+}
|
|
+
|
|
buildscript {
|
|
repositories {
|
|
google()
|
|
@@ -26,12 +64,21 @@
|
|
versionCode 1
|
|
versionName "1.0"
|
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
-
|
|
+
|
|
ndk {
|
|
- abiFilters 'arm64-v8a'
|
|
+ abiFilters 'arm64-v8a', 'riscv64'
|
|
+ }
|
|
+
|
|
+ externalNativeBuild {
|
|
+ cmake {
|
|
+ arguments "-DELIZA_REPO_ROOT=${resolveElizaRepoRoot()}",
|
|
+ "-DELIZA_MTP_ANDROID_LIBDIR_ARM64_V8A=${resolveElizaMtpAndroidLibDir('arm64-v8a')}",
|
|
+ "-DELIZA_MTP_ANDROID_LIBDIR_RISCV64=${resolveElizaMtpAndroidLibDir('riscv64')}",
|
|
+ "-DELIZA_SKIP_MTP_ANDROID_LIB=${resolveElizaSkipMtpAndroidLib() ? 'ON' : 'OFF'}"
|
|
+ }
|
|
}
|
|
}
|
|
-
|
|
+
|
|
externalNativeBuild {
|
|
cmake {
|
|
path "src/main/CMakeLists.txt"
|
|
@@ -40,23 +87,23 @@
|
|
ndkVersion = "29.0.13113456"
|
|
}
|
|
}
|
|
-
|
|
+
|
|
buildTypes {
|
|
release {
|
|
minifyEnabled false
|
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
}
|
|
}
|
|
-
|
|
+
|
|
lintOptions {
|
|
abortOnError = false
|
|
}
|
|
-
|
|
+
|
|
compileOptions {
|
|
sourceCompatibility JavaVersion.VERSION_21
|
|
targetCompatibility JavaVersion.VERSION_21
|
|
}
|
|
-
|
|
+
|
|
sourceSets {
|
|
main {
|
|
java {
|
|
@@ -64,13 +111,6 @@
|
|
}
|
|
}
|
|
}
|
|
-
|
|
- // Disable clean tasks that might cause issues
|
|
- tasks.whenTaskAdded { task ->
|
|
- if (task.name.contains('Clean') && task.name.contains('Debug')) {
|
|
- task.enabled = false
|
|
- }
|
|
- }
|
|
}
|
|
|
|
repositories {
|
|
diff --git a/android/src/main/CMakeLists.txt b/android/src/main/CMakeLists.txt
|
|
--- a/android/src/main/CMakeLists.txt
|
|
+++ b/android/src/main/CMakeLists.txt
|
|
@@ -1,131 +1,157 @@
|
|
-cmake_minimum_required(VERSION 3.10)
|
|
+cmake_minimum_required(VERSION 3.22)
|
|
|
|
-project(llama-cpp)
|
|
+project(llama-cpp-capacitor-eliza-mtp)
|
|
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
-set(LLAMACPP_LIB_DIR ${CMAKE_SOURCE_DIR}/../../../cpp)
|
|
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
|
|
-include_directories(
|
|
- ${LLAMACPP_LIB_DIR}
|
|
- ${LLAMACPP_LIB_DIR}/ggml-cpu
|
|
- ${LLAMACPP_LIB_DIR}/tools/mtmd
|
|
-)
|
|
+option(ELIZA_SKIP_MTP_ANDROID_LIB "Build a no-op JNI library for Android smoke builds without MTP libs" OFF)
|
|
+
|
|
+find_library(LOG_LIB log)
|
|
+find_library(ANDROID_LIB android)
|
|
+
|
|
+if(ELIZA_SKIP_MTP_ANDROID_LIB)
|
|
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/eliza-mtp-smoke.cpp" "extern \"C\" int eliza_mtp_smoke() { return 0; }\n")
|
|
+ if(ANDROID_ABI STREQUAL "riscv64")
|
|
+ set(ELIZA_SMOKE_OUTPUT_NAME "llama-cpp-riscv64")
|
|
+ else()
|
|
+ set(ELIZA_SMOKE_OUTPUT_NAME "llama-cpp-arm64")
|
|
+ endif()
|
|
+ add_library(${ELIZA_SMOKE_OUTPUT_NAME} SHARED "${CMAKE_CURRENT_BINARY_DIR}/eliza-mtp-smoke.cpp")
|
|
+ target_link_libraries(${ELIZA_SMOKE_OUTPUT_NAME} PRIVATE ${LOG_LIB} ${ANDROID_LIB})
|
|
+ set_target_properties(
|
|
+ ${ELIZA_SMOKE_OUTPUT_NAME}
|
|
+ PROPERTIES
|
|
+ OUTPUT_NAME "${ELIZA_SMOKE_OUTPUT_NAME}"
|
|
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/jniLibs/${ANDROID_ABI}"
|
|
+ )
|
|
+ message(STATUS "Building Eliza MTP JNI smoke library for Android ${ANDROID_ABI}")
|
|
+ return()
|
|
+endif()
|
|
+
|
|
+if(NOT DEFINED ELIZA_REPO_ROOT)
|
|
+ message(FATAL_ERROR "ELIZA_REPO_ROOT is required for the Eliza MTP Android JNI bridge")
|
|
+endif()
|
|
|
|
-set(
|
|
- SOURCE_FILES
|
|
- ${LLAMACPP_LIB_DIR}/ggml.c
|
|
- ${LLAMACPP_LIB_DIR}/ggml-alloc.c
|
|
- ${LLAMACPP_LIB_DIR}/ggml-backend.cpp
|
|
- ${LLAMACPP_LIB_DIR}/ggml-backend-reg.cpp
|
|
- ${LLAMACPP_LIB_DIR}/ggml-cpu/amx/amx.cpp
|
|
- ${LLAMACPP_LIB_DIR}/ggml-cpu/amx/mmq.cpp
|
|
- ${LLAMACPP_LIB_DIR}/ggml-cpu/ggml-cpu.c
|
|
- ${LLAMACPP_LIB_DIR}/ggml-cpu/ggml-cpu.cpp
|
|
- ${LLAMACPP_LIB_DIR}/ggml-cpu/quants.c
|
|
- ${LLAMACPP_LIB_DIR}/ggml-cpu/traits.cpp
|
|
- ${LLAMACPP_LIB_DIR}/ggml-cpu/repack.cpp
|
|
- ${LLAMACPP_LIB_DIR}/ggml-cpu/unary-ops.cpp
|
|
- ${LLAMACPP_LIB_DIR}/ggml-cpu/binary-ops.cpp
|
|
- ${LLAMACPP_LIB_DIR}/ggml-cpu/vec.cpp
|
|
- ${LLAMACPP_LIB_DIR}/ggml-cpu/ops.cpp
|
|
- ${LLAMACPP_LIB_DIR}/ggml-opt.cpp
|
|
- ${LLAMACPP_LIB_DIR}/ggml-threading.cpp
|
|
- ${LLAMACPP_LIB_DIR}/ggml-quants.c
|
|
- ${LLAMACPP_LIB_DIR}/gguf.cpp
|
|
- ${LLAMACPP_LIB_DIR}/log.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-impl.cpp
|
|
- ${LLAMACPP_LIB_DIR}/chat-parser.cpp
|
|
- ${LLAMACPP_LIB_DIR}/json-partial.cpp
|
|
- ${LLAMACPP_LIB_DIR}/regex-partial.cpp
|
|
- # Multimodal support
|
|
- ${LLAMACPP_LIB_DIR}/tools/mtmd/mtmd.cpp
|
|
- ${LLAMACPP_LIB_DIR}/tools/mtmd/mtmd-audio.cpp
|
|
- ${LLAMACPP_LIB_DIR}/tools/mtmd/clip.cpp
|
|
- ${LLAMACPP_LIB_DIR}/tools/mtmd/mtmd-helper.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-grammar.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-sampling.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-vocab.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-adapter.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-chat.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-context.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-arch.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-batch.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-cparams.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-hparams.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-model.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-model-loader.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-model-saver.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-kv-cache.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-kv-cache-iswa.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-memory-hybrid.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-memory-recurrent.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-mmap.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-vocab.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-memory.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-io.cpp
|
|
- ${LLAMACPP_LIB_DIR}/llama-graph.cpp
|
|
- ${LLAMACPP_LIB_DIR}/sampling.cpp
|
|
- ${LLAMACPP_LIB_DIR}/unicode-data.cpp
|
|
- ${LLAMACPP_LIB_DIR}/unicode.cpp
|
|
- ${LLAMACPP_LIB_DIR}/common.cpp
|
|
- ${LLAMACPP_LIB_DIR}/chat.cpp
|
|
- ${LLAMACPP_LIB_DIR}/json-schema-to-grammar.cpp
|
|
- ${LLAMACPP_LIB_DIR}/nlohmann/json.hpp
|
|
- ${LLAMACPP_LIB_DIR}/nlohmann/json_fwd.hpp
|
|
- ${LLAMACPP_LIB_DIR}/minja/minja.hpp
|
|
- ${LLAMACPP_LIB_DIR}/minja/chat-template.hpp
|
|
- ${LLAMACPP_LIB_DIR}/anyascii.c
|
|
- ${LLAMACPP_LIB_DIR}/cap-llama.cpp
|
|
- ${LLAMACPP_LIB_DIR}/cap-completion.cpp
|
|
- ${LLAMACPP_LIB_DIR}/cap-tts.cpp
|
|
- ${CMAKE_SOURCE_DIR}/jni-utils.h
|
|
- ${CMAKE_SOURCE_DIR}/jni.cpp
|
|
+if(NOT DEFINED ELIZA_REPO_ROOT)
|
|
+ message(FATAL_ERROR "ELIZA_REPO_ROOT is required for the Eliza MTP Android JNI bridge")
|
|
+endif()
|
|
+
|
|
+# Per-ABI MTP lib dirs are passed by android/build.gradle. Only the
|
|
+# entry for the currently-building ABI is required; the other can be empty.
|
|
+# riscv64 is CPU-only today (no ggml-vulkan.so produced yet).
|
|
+if(ANDROID_ABI STREQUAL "arm64-v8a")
|
|
+ set(ELIZA_MTP_LIBDIR "${ELIZA_MTP_ANDROID_LIBDIR_ARM64_V8A}")
|
|
+ set(ELIZA_OUTPUT_NAME "llama-cpp-arm64")
|
|
+ set(ELIZA_HAS_VULKAN TRUE)
|
|
+elseif(ANDROID_ABI STREQUAL "riscv64")
|
|
+ set(ELIZA_MTP_LIBDIR "${ELIZA_MTP_ANDROID_LIBDIR_RISCV64}")
|
|
+ set(ELIZA_OUTPUT_NAME "llama-cpp-riscv64")
|
|
+ set(ELIZA_HAS_VULKAN FALSE)
|
|
+else()
|
|
+ message(FATAL_ERROR "Unsupported ANDROID_ABI for Eliza MTP JNI bridge: ${ANDROID_ABI} (expected arm64-v8a or riscv64)")
|
|
+endif()
|
|
+
|
|
+if(NOT ELIZA_MTP_LIBDIR OR ELIZA_MTP_LIBDIR STREQUAL "")
|
|
+ message(FATAL_ERROR "MTP Android lib dir is empty for ABI ${ANDROID_ABI}; set -Peliza.mtp.android.libdir.${ANDROID_ABI} or ELIZA_MTP_ANDROID_LIBDIR_<ABI>, or run packages/app-core/scripts/build-llama-cpp-mtp.mjs --target android-${ANDROID_ABI}-cpu (or aosp/compile-libllama.mjs)")
|
|
+endif()
|
|
+
|
|
+set(ELIZA_LLAMA_CPP_DIR "${ELIZA_REPO_ROOT}/plugins/plugin-local-inference/native/llama.cpp")
|
|
+
|
|
+# Resolve the Eliza MTP JNI bridge source. The canonical workspace
|
|
+# path moved during the os-linux cleanup: prefer the new location
|
|
+# (packages/native/plugins/llama) but fall back to the historical
|
|
+# alternates so older checkouts keep building.
|
|
+foreach(candidate_jni
|
|
+ "${ELIZA_REPO_ROOT}/packages/native/plugins/llama/android/eliza-mtp-jni.cpp"
|
|
+ "${ELIZA_REPO_ROOT}/plugins/plugin-native-llama/android/eliza-mtp-jni.cpp"
|
|
+ "${ELIZA_REPO_ROOT}/packages/native-plugins/llama/android/eliza-mtp-jni.cpp"
|
|
)
|
|
+ if(EXISTS "${candidate_jni}")
|
|
+ set(ELIZA_MTP_JNI_CPP "${candidate_jni}")
|
|
+ break()
|
|
+ endif()
|
|
+endforeach()
|
|
+
|
|
+if(NOT DEFINED ELIZA_MTP_JNI_CPP)
|
|
+ message(FATAL_ERROR "Could not locate eliza-mtp-jni.cpp under ${ELIZA_REPO_ROOT} (looked under packages/native/plugins/llama, plugins/plugin-native-llama, packages/native-plugins/llama)")
|
|
+endif()
|
|
+
|
|
+set(_eliza_required_libs libllama.so libggml.so libggml-base.so libggml-cpu.so)
|
|
+if(ELIZA_HAS_VULKAN)
|
|
+ list(APPEND _eliza_required_libs libggml-vulkan.so)
|
|
+endif()
|
|
+foreach(required_lib ${_eliza_required_libs})
|
|
+ if(NOT EXISTS "${ELIZA_MTP_LIBDIR}/${required_lib}")
|
|
+ message(FATAL_ERROR "Missing MTP Android library: ${ELIZA_MTP_LIBDIR}/${required_lib}")
|
|
+ endif()
|
|
+endforeach()
|
|
+
|
|
+add_library(eliza_llama SHARED IMPORTED)
|
|
+set_target_properties(eliza_llama PROPERTIES IMPORTED_LOCATION "${ELIZA_MTP_LIBDIR}/libllama.so")
|
|
+
|
|
+add_library(eliza_ggml SHARED IMPORTED)
|
|
+set_target_properties(eliza_ggml PROPERTIES IMPORTED_LOCATION "${ELIZA_MTP_LIBDIR}/libggml.so")
|
|
+
|
|
+add_library(eliza_ggml_base SHARED IMPORTED)
|
|
+set_target_properties(eliza_ggml_base PROPERTIES IMPORTED_LOCATION "${ELIZA_MTP_LIBDIR}/libggml-base.so")
|
|
+
|
|
+add_library(eliza_ggml_cpu SHARED IMPORTED)
|
|
+set_target_properties(eliza_ggml_cpu PROPERTIES IMPORTED_LOCATION "${ELIZA_MTP_LIBDIR}/libggml-cpu.so")
|
|
+
|
|
+if(ELIZA_HAS_VULKAN)
|
|
+ add_library(eliza_ggml_vulkan SHARED IMPORTED)
|
|
+ set_target_properties(eliza_ggml_vulkan PROPERTIES IMPORTED_LOCATION "${ELIZA_MTP_LIBDIR}/libggml-vulkan.so")
|
|
+endif()
|
|
|
|
-# Find Android libraries
|
|
find_library(LOG_LIB log)
|
|
find_library(ANDROID_LIB android)
|
|
|
|
-# ARM64 specific build function for real devices
|
|
-function(build_library_arm64 target_name)
|
|
- add_library(
|
|
- ${target_name}
|
|
- SHARED
|
|
- ${SOURCE_FILES}
|
|
- )
|
|
-
|
|
- # ARM64 specific compile options for real devices
|
|
- target_compile_options(${target_name} PRIVATE
|
|
- -march=armv8-a
|
|
- -mtune=cortex-a76
|
|
- -O3
|
|
- -DNDEBUG
|
|
- -DLM_GGML_USE_CPU
|
|
- -DLM_GGML_CPU_GENERIC
|
|
- -fno-finite-math-only
|
|
- -funroll-loops
|
|
- )
|
|
-
|
|
- # Link with Android libraries
|
|
- target_link_libraries(${target_name}
|
|
- ${LOG_LIB}
|
|
- ${ANDROID_LIB}
|
|
- )
|
|
-
|
|
- # Set output name and directory
|
|
- set_target_properties(${target_name} PROPERTIES
|
|
- OUTPUT_NAME "llama-cpp-arm64"
|
|
- LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/jniLibs/arm64-v8a"
|
|
- )
|
|
-endfunction()
|
|
-
|
|
-# Build ARM64 library for real devices
|
|
-build_library_arm64(llama-cpp-arm64)
|
|
-
|
|
-# Print build information
|
|
-message(STATUS "Building llama-cpp for Android ARM64 (real devices)")
|
|
-message(STATUS "Source directory: ${LLAMACPP_LIB_DIR}")
|
|
-message(STATUS "Architecture: ARM64 (arm64-v8a)")
|
|
-message(STATUS "Optimizations: ARMv8-A, Cortex-A76 tuning")
|
|
-message(STATUS "Output directory: ${CMAKE_CURRENT_SOURCE_DIR}/jniLibs/arm64-v8a")
|
|
+add_library(
|
|
+ ${ELIZA_OUTPUT_NAME}
|
|
+ SHARED
|
|
+ ${ELIZA_MTP_JNI_CPP}
|
|
+ ${ELIZA_LLAMA_CPP_DIR}/common/json-schema-to-grammar.cpp
|
|
+)
|
|
+
|
|
+target_include_directories(
|
|
+ ${ELIZA_OUTPUT_NAME}
|
|
+ PRIVATE
|
|
+ ${ELIZA_LLAMA_CPP_DIR}/include
|
|
+ ${ELIZA_LLAMA_CPP_DIR}/ggml/include
|
|
+ ${ELIZA_LLAMA_CPP_DIR}/common
|
|
+ ${ELIZA_LLAMA_CPP_DIR}/vendor
|
|
+)
|
|
+
|
|
+target_compile_options(
|
|
+ ${ELIZA_OUTPUT_NAME}
|
|
+ PRIVATE
|
|
+ -O3
|
|
+ -DNDEBUG
|
|
+ -fno-finite-math-only
|
|
+)
|
|
+
|
|
+set(_eliza_link_libs eliza_llama eliza_ggml eliza_ggml_cpu eliza_ggml_base)
|
|
+if(ELIZA_HAS_VULKAN)
|
|
+ list(APPEND _eliza_link_libs eliza_ggml_vulkan)
|
|
+endif()
|
|
+
|
|
+target_link_libraries(
|
|
+ ${ELIZA_OUTPUT_NAME}
|
|
+ PRIVATE
|
|
+ ${_eliza_link_libs}
|
|
+ ${LOG_LIB}
|
|
+ ${ANDROID_LIB}
|
|
+)
|
|
+
|
|
+set_target_properties(
|
|
+ ${ELIZA_OUTPUT_NAME}
|
|
+ PROPERTIES
|
|
+ OUTPUT_NAME "${ELIZA_OUTPUT_NAME}"
|
|
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/jniLibs/${ANDROID_ABI}"
|
|
+)
|
|
+
|
|
+message(STATUS "Building Eliza MTP JNI bridge for Android ${ANDROID_ABI}")
|
|
+message(STATUS "Eliza repo root: ${ELIZA_REPO_ROOT}")
|
|
+message(STATUS "MTP lib dir: ${ELIZA_MTP_LIBDIR}")
|
|
+message(STATUS "Vulkan backend: ${ELIZA_HAS_VULKAN}")
|
|
diff --git a/android/src/main/java/ai/annadata/plugin/capacitor/LlamaCpp.java b/android/src/main/java/ai/annadata/plugin/capacitor/LlamaCpp.java
|
|
--- a/android/src/main/java/ai/annadata/plugin/capacitor/LlamaCpp.java
|
|
+++ b/android/src/main/java/ai/annadata/plugin/capacitor/LlamaCpp.java
|
|
@@ -305,13 +305,40 @@
|
|
case "x86_64":
|
|
libraryName = "llama-cpp-x86_64";
|
|
break;
|
|
+ case "riscv64":
|
|
+ libraryName = "llama-cpp-riscv64";
|
|
+ break;
|
|
default:
|
|
Log.w(TAG, "Unsupported ABI: " + abi + ", falling back to arm64-v8a");
|
|
libraryName = "llama-cpp-arm64";
|
|
break;
|
|
}
|
|
-
|
|
+
|
|
Log.i(TAG, "Loading native library for ABI: " + abi + " (library: " + libraryName + ")");
|
|
+ // Preload MTP dependency libraries before our JNI bridge so
|
|
+ // dlopen resolves the chain without ld.so probing LD_LIBRARY_PATH.
|
|
+ // riscv64 currently has no ggml-vulkan.so (Wave 2 CPU-only); the
|
|
+ // preload is wrapped in try/catch and an absent dependency is
|
|
+ // logged as a warning rather than failing the load.
|
|
+ if ("arm64-v8a".equals(abi) || "riscv64".equals(abi)) {
|
|
+ java.util.List<String> mtpDependencies = new java.util.ArrayList<>();
|
|
+ mtpDependencies.add("omp");
|
|
+ mtpDependencies.add("ggml-base");
|
|
+ mtpDependencies.add("ggml-cpu");
|
|
+ if ("arm64-v8a".equals(abi)) {
|
|
+ mtpDependencies.add("ggml-vulkan");
|
|
+ }
|
|
+ mtpDependencies.add("ggml");
|
|
+ mtpDependencies.add("llama");
|
|
+ for (String dependency : mtpDependencies) {
|
|
+ try {
|
|
+ System.loadLibrary(dependency);
|
|
+ Log.i(TAG, "Loaded MTP dependency: " + dependency);
|
|
+ } catch (UnsatisfiedLinkError dependencyError) {
|
|
+ Log.w(TAG, "Could not preload MTP dependency " + dependency + ": " + dependencyError.getMessage());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
System.loadLibrary(libraryName);
|
|
Log.i(TAG, "Successfully loaded llama-cpp native library: " + libraryName);
|
|
} catch (UnsatisfiedLinkError e) {
|
|
@@ -332,7 +359,17 @@
|
|
Log.i(TAG, "Native logging disabled");
|
|
}
|
|
callback.onResult(LlamaResult.success(null));
|
|
- } catch (Exception e) {
|
|
+ } catch (Throwable e) {
|
|
+ // Catch Throwable, not just Exception: when the native library is a
|
|
+ // symbol-less stub (the skipForkLlamaLib / ELIZA_ANDROID_SKIP_FORK_LLAMA_LIB
|
|
+ // dev build ships a JNI-symbol-free libllama-cpp-arm64.so), the JNI
|
|
+ // binding for toggleNativeLogNative fails with UnsatisfiedLinkError,
|
|
+ // which is an Error rather than an Exception. Left uncaught it escapes
|
|
+ // this @PluginMethod, is rewrapped by Capacitor's Bridge as a
|
|
+ // RuntimeException on the UI thread, and force-finishes MainActivity
|
|
+ // ("Eliza keeps stopping"). A missing optional native-log toggle must
|
|
+ // degrade gracefully instead, so we reject the call and keep booting.
|
|
+ Log.w(TAG, "Native log toggle unavailable (stub/missing native lib): " + e);
|
|
callback.onResult(LlamaResult.failure(new LlamaError("Failed to toggle native log: " + e.getMessage())));
|
|
}
|
|
}
|