diff --git a/app/kernel/build-android.sh b/app/kernel/build-android.sh index f98f161..cc2ba4e 100644 --- a/app/kernel/build-android.sh +++ b/app/kernel/build-android.sh @@ -1,6 +1,13 @@ #!/usr/bin/env bash # build-android.sh — gomobile bind sing-box libbox → dist/android/libbox.aar # +# 与 scripts/build-libbox.sh android 的关系(两条都能产 app/kernel/dist/android/libbox.aar): +# - 本脚本:裸 gomobile bind 本地 .build/singbox 源,tag 精简(无 tailscale/cronet)→ +# 体积小、NDK 27 也能链接。**必须带 -javapkg io.nekohasekai**(见下方 bind),否则 +# 产出包名是默认 `libbox`,与 Kotlin 的 io.nekohasekai.libbox 对不上、APK 编不过。 +# - scripts/build-libbox.sh:走上游官方 build_libbox,带 tailscale/cronet → 体积大、需 NDK ≥ 28。 +# 两者产出包名一致(io.nekohasekai.libbox),择一即可;product 是 gitignore 的,清掉就得重建。 +# # 用法: ./build-android.sh [--force] # --force 忽略已有产物,强制重新构建 # @@ -155,6 +162,7 @@ LDFLAGS="-X github.com/sagernet/sing-box/constant.Version=${SINGBOX_VERSION} -X -target android/arm64,android/arm,android/amd64 \ -androidapi 21 \ -tags "${BUILD_TAGS}" \ + -javapkg io.nekohasekai \ -o "${OUT_AAR}" \ ./experimental/libbox ) diff --git a/client/android/app/build.gradle b/client/android/app/build.gradle index 658e5e7..b497e12 100644 --- a/client/android/app/build.gradle +++ b/client/android/app/build.gradle @@ -62,8 +62,11 @@ flutter { dependencies { // ── sing-box libbox(gomobile AAR)────────────────────────────── - // 产物由 app/kernel/build-android.sh 生成: - // cd app/kernel && ./build-android.sh + // 产物(gitignore,清掉/换 worktree 都要重建)二选一,均产 io.nekohasekai.libbox 包: + // bash scripts/build-libbox.sh android # 官方 build_libbox,需 NDK ≥ 28(自动部署到此路径) + // cd app/kernel && ./build-android.sh # 裸 gomobile bind,精简 tag、NDK 27 可 + // ⚠️ 包名必须是 io.nekohasekai.libbox(Kotlin import 依赖);若编出默认 `libbox` 包, + // 多半是 build-android.sh 漏了 -javapkg io.nekohasekai。 // 路径:client/android/app → ../../.. → repo root → app/kernel/dist/android/ // Kotlin stdlib 由 kotlin-android 插件自动引入,无需显式声明。 def libboxAar = file("${projectDir}/../../../app/kernel/dist/android/libbox.aar") diff --git a/scripts/build-libbox.sh b/scripts/build-libbox.sh index d40572c..c810aba 100644 --- a/scripts/build-libbox.sh +++ b/scripts/build-libbox.sh @@ -8,10 +8,19 @@ # 关键:用 sagernet 的 gomobile **fork**(非上游 golang.org/x/mobile)。 # sing-box 版本必须与节点对齐(当前节点 1.13.13)。 # +# 前置: +# - Go(PATH 中);gomobile/gobind 由本脚本自动 go install 到 $(go env GOPATH)/bin 并加 PATH。 +# - Android 还需 Android NDK ≥ 28(未设 ANDROID_NDK_HOME 则自动挑 SDK 里最高版)。 +# NDK 27 会因 cronet-go 预编译库链接失败(unknown relocation 315)。JDK 17 用于 bind 末段 javac。 +# +# 产物自动部署到工程引用位置(均 gitignore,故每次重建或换 worktree 都要重跑): +# apple → client/macos/Frameworks/Libbox.xcframework + client/ios/Frameworks/Libbox.xcframework +# android→ app/kernel/dist/android/libbox.aar(包名 io.nekohasekai.libbox,build.gradle 读这里) +# # 用法: # bash scripts/build-libbox.sh apple macos # 只编 macOS(快) # bash scripts/build-libbox.sh apple # 全 Apple(ios+sim+tvos+macos,慢) -# bash scripts/build-libbox.sh android +# bash scripts/build-libbox.sh android # Android aar(需 NDK ≥ 28) # SINGBOX_VERSION=v1.13.13 WORK=/tmp/x bash scripts/build-libbox.sh apple macos set -euo pipefail @@ -19,9 +28,23 @@ SINGBOX_VERSION="${SINGBOX_VERSION:-v1.13.13}" # 与节点 sing-box 对齐 TARGET="${1:-apple}" # apple | android PLATFORM="${2:-}" # macos | ios | "" (全 Apple) WORK="${WORK:-/tmp/pangolin-libbox}" +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" command -v go >/dev/null || { echo "✗ 需要 Go"; exit 1; } +# ── Android: 选 NDK ───────────────────────────────────────────────────────── +# ⚠️ 官方 build_libbox 会拉 cronet-go(Tailscale 依赖),其预编译 libcronet.a 含新版 +# 重定位类型,NDK 27 的 lld 链接报 "unknown relocation (315)" 而失败。**必须 NDK ≥ 28。** +# 未显式设 ANDROID_NDK_HOME 时,自动从 SDK 挑最高版本 NDK。 +if [ "$TARGET" = "android" ] && [ -z "${ANDROID_NDK_HOME:-}" ]; then + SDK="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-$HOME/Library/Android/sdk}}" + if [ -d "$SDK/ndk" ]; then + NDK_PICK="$(ls -d "$SDK"/ndk/*/ 2>/dev/null | sort | tail -1)" + [ -n "$NDK_PICK" ] && export ANDROID_NDK_HOME="${NDK_PICK%/}" ANDROID_HOME="$SDK" + fi +fi +[ "$TARGET" = "android" ] && echo " NDK = ${ANDROID_NDK_HOME:-<未找到!gomobile 会失败>}(android 需 ≥ 28,27 会链接失败)" + echo "==> [1/3] 安装 sagernet/gomobile fork v0.1.12(非上游)" go install github.com/sagernet/gomobile/cmd/gomobile@v0.1.12 go install github.com/sagernet/gomobile/cmd/gobind@v0.1.12 @@ -42,9 +65,19 @@ if [ "$TARGET" = "apple" ]; then go run ./cmd/internal/build_libbox -target apple fi echo "✅ 产物: $WORK/sing-box/Libbox.xcframework" - echo " 下一步(P1):拖进 macOS System Extension target 链接;Headers 暴露" - echo " LibboxNewService / LibboxCommandClient(状态·速率)等 API。" + # 部署到工程引用位置(client/{macos,ios}/Frameworks/Libbox.xcframework,均 gitignore)。 + for fw in "$REPO_ROOT/client/macos/Frameworks" "$REPO_ROOT/client/ios/Frameworks"; do + mkdir -p "$fw" + rm -rf "$fw/Libbox.xcframework" + cp -R "$WORK/sing-box/Libbox.xcframework" "$fw/" + echo " → 已部署 $fw/Libbox.xcframework" + done else go run ./cmd/internal/build_libbox -target android echo "✅ 产物: $WORK/sing-box/Libbox.aar" + # 部署到 build.gradle 引用位置(app/kernel/dist/android/libbox.aar,gitignore)。 + # ⚠️ 注意大小写/文件名:gradle 读的是小写 libbox.aar。 + mkdir -p "$REPO_ROOT/app/kernel/dist/android" + cp "$WORK/sing-box/Libbox.aar" "$REPO_ROOT/app/kernel/dist/android/libbox.aar" + echo " → 已部署 $REPO_ROOT/app/kernel/dist/android/libbox.aar(包名 io.nekohasekai.libbox)" fi