#!/usr/bin/env bash # 打包 macOS 完整客户端(登录 → 选人 → 进游戏)。 # # ./build-macos-client.sh [debug|release] # # 产物:build/export/mtgodot-poc.app(40250 Client/pack 和 BGM 自包含)。 # 依赖:Godot 4.7.1 的 macOS 导出模板(editor 里 “管理导出模板” 装,或放 # ~/Library/Application Support/Godot/export_templates/4.7.1.stable/macos.zip)。 set -euo pipefail cd "$(dirname "$0")" REPO="$(pwd)" SOURCE_CLIENT="${MT_40250_CLIENT:-$REPO/Client}" if [ ! -f "$SOURCE_CLIENT/pack/Index" ] && [ -f "$REPO/../40250/Server Client TMP4/Client/pack/Index" ]; then SOURCE_CLIENT="$REPO/../40250/Server Client TMP4/Client" fi CFG="${1:-debug}" OUT="${MT_MAC_OUTPUT_DIR:-$REPO/build/export}" APP="$OUT/mtgodot-poc.app" GODOT="${GODOT:-godot}" MAC_ARCHES="${MT_MAC_ARCHES:-universal}" ENGINE_OVERRIDE="${MT_MAC_ENGINE:-}" test -f "$SOURCE_CLIENT/pack/Index" || { echo "错误:缺少 40250 Client/pack/Index:$SOURCE_CLIENT" >&2 exit 1 } if [ -n "$ENGINE_OVERRIDE" ]; then test -x "$ENGINE_OVERRIDE" ENGINE_INFO="$(lipo -info "$ENGINE_OVERRIDE")" case "$MAC_ARCHES:$ENGINE_INFO" in universal:*x86_64*arm64*|universal:*arm64*x86_64*|arm64:*arm64*|x86_64:*x86_64*) ;; *) echo "错误:自定义引擎架构不匹配:$ENGINE_INFO" >&2; exit 1 ;; esac echo "自定义引擎:$ENGINE_OVERRIDE" "$ENGINE_OVERRIDE" --version fi BUILD_TYPE="Debug" if [ "$CFG" = release ]; then BUILD_TYPE="Release" fi echo "== 1. GDExtension .dylib ==" if [ "$MAC_ARCHES" = universal ]; then CMAKE_ARCHES="arm64;x86_64" else CMAKE_ARCHES="$MAC_ARCHES" fi cmake -S . -B build -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_OSX_ARCHITECTURES="$CMAKE_ARCHES" cmake --build build --target mtgodot -j8 DYLIB="project/bin/libmtgodot.macos.template_${CFG}.dylib" if [ ! -f "$DYLIB" ]; then # CMake 目前只出 debug 名;release 就复用它 cp -f project/bin/libmtgodot.macos.template_debug.dylib "$DYLIB" fi if [ "$MAC_ARCHES" = universal ]; then LIPO_INFO="$(lipo -info "$DYLIB")" case "$LIPO_INFO" in *x86_64*arm64*|*arm64*x86_64*) ;; *) echo "错误:GDExtension 不是 universal:$LIPO_INFO" >&2; exit 1 ;; esac fi echo "== 2. 导出 ==" mkdir -p "$OUT" if [ "$CFG" = release ]; then "$GODOT" --headless --path project --export-release macOS "$APP" else "$GODOT" --headless --path project --export-debug macOS "$APP" fi echo "== 3. 40250 资源(自包含)==" BUNDLE_CLIENT="$APP/Contents/Resources/40250/Client" mkdir -p "$BUNDLE_CLIENT" ditto "$SOURCE_CLIENT/pack" "$BUNDLE_CLIENT/pack" if [ -d "$SOURCE_CLIENT/BGM" ]; then ditto "$SOURCE_CLIENT/BGM" "$BUNDLE_CLIENT/BGM"; fi if [ -f "$SOURCE_CLIENT/locale.cfg" ]; then cp "$SOURCE_CLIENT/locale.cfg" "$BUNDLE_CLIENT/locale.cfg"; fi if [ -d "$SOURCE_CLIENT/sound" ]; then ditto "$SOURCE_CLIENT/sound" "$BUNDLE_CLIENT/sound" elif [ -d "$REPO/assets/Sound/sound" ]; then ditto "$REPO/assets/Sound/sound" "$BUNDLE_CLIENT/sound" fi test -s "$BUNDLE_CLIENT/pack/Index" # Record the exact source revision inside the signed bundle. A Beta release is built only # after its changes are committed, so the identity remains useful when the checkout moves on. python3 - "$REPO" "$APP/Contents/Resources/beta-build.json" <<'PY' import json, pathlib, subprocess, sys repo, output = sys.argv[1:] commit = subprocess.check_output(['git', '-C', repo, 'rev-parse', 'HEAD'], text=True).strip() dirty = bool(subprocess.check_output(['git', '-C', repo, 'status', '--porcelain', '--untracked-files=normal'], text=True).strip()) pathlib.Path(output).write_text(json.dumps({'source_commit': commit, 'source_dirty': dirty}, indent=2) + '\n') PY echo "== 4. 签名(默认 ad-hoc;CODESIGN_IDENTITY 可切正式证书)==" if [ -n "$ENGINE_OVERRIDE" ]; then cp "$ENGINE_OVERRIDE" "$APP/Contents/MacOS/mtgodot-poc" fi CODESIGN_IDENTITY="${CODESIGN_IDENTITY:--}" ENTITLEMENTS="$REPO/macos.entitlements" test -f "$ENTITLEMENTS" # The exported Godot executable loads the GDExtension from Contents/Frameworks. # Because this package uses hardened runtime, the main executable must carry # disable-library-validation or macOS rejects the ad-hoc/formally signed dylib # at runtime even when the bundle passes a static codesign verification. find "$APP/Contents/Frameworks" -type f \( -name '*.dylib' -o -name '*.so' \) -exec \ codesign --force --options runtime --timestamp=none --sign "$CODESIGN_IDENTITY" {} \; codesign --force --options runtime --timestamp=none --entitlements "$ENTITLEMENTS" \ --sign "$CODESIGN_IDENTITY" "$APP/Contents/MacOS/mtgodot-poc" codesign --force --options runtime --timestamp=none --entitlements "$ENTITLEMENTS" \ --sign "$CODESIGN_IDENTITY" "$APP" xattr -dr com.apple.quarantine "$APP" 2>/dev/null || true echo echo "OK -> $APP" echo "跑: open '$APP'" echo "开发覆盖资源:MT_ASSETS='$REPO/assets' '$APP/Contents/MacOS/mtgodot-poc'"