134 lines
6.0 KiB
Bash
134 lines
6.0 KiB
Bash
#!/usr/bin/env bash
|
||
# build-android.sh — gomobile bind sing-box libbox → dist/android/libbox.aar
|
||
#
|
||
# 用法: ./build-android.sh [--force]
|
||
# --force 忽略已有产物,强制重新构建
|
||
#
|
||
# 依赖:
|
||
# - Go : VERSION 中 GO_VERSION 指定的版本($GOROOT 或 PATH 中的 go)
|
||
# - gomobile: 脚本自动安装至 $GOPATH/bin,依赖 GOMOBILE_VERSION
|
||
# - Android NDK: 需设置 ANDROID_NDK_HOME 或 ANDROID_HOME(含 ndk-bundle/ndk/<ver>)
|
||
#
|
||
# 产物: dist/android/libbox.aar
|
||
# 包含三个 ABI: arm64-v8a / armeabi-v7a / x86_64
|
||
#
|
||
# Build tags 说明(对齐官方 SFA — sing-box for Android):
|
||
# with_quic — QUIC/HTTP3 协议支持(Hysteria2 必须)
|
||
# with_utls — uTLS 指纹模拟(TLS 防检测)
|
||
# with_clash_api — Clash 兼容 API(面板控制必须)
|
||
# with_gvisor — gVisor TUN 网络栈(高性能 TUN 回退)
|
||
#
|
||
# 裁剪开关(按需取消注释):
|
||
# with_grpc — gRPC 入站(约 +4 MB so 体积)
|
||
# with_ech — TLS ECH 扩展(约 +0.5 MB)
|
||
# with_wireguard — WireGuard 出站(约 +2 MB)
|
||
|
||
set -euo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
||
# ── 加载版本锚点 ─────────────────────────────────────────────────────────────
|
||
# shellcheck source=VERSION
|
||
. "${SCRIPT_DIR}/VERSION"
|
||
|
||
# ── 参数解析 ─────────────────────────────────────────────────────────────────
|
||
FORCE=false
|
||
for arg in "$@"; do
|
||
case "${arg}" in
|
||
--force) FORCE=true ;;
|
||
*) printf 'Unknown argument: %s\n' "${arg}" >&2; exit 1 ;;
|
||
esac
|
||
done
|
||
|
||
# ── 路径配置 ─────────────────────────────────────────────────────────────────
|
||
DIST_DIR="${SCRIPT_DIR}/dist/android"
|
||
OUT_AAR="${DIST_DIR}/libbox.aar"
|
||
BUILD_SRC="${SCRIPT_DIR}/.build/singbox"
|
||
|
||
# ── Build tags ────────────────────────────────────────────────────────────────
|
||
BUILD_TAGS="with_quic,with_utls,with_clash_api,with_gvisor"
|
||
# 取消注释以增加功能(会增大 .so 体积):
|
||
# BUILD_TAGS="${BUILD_TAGS},with_grpc"
|
||
# BUILD_TAGS="${BUILD_TAGS},with_ech"
|
||
# BUILD_TAGS="${BUILD_TAGS},with_wireguard"
|
||
|
||
# ── 幂等检查 ─────────────────────────────────────────────────────────────────
|
||
if [[ "${FORCE}" == false && -f "${OUT_AAR}" ]]; then
|
||
printf '✓ %s 已存在,跳过构建(传 --force 强制重建)\n' "${OUT_AAR}"
|
||
exit 0
|
||
fi
|
||
|
||
# ── 前置检查 ─────────────────────────────────────────────────────────────────
|
||
printf '==> 检查前置依赖…\n'
|
||
|
||
if ! command -v go >/dev/null 2>&1; then
|
||
printf '✗ go 未找到,请安装 Go %s\n' "${GO_VERSION}" >&2
|
||
exit 1
|
||
fi
|
||
if ! command -v git >/dev/null 2>&1; then
|
||
printf '✗ git 未找到\n' >&2
|
||
exit 1
|
||
fi
|
||
|
||
ACTUAL_GO="$(go version | awk '{print $3}' | sed 's/go//')"
|
||
printf ' Go 版本: %s(期望 %s)\n' "${ACTUAL_GO}" "${GO_VERSION}"
|
||
|
||
if [[ -n "${ANDROID_NDK_HOME:-}" ]]; then
|
||
printf ' NDK: %s\n' "${ANDROID_NDK_HOME}"
|
||
elif [[ -n "${ANDROID_HOME:-}" ]]; then
|
||
printf ' Android SDK: %s(gomobile 将自动定位 NDK)\n' "${ANDROID_HOME}"
|
||
else
|
||
printf '⚠ 未设置 ANDROID_NDK_HOME / ANDROID_HOME,gomobile init 可能失败\n' >&2
|
||
fi
|
||
|
||
# ── 安装 gomobile ─────────────────────────────────────────────────────────────
|
||
printf '==> 安装 gomobile@%s…\n' "${GOMOBILE_VERSION}"
|
||
go install "golang.org/x/mobile/cmd/gomobile@${GOMOBILE_VERSION}"
|
||
go install "golang.org/x/mobile/cmd/gobind@${GOMOBILE_VERSION}"
|
||
|
||
printf '==> gomobile init…\n'
|
||
gomobile init
|
||
|
||
# ── 准备 sing-box 源码 ────────────────────────────────────────────────────────
|
||
printf '==> 准备 sing-box %s 源码…\n' "${SINGBOX_VERSION}"
|
||
|
||
EXISTING_TAG=""
|
||
if [[ -d "${BUILD_SRC}/.git" ]]; then
|
||
EXISTING_TAG="$(git -C "${BUILD_SRC}" describe --tags --exact-match 2>/dev/null)" || EXISTING_TAG="unknown"
|
||
fi
|
||
|
||
if [[ "${EXISTING_TAG}" == "${SINGBOX_VERSION}" ]]; then
|
||
printf ' 源码已是 %s,跳过克隆\n' "${SINGBOX_VERSION}"
|
||
else
|
||
if [[ -d "${BUILD_SRC}" ]]; then
|
||
printf ' 已有源码版本 %s ≠ %s,清理后重新克隆…\n' "${EXISTING_TAG}" "${SINGBOX_VERSION}"
|
||
rm -rf "${BUILD_SRC}"
|
||
fi
|
||
mkdir -p "${BUILD_SRC%/*}"
|
||
git clone --depth 1 --branch "${SINGBOX_VERSION}" \
|
||
https://github.com/SagerNet/sing-box.git "${BUILD_SRC}"
|
||
fi
|
||
|
||
# ── 构建 AAR ──────────────────────────────────────────────────────────────────
|
||
printf '==> 构建 libbox.aar\n'
|
||
printf ' target : android/arm64,android/arm,android/amd64\n'
|
||
printf ' api : 21\n'
|
||
printf ' tags : %s\n' "${BUILD_TAGS}"
|
||
|
||
mkdir -p "${DIST_DIR}"
|
||
|
||
(
|
||
cd "${BUILD_SRC}"
|
||
go mod download
|
||
gomobile bind \
|
||
-target android/arm64,android/arm,android/amd64 \
|
||
-androidapi 21 \
|
||
-tags "${BUILD_TAGS}" \
|
||
-o "${OUT_AAR}" \
|
||
./experimental/libbox
|
||
)
|
||
|
||
printf '\n✓ 构建完成: %s\n' "${OUT_AAR}"
|
||
printf ' ABI 验证(.so 文件列表):\n'
|
||
unzip -l "${OUT_AAR}" | grep -E '\.so$' | awk '{print " " $NF}' || true
|