#!/bin/bash
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
BUILD_IMAGE="${BUILD_IMAGE:-yuanrong/builder:arm64}"
CONTAINER_NAME_PREFIX="yr-builder"
MAC_SSH_PORT="${MAC_SSH_PORT:-2222}"
OUTPUT_DIR="${PROJECT_ROOT}/output"
print_usage() {
cat << EOF
使用方法: bash $0 [command] [target]
命令:
setup - 设置构建环境 (拉取镜像等)
build - 执行构建 (默认)
shell - 进入构建容器 shell
clean - 清理构建容器
exec - 在容器中执行自定义命令
构建目标 (与 make all 相同):
all - 构建所有组件 (默认)
frontend - 仅构建 frontend
datasystem - 仅构建 datasystem
functionsystem - 仅构建 functionsystem
runtime_launcher - 仅构建 runtime_launcher
dashboard - 仅构建 dashboard
yuanrong - 仅构建 yuanrong
环境变量:
BUILD_IMAGE - 指定构建镜像 (默认: yuanrong/builder:arm64)
MAC_SSH_PORT - SSH 端口 (默认: 2222)
示例:
# 首次使用 - 设置环境
$0 setup
# 构建所有组件
$0 build all
# 只构建 functionsystem
$0 build functionsystem
# 进入容器调试
$0 shell
# 清理容器
$0 clean
EOF
}
check_docker() {
if ! command -v docker &> /dev/null; then
echo "错误: Docker 未安装"
echo "请在 macOS 上安装 Docker Desktop: https://www.docker.com/products/docker-desktop"
exit 1
fi
if ! docker info &> /dev/null; then
echo "错误: Docker 未运行,请启动 Docker Desktop"
exit 1
fi
echo "✓ Docker 可用"
}
get_container_name() {
echo "${CONTAINER_NAME_PREFIX}-$$"
}
check_image() {
if docker image inspect "${BUILD_IMAGE}" &> /dev/null; then
echo "✓ 构建镜像存在: ${BUILD_IMAGE}"
return 0
else
echo "✗ 构建镜像不存在: ${BUILD_IMAGE}"
return 1
fi
}
cmd_setup() {
echo "=== Docker ARM64 构建环境设置 ==="
echo ""
check_docker
echo ""
echo "检查构建镜像..."
if check_image; then
echo "镜像已存在,跳过拉取"
echo "如需更新镜像,请执行: docker pull ${BUILD_IMAGE}"
else
echo "正在拉取构建镜像..."
echo "镜像: ${BUILD_IMAGE}"
echo ""
echo "如果镜像不存在,请先构建或推送镜像:"
echo " docker build -t ${BUILD_IMAGE} -f path/to/Dockerfile ."
echo " # 或从 registry 拉取"
echo " docker pull ${BUILD_IMAGE}"
echo ""
read -p "按回车继续,或 Ctrl+C 退出..."
fi
mkdir -p "${OUTPUT_DIR}"
echo ""
echo "=== 设置完成 ==="
echo "构建镜像: ${BUILD_IMAGE}"
echo "项目目录: ${PROJECT_ROOT}"
echo "输出目录: ${OUTPUT_DIR}"
echo ""
echo "现在可以运行: $0 build [target]"
}
run_build_container() {
local target="${1:-all}"
local container_name=$(get_container_name)
local workspace="/workspace"
echo "=== Docker ARM64 构建 ==="
echo "目标: ${target}"
echo "镜像: ${BUILD_IMAGE}"
echo "容器: ${container_name}"
echo ""
local docker_opts=(
--rm
--name "${container_name}"
--platform linux/arm64
-v "${PROJECT_ROOT}:${workspace}"
-w "${workspace}"
-e "BUILD_VERSION=${BUILD_VERSION:-v0.0.1}"
-e "JOBS=${JOBS:-$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)}"
-e "GO111MODULE=on"
-e "CGO_ENABLED=1"
-e "GOOS=linux"
-e "GOARCH=arm64"
)
if [ -n "${GOPROXY}" ]; then
docker_opts+=(-e "GOPROXY=${GOPROXY}")
fi
echo "开始构建..."
echo "docker run ${docker_opts[*]} ${BUILD_IMAGE} make ${target}"
echo ""
docker run "${docker_opts[@]}" "${BUILD_IMAGE}" \
bash -c "
echo '=== 容器信息 ==='
uname -a
echo 'CPU: '\$(nproc) cores
echo ''
echo '=== 开始构建 ${target} ==='
make ${target} -j\${JOBS}
"
echo ""
echo "=== 构建完成 ==="
echo "产物位置: ${OUTPUT_DIR}/"
ls -la "${OUTPUT_DIR}/" 2>/dev/null || echo "暂无输出文件"
}
cmd_shell() {
local container_name="${CONTAINER_NAME_PREFIX}-shell"
local workspace="/workspace"
echo "=== 进入构建容器 Shell ==="
echo "输入 'exit' 退出"
echo ""
if docker ps --filter "name=${container_name}" --format '{{.Names}}' | grep -q "^${container_name}$"; then
echo "已存在运行中的容器,正在连接..."
docker exec -it "${container_name}" bash
else
echo "启动新容器..."
docker run -it --rm \
--name "${container_name}" \
--platform linux/arm64 \
-v "${PROJECT_ROOT}:${workspace}" \
-w "${workspace}" \
-e "GO111MODULE=on" \
-e "GOPROXY=${GOPROXY:-https://goproxy.cn,direct}" \
"${BUILD_IMAGE}" \
bash
fi
}
cmd_clean() {
echo "=== 清理构建容器 ==="
echo ""
local containers=$(docker ps -a --filter "name=${CONTAINER_NAME_PREFIX}" --format '{{.Names}}')
if [ -n "$containers" ]; then
echo "删除容器:"
echo "$containers"
echo "$containers" | xargs docker rm -f
else
echo "没有需要清理的容器"
fi
echo ""
echo "=== 清理完成 ==="
}
cmd_exec() {
shift
if [ $# -eq 0 ]; then
echo "错误: 请指定要执行的命令"
echo "示例: $0 exec bash -c 'pwd && ls'"
exit 1
fi
local workspace="/workspace"
docker run --rm -it \
--platform linux/arm64 \
-v "${PROJECT_ROOT}:${workspace}" \
-w "${workspace}" \
"${BUILD_IMAGE}" \
"$@"
}
main() {
local command="${1:-build}"
shift || true
case "${command}" in
setup)
cmd_setup
;;
build)
check_docker
run_build_container "$@"
;;
shell)
check_docker
cmd_shell
;;
clean)
check_docker
cmd_clean
;;
exec)
check_docker
cmd_exec "$@"
;;
help|-h|--help)
print_usage
;;
*)
echo "错误: 未知命令 '${command}'"
echo ""
print_usage
exit 1
;;
esac
}
main "$@"