Files
claude-code/packaging/build-dist.sh
T
abel533andCopilot f9072534ef feat: jlink打包脚本 - 创建最小JRE发行版(Windows/Linux/macOS)
- packaging/build-dist.ps1: PowerShell跨平台构建脚本
- packaging/build-dist.sh: Bash构建脚本
- BUILD.md: 完整构建安装指南
- 自动jdeps分析 + jlink精简JRE(~49MB)+ fat jar + 启动脚本
- 发行包约120MB,免安装JDK直接运行
- 删除旧run.bat/run.ps1

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-03 00:27:40 +08:00

181 lines
5.1 KiB
Bash
Raw Permalink 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.
#!/usr/bin/env bash
#
# 构建 Claude Code Java 发行版(jlink 最小 JRE + fat jar
#
# 用法:
# ./packaging/build-dist.sh # 使用 JAVA_HOME
# JAVA_HOME=/path/to/jdk25 ./packaging/build-dist.sh # 指定 JDK
# ./packaging/build-dist.sh --skip-build # 跳过 Maven 构建
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
OUTPUT_DIR="${OUTPUT_DIR:-dist}"
SKIP_BUILD=false
for arg in "$@"; do
case "$arg" in
--skip-build) SKIP_BUILD=true ;;
--help|-h)
echo "Usage: $0 [--skip-build]"
echo " Environment: JAVA_HOME (required), OUTPUT_DIR (default: dist)"
exit 0 ;;
esac
done
# ─── 验证环境 ───
if [ -z "${JAVA_HOME:-}" ] || [ ! -x "$JAVA_HOME/bin/java" ]; then
echo "Error: JAVA_HOME not set or JDK not found."
echo " export JAVA_HOME=/path/to/jdk-25"
exit 1
fi
export PATH="$JAVA_HOME/bin:$PATH"
JAVA_VERSION=$("$JAVA_HOME/bin/java" --version 2>&1 | head -1)
echo ""
echo " Claude Code Java - Distribution Builder"
echo " ========================================"
echo " JDK: $JAVA_VERSION"
echo " Output: $OUTPUT_DIR"
# 检测平台
OS="$(uname -s)"
ARCH="$(uname -m)"
case "$OS" in
Darwin)
PLATFORM="macos-$([ "$ARCH" = "arm64" ] && echo "aarch64" || echo "x64")" ;;
Linux)
PLATFORM="linux-$([ "$ARCH" = "aarch64" ] && echo "aarch64" || echo "x64")" ;;
*)
PLATFORM="unknown-$OS-$ARCH" ;;
esac
echo " Platform: $PLATFORM"
echo ""
cd "$PROJECT_ROOT"
# ─── Step 1: Maven 构建 ───
if [ "$SKIP_BUILD" = false ]; then
echo "[1/4] Building fat jar with Maven..."
mvn package -q -DskipTests
echo " OK Build succeeded"
else
echo "[1/4] Skipping build (using existing jar)"
fi
JAR_FILE=$(find target -maxdepth 1 -name "*.jar" ! -name "*original*" | head -1)
if [ -z "$JAR_FILE" ]; then
echo "Error: No jar found in target/. Run without --skip-build."
exit 1
fi
JAR_SIZE=$(du -m "$JAR_FILE" | cut -f1)
echo " Jar: $(basename "$JAR_FILE") (${JAR_SIZE} MB)"
# ─── Step 2: jdeps 分析 ───
echo "[2/4] Analyzing module dependencies with jdeps..."
DETECTED=$("$JAVA_HOME/bin/jdeps" --print-module-deps --ignore-missing-deps --multi-release 25 "$JAR_FILE" 2>/dev/null || echo "")
if [ -z "$DETECTED" ]; then
echo " Warning: jdeps failed, using defaults"
DETECTED="java.base,java.desktop,java.management,java.net.http"
fi
echo " Detected: $DETECTED"
# 追加 Spring Boot 运行时模块
EXTRA="java.naming,java.xml,java.sql,java.instrument,java.compiler,java.scripting,jdk.unsupported,jdk.crypto.ec,jdk.zipfs,jdk.jfr,jdk.net"
ALL_MODULES=$(echo "$DETECTED,$EXTRA" | tr ',' '\n' | sort -u | tr '\n' ',' | sed 's/,$//')
echo " Final: $ALL_MODULES"
# ─── Step 3: jlink ───
echo "[3/4] Creating minimal JRE with jlink..."
DIST_DIR="$PROJECT_ROOT/$OUTPUT_DIR"
RUNTIME_DIR="$DIST_DIR/runtime"
rm -rf "$DIST_DIR"
mkdir -p "$DIST_DIR"
"$JAVA_HOME/bin/jlink" \
--add-modules "$ALL_MODULES" \
--output "$RUNTIME_DIR" \
--strip-debug \
--compress zip-6 \
--no-header-files \
--no-man-pages
RUNTIME_SIZE=$(du -sm "$RUNTIME_DIR" | cut -f1)
echo " OK Runtime: ${RUNTIME_SIZE} MB"
# ─── Step 4: 组装 ───
echo "[4/4] Assembling distribution..."
# lib/
mkdir -p "$DIST_DIR/lib"
cp "$JAR_FILE" "$DIST_DIR/lib/claude-code-java.jar"
# bin/
mkdir -p "$DIST_DIR/bin"
# Unix launcher
cat > "$DIST_DIR/bin/claude-code" << 'LAUNCHER'
#!/bin/sh
SCRIPT="$0"
while [ -L "$SCRIPT" ]; do
DIR="$(cd "$(dirname "$SCRIPT")" && pwd)"
SCRIPT="$(readlink "$SCRIPT")"
[ "${SCRIPT#/}" = "$SCRIPT" ] && SCRIPT="$DIR/$SCRIPT"
done
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT")" && pwd)"
APP_HOME="$(cd "$SCRIPT_DIR/.." && pwd)"
exec "$APP_HOME/runtime/bin/java" \
--enable-preview \
--enable-native-access=ALL-UNNAMED \
--sun-misc-unsafe-memory-access=allow \
-Xmx512m \
-Djava.net.preferIPv4Stack=true \
-Dstdout.encoding=UTF-8 \
-Dstderr.encoding=UTF-8 \
-Dfile.encoding=UTF-8 \
-jar "$APP_HOME/lib/claude-code-java.jar" \
"$@"
LAUNCHER
chmod +x "$DIST_DIR/bin/claude-code"
# Windows launcher
cat > "$DIST_DIR/bin/claude-code.cmd" << 'LAUNCHER'
@echo off
setlocal enabledelayedexpansion
chcp 65001 >nul 2>&1
set "SCRIPT_DIR=%~dp0"
set "APP_HOME=%SCRIPT_DIR%.."
"%APP_HOME%\runtime\bin\java.exe" ^
--enable-preview ^
--enable-native-access=ALL-UNNAMED ^
--sun-misc-unsafe-memory-access=allow ^
-Xmx512m ^
-Djava.net.preferIPv4Stack=true ^
-Dstdout.encoding=UTF-8 ^
-Dstderr.encoding=UTF-8 ^
-Dfile.encoding=UTF-8 ^
-jar "%APP_HOME%\lib\claude-code-java.jar" ^
%*
LAUNCHER
# 统计
TOTAL_SIZE=$(du -sm "$DIST_DIR" | cut -f1)
echo ""
echo " Distribution built successfully!"
echo " ================================"
echo " Location : $DIST_DIR"
echo " Size : ${TOTAL_SIZE} MB (Runtime ${RUNTIME_SIZE} MB + Jar ${JAR_SIZE} MB)"
echo " Platform : $PLATFORM"
echo ""
echo " Quick start:"
echo " export AI_API_KEY=your-key"
echo " $DIST_DIR/bin/claude-code"
echo ""
echo " Or add to PATH:"
echo " export PATH=\"$DIST_DIR/bin:\$PATH\""
echo ""