Appearance
text
# Related Code
build.py - PyInstaller 构建脚本
dmg_settings.py - DMG 配置
Makefile - 构建命令
pyproject.toml - 依赖配置构建系统
构建工具链
| 工具 | 用途 |
|---|---|
| PyInstaller | 打包 Python 为独立可执行文件 |
| dmgbuild | 创建 macOS DMG 安装包 |
| Makefile | 构建命令封装 |
PyInstaller 配置
build.py 主要逻辑
python
# build.py
def build_app():
PyInstaller.__main__.run([
'main.py',
'--onedir', # 目录模式(非单文件)
'--windowed', # GUI 应用,无控制台
'--name', f'HF Model Downloader-{arch}',
'--icon', icon_path,
'--add-data', 'assets:assets',
])为什么用 onedir 而非 onefile
| 模式 | 优点 | 缺点 |
|---|---|---|
| onefile | 单文件分发 | 启动慢(解压临时目录) |
| onedir | 启动快 | 多文件 |
对于 GUI 应用,启动速度更重要。
资源打包
python
# --add-data 格式:源路径:目标路径
'--add-data', 'assets:assets'运行时通过 resource_utils.py 获取正确路径:
python
# src/resource_utils.py
def get_resource_path(relative_path):
if getattr(sys, 'frozen', False):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.dirname(__file__), '..', relative_path)架构检测
python
# build.py
def get_architecture():
arch = platform.machine().lower()
if arch in ['arm64', 'aarch64']:
return 'arm64'
return 'x86_64'产物命名包含架构:
HF Model Downloader-arm64.appHF Model Downloader-x86_64.app
DMG 创建
dmg_settings.py
python
# dmg_settings.py
application = defines.get('app', 'HF Model Downloader.app')
appname = os.path.basename(application)
format = 'UDBZ' # 压缩格式
files = [application]
symlinks = {'Applications': '/Applications'}
icon_locations = {
appname: (140, 120),
'Applications': (500, 120)
}DMG 布局
┌────────────────────────────────────┐
│ │
│ [App Icon] → [Apps] │
│ │
│ 拖拽安装到 Applications │
│ │
└────────────────────────────────────┘Makefile 构建流程
make build
makefile
build:
@$(PYTHON) build.py执行 PyInstaller 打包。
make dmg
makefile
dmg: build
@cd $(DIST_DIR) && \
mv "*.app" "HF Model Downloader.app" && \
dmgbuild -s settings.py "HF Model Downloader" "$(APP_NAME)-$(ARCH_NAME).dmg"- 依赖 build 目标
- 重命名 .app(去掉架构后缀)
- 调用 dmgbuild 创建 DMG
完整构建流程
平台特定处理
macOS
python
# build.py
if sys.platform == 'darwin':
icon_path = 'assets/icon.icns'Windows
python
# build.py
if sys.platform == 'win32':
icon_path = 'assets/icon.ico'
# 额外处理 UTF-8 编码图标格式
| 平台 | 格式 | 文件 |
|---|---|---|
| macOS | .icns | assets/icon.icns |
| Windows | .ico | assets/icon.ico |
| Linux | .png | assets/icon.png |
依赖处理
隐式导入
PyInstaller 可能遗漏动态导入的模块:
python
# build.py
hiddenimports = [
'huggingface_hub',
'modelscope',
'tqdm',
]排除不需要的模块
python
excludes = [
'matplotlib',
'scipy',
'tkinter',
]减少打包体积。
构建验证
bash
# 验证构建产物
make test-build
# 检查产物大小
ls -lh dist/
# 测试运行
open dist/HF\ Model\ Downloader-arm64.app常见问题
Q: 构建后应用无法启动
检查点:
- 多进程初始化是否正确 (
freeze_support()) - 资源路径是否使用
get_resource_path() - 隐式导入是否完整
Q: 打包体积过大
优化方向:
- 排除未使用的模块
- 使用 UPX 压缩(可选)
- 检查数据文件大小
Q: DMG 创建失败
确保:
- .app 存在于 dist 目录
- dmgbuild 已安装
- macOS 系统(DMG 仅限 macOS)