Support relocatable custom install roots

This commit is contained in:
mm644706215
2026-03-20 18:05:39 +08:00
parent 68f24e6658
commit a4c92ee59a
9 changed files with 298 additions and 51 deletions

View File

@@ -12,14 +12,16 @@
# 1. apk 模式: 使用 Alpine apk 安装 nodejs版本受限于 Alpine 仓库
# 2. cross 模式: 从 Node.js 官方下载 glibc 版本,转换为 musl
# 使用 patchelf 修改 node 二进制的 ELF interpreter 和 rpath
# 使其直接使用打包的 musl 链接器和共享库,无需 LD_LIBRARY_PATH
# 使其使用系统 musl 动态链接器和相对 rpath可从任意安装根目录直接运行
# 这样 process.execPath 返回正确的 node 路径,子进程 fork 也能正常工作。
# 安装路径固定为 /opt/openclaw/node (与 openclaw-env 一致)。
# ============================================================================
set -e
INSTALL_PREFIX="/opt/openclaw/node"
BUILD_MODE="${BUILD_MODE:-apk}"
DEFAULT_VERIFY_PREFIX="/opt/openclaw/node"
CUSTOM_VERIFY_PREFIX="/tmp/custom-openclaw-root/openclaw/node"
SYSTEM_MUSL_LOADER="/lib/ld-musl-aarch64.so.1"
RELATIVE_RPATH='$ORIGIN/../lib'
echo "=== Node.js ARM64 musl Build ==="
echo " Target version: v${NODE_VER}"
@@ -198,10 +200,10 @@ finalize_package() {
# 用 patchelf 修改 node 二进制
echo "=== Patching ELF binary ==="
patchelf --set-interpreter "${INSTALL_PREFIX}/lib/ld-musl-aarch64.so.1" "${PKG_DIR}/bin/node"
patchelf --set-rpath "${INSTALL_PREFIX}/lib" "${PKG_DIR}/bin/node"
echo " interpreter: ${INSTALL_PREFIX}/lib/ld-musl-aarch64.so.1"
echo " rpath: ${INSTALL_PREFIX}/lib"
patchelf --set-interpreter "/lib/ld-musl-aarch64.so.1" "${PKG_DIR}/bin/node"
patchelf --set-rpath "$RELATIVE_RPATH" "${PKG_DIR}/bin/node"
echo " interpreter: ${SYSTEM_MUSL_LOADER}"
echo " rpath: ${RELATIVE_RPATH}"
# 创建 node wrapper 脚本
cat > "${PKG_DIR}/bin/node-wrapper" << 'NODEWRAPPER'
@@ -229,20 +231,27 @@ exec "${SELF_DIR}/node" "${SELF_DIR}/../lib/node_modules/npm/bin/npx-cli.js" "$@
NPXWRAPPER
chmod +x "${PKG_DIR}/bin/npm" "${PKG_DIR}/bin/npx"
# 验证
echo "=== Verification ==="
mkdir -p "${INSTALL_PREFIX}"
cp -a "${PKG_DIR}"/* "${INSTALL_PREFIX}/"
# 设置库路径并测试
export LD_LIBRARY_PATH="${INSTALL_PREFIX}/lib"
"${INSTALL_PREFIX}/bin/node" --version
"${INSTALL_PREFIX}/bin/node" -e "console.log('execPath:', process.execPath)"
"${INSTALL_PREFIX}/bin/node" -e "console.log(process.arch, process.platform, process.versions.modules)"
NODE_ICU_DATA="${INSTALL_PREFIX}/share/icu" "${INSTALL_PREFIX}/bin/npm" --version 2>/dev/null || echo "npm needs ICU data"
rm -rf "${INSTALL_PREFIX}"
verify_prefix() {
local prefix="$1"
local label="$2"
local exec_path=""
echo "=== Verification (${label}) ==="
rm -rf "$prefix" 2>/dev/null || true
mkdir -p "$prefix"
cp -a "${PKG_DIR}"/* "${prefix}/"
"${prefix}/bin/node" --version
exec_path=$("${prefix}/bin/node" -e "process.stdout.write(process.execPath)")
[ "$exec_path" = "${prefix}/bin/node" ]
"${prefix}/bin/node" -e "console.log(process.arch, process.platform, process.versions.modules)"
NODE_ICU_DATA="${prefix}/share/icu" "${prefix}/bin/npm" --version >/dev/null
rm -rf "$prefix" 2>/dev/null || true
}
verify_prefix "$DEFAULT_VERIFY_PREFIX" "default install root"
verify_prefix "$CUSTOM_VERIFY_PREFIX" "custom install root"
# 打包
echo "=== Creating tarball ==="