build_mac_universal.sh
5.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#!/bin/bash
# macOS Build Script - Universal (Intel + Apple Silicon)
# 自动检测架构,自动安装依赖
set -e # 遇错即停
echo "================================"
echo "Building Gemini Image Generator"
echo "================================"
# 检测架构
ARCH=$(uname -m)
echo "Detected architecture: $ARCH"
# 设置 Homebrew 路径
if [ "$ARCH" = "arm64" ]; then
BREW_PREFIX="/opt/homebrew"
else
BREW_PREFIX="/usr/local"
fi
# 检查 Homebrew 是否安装
if ! command -v brew &> /dev/null; then
echo "Homebrew not found. Installing..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 添加到当前 shell 的 PATH
eval "$($BREW_PREFIX/bin/brew shellenv)"
fi
# 确保 brew 在 PATH 中
if ! command -v brew &> /dev/null; then
eval "$($BREW_PREFIX/bin/brew shellenv)"
fi
# 检查 Python 3.11 是否安装
PYTHON_CMD="$BREW_PREFIX/bin/python3.11"
if [ ! -f "$PYTHON_CMD" ]; then
echo "Python 3.11 not found. Installing via Homebrew..."
brew install python@3.11
fi
# 验证 Python 可用
if [ ! -f "$PYTHON_CMD" ]; then
echo "Error: Failed to install Python 3.11"
exit 1
fi
echo "Using Python: $PYTHON_CMD"
$PYTHON_CMD --version
# 检查虚拟环境是否有效(macOS 用 bin/activate,Windows 用 Scripts/activate)
if [ ! -f ".venv/bin/activate" ]; then
echo "Valid virtual environment not found, creating..."
rm -rf .venv
"$PYTHON_CMD" -m venv .venv
fi
# 激活虚拟环境
echo "Activating virtual environment..."
source .venv/bin/activate
# 安装依赖
echo "Installing dependencies..."
pip install --upgrade pip
pip install -r requirements.txt
pip install pyinstaller
# 清理旧构建 (保留 spec 文件,它是构建配置的唯一真相源)
echo "Cleaning previous builds..."
rm -rf build dist
# 构建 (所有配置都在 ZB100ImageGenerator.spec 里)
echo "Building executable..."
pyinstaller ZB100ImageGenerator.spec
# 验证 .app 构建结果
if [ ! -d "dist/ZB100ImageGenerator.app" ]; then
echo "================================"
echo "Build failed! (.app not produced)"
echo "================================"
exit 1
fi
# 打包 DMG 作为分发格式 (带 drag-to-install 布局)
# 为什么必须: .app 里有嵌套 symlink (PIL/.dylibs -> __dot__dylibs),
# cp/NAS/SMB/微信 等传输方式可能吞掉内层 symlink 导致目标机启动失败.
# .dmg 是 HFS+ 镜像, symlink 原样保存, 用户挂载拖拽即用.
echo "Creating DMG with drag-to-install layout..."
DMG_PATH="dist/ZB100ImageGenerator.dmg"
TMP_DMG="dist/.tmp_rw.dmg"
STAGE="dist/.dmg_stage"
VOL_NAME="ZB100ImageGenerator"
# 1. 准备 staging: .app + Applications 快捷方式
rm -rf "$STAGE"
mkdir -p "$STAGE"
cp -R "dist/ZB100ImageGenerator.app" "$STAGE/"
ln -s /Applications "$STAGE/Applications"
# 2. 先卸载可能残留的同名卷, 防止上次失败留下的挂载
hdiutil detach "/Volumes/$VOL_NAME" -force >/dev/null 2>&1 || true
# 3. 创建可写 DMG (UDRW), 便于随后调整窗口布局
rm -f "$TMP_DMG" "$DMG_PATH"
hdiutil create \
-volname "$VOL_NAME" \
-srcfolder "$STAGE" \
-ov -format UDRW \
"$TMP_DMG"
# 4. 挂载并用 AppleScript 布置窗口 (.app 在左, Applications 在右)
MOUNT_POINT="/Volumes/$VOL_NAME"
hdiutil attach "$TMP_DMG" -readwrite -noverify -noautoopen >/dev/null
# osascript 失败不致命 (可能因 Finder 自动化权限), DMG 仍然可用, 只是没布局
osascript <<OSASCRIPT_EOF || echo "Warning: Finder 布局失败 (可能需要授予 Finder 自动化权限), DMG 仍可用"
tell application "Finder"
tell disk "$VOL_NAME"
open
set current view of container window to icon view
set toolbar visible of container window to false
set statusbar visible of container window to false
set the bounds of container window to {200, 120, 800, 470}
set theViewOptions to the icon view options of container window
set arrangement of theViewOptions to not arranged
set icon size of theViewOptions to 128
set position of item "ZB100ImageGenerator.app" of container window to {160, 170}
set position of item "Applications" of container window to {440, 170}
update without registering applications
delay 1
close
end tell
end tell
OSASCRIPT_EOF
sync
hdiutil detach "$MOUNT_POINT" -force >/dev/null
# 5. 压缩成最终只读 DMG
hdiutil convert "$TMP_DMG" -format UDZO -imagekey zlib-level=9 -o "$DMG_PATH" >/dev/null
# 6. 清理临时
rm -f "$TMP_DMG"
rm -rf "$STAGE"
if [ ! -f "$DMG_PATH" ]; then
echo "================================"
echo "Build partially failed: .app OK but DMG creation failed"
echo "================================"
exit 1
fi
echo "================================"
echo "Build successful!"
echo "Architecture: $ARCH"
echo " App: dist/ZB100ImageGenerator.app ($(du -sh dist/ZB100ImageGenerator.app | awk '{print $1}'))"
echo " DMG: $DMG_PATH ($(du -sh "$DMG_PATH" | awk '{print $1}'))"
echo "================================"
echo "分发请用 DMG, 不要直接拷贝 .app 目录 (symlink 易丢)."