#!/bin/bash # ============================================================ # OpenDance Studio —— Windows 客户端导出(在 Linux 上执行) # # 文档 §5.3 方案 A:Godot 4 支持在 Linux 上导出 Windows 可执行文件。 # # 前置: # 1. Godot 4 可执行文件(GODOT_BIN 指定,或已在 PATH 中) # 2. 已安装对应版本的 export templates # 下载:https://github.com/godotengine/godot/releases # Godot_v<版本>-stable_export_templates.tpz # 安装:解压后把 templates/* 放到 # ~/.local/share/godot/export_templates/<版本>.stable/ # # 用法:bash build/export-windows.sh [debug|release] # ============================================================ set -euo pipefail PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)" cd "$PROJECT_DIR" MODE="${1:-release}" if [ "$MODE" != "debug" ] && [ "$MODE" != "release" ]; then echo "用法:bash build/export-windows.sh [debug|release]" >&2 exit 2 fi # ---- 定位 Godot ---- GODOT_BIN="${GODOT_BIN:-}" if [ -z "$GODOT_BIN" ]; then for candidate in godot godot4 Godot; do if command -v "$candidate" >/dev/null 2>&1; then GODOT_BIN="$candidate"; break; fi done fi if [ -z "$GODOT_BIN" ]; then echo "错误:未找到 Godot 可执行文件。请安装 Godot 4 或用 GODOT_BIN=<路径> 指定。" >&2 exit 1 fi OUTPUT_DIR="$PROJECT_DIR/build/windows" mkdir -p "$OUTPUT_DIR" GODOT_VERSION="$("$GODOT_BIN" --version 2>/dev/null | head -1 || true)" echo "[export] Godot:$GODOT_BIN($GODOT_VERSION)" echo "[export] 项目:$PROJECT_DIR" echo "[export] 模式:$MODE" # ---- 导出预设必须位于项目根目录(Godot 的硬性要求)---- if [ ! -f "$PROJECT_DIR/export_presets.cfg" ]; then if [ -f "$PROJECT_DIR/build/export_presets.cfg" ]; then cp "$PROJECT_DIR/build/export_presets.cfg" "$PROJECT_DIR/export_presets.cfg" echo "[export] 已从 build/ 复制导出预设到项目根目录" else echo "错误:缺少 export_presets.cfg(Godot 要求放在项目根目录)。" >&2 exit 1 fi fi # ---- 检查导出模板 ---- TEMPLATE_DIR="${HOME}/.local/share/godot/export_templates" if [ ! -d "$TEMPLATE_DIR" ] || [ -z "$(ls -A "$TEMPLATE_DIR" 2>/dev/null)" ]; then echo "错误:未找到导出模板($TEMPLATE_DIR 为空)。" >&2 echo " 请从 https://github.com/godotengine/godot/releases 下载" >&2 echo " Godot_v<版本>-stable_export_templates.tpz 并安装到" >&2 echo " ~/.local/share/godot/export_templates/<版本>.stable/" >&2 exit 1 fi echo "[export] 导出模板:$(ls "$TEMPLATE_DIR" | tr '\n' ' ')" # ---- 导出前:把版本号同步进导出预设 ---- # export_presets.cfg 的 application/file_version / product_version 决定产物 exe 的 # PE 版本资源(Windows「右键 → 属性 → 详细信息」里显示的版本),它们**不会** # 跟随 project.godot 的 application/config/version 自动更新。不在这里同步, # 导出的包就会带着旧版本号 —— v0.2.1 正是因此显示了 0.1.0。 echo "[export] 同步版本号到导出预设…" bash "$PROJECT_DIR/build/sync-export-version.sh" || { echo "错误:导出预设版本同步失败。" >&2 exit 1 } # ---- 确保资源已导入(缺失会让导出静默产出不完整的包)---- echo "[export] 导入资源…" "$GODOT_BIN" --headless --path "$PROJECT_DIR" --import >/dev/null 2>&1 || true # ---- 导出 ---- echo "[export] 导出中…" set +e "$GODOT_BIN" --headless --path "$PROJECT_DIR" \ --export-"$MODE" "Windows Desktop" "$OUTPUT_DIR/OpenDance.exe" EXPORT_STATUS=$? set -e if [ "$EXPORT_STATUS" -ne 0 ]; then echo "[export] 导出命令返回 $EXPORT_STATUS,检查产物是否存在…" fi # ---- 校验产物 ---- EXE="$OUTPUT_DIR/OpenDance.exe" PCK="$OUTPUT_DIR/OpenDance.pck" CONSOLE="$OUTPUT_DIR/OpenDance.console.exe" MISSING=0 [ -f "$EXE" ] || { echo "错误:未生成 $EXE" >&2; MISSING=1; } [ -f "$PCK" ] || { echo "错误:未生成 $PCK" >&2; MISSING=1; } [ -f "$CONSOLE" ] || echo "[export] 提示:未生成 console 包装器(非致命)" if [ "$MISSING" -ne 0 ]; then echo "导出失败。" >&2 exit 1 fi # 校验 PE 头,确认确实是 Windows 可执行文件 MAGIC=$(head -c 2 "$EXE" | od -An -tx1 | tr -d ' \n') if [ "$MAGIC" != "4d5a" ]; then echo "错误:$EXE 不是合法的 Windows PE 文件(头 2 字节为 $MAGIC,期望 4d5a 'MZ')" >&2 exit 1 fi # 校验 PE 版本资源 = 当前项目版本(文档 §11.2:产物元数据也必须可核对) PROJECT_VERSION="$(sed -n 's/^config\/version="\(.*\)"$/\1/p' "$PROJECT_DIR/project.godot" | head -1)" echo "[export] 校验产物 PE 版本资源(期望 $PROJECT_VERSION)…" if ! bash "$PROJECT_DIR/build/check-pe-version.sh" "$EXE" "$PROJECT_VERSION"; then echo "错误:$EXE 的 PE 版本资源与项目版本不一致。" >&2 exit 1 fi SIZE_EXE=$(stat -c%s "$EXE") SIZE_PCK=$(stat -c%s "$PCK") echo "" echo "[export] 完成:" echo " $EXE ($((SIZE_EXE / 1024)) KiB, PE 头与版本资源校验通过)" echo " $PCK ($((SIZE_PCK / 1024)) KiB)" [ -f "$CONSOLE" ] && echo " $CONSOLE ($(( $(stat -c%s "$CONSOLE") / 1024 )) KiB)" echo "" echo "在 Windows 10/11 上运行 $EXE 即可(.pck 必须与 .exe 同目录)。"