三端打包
PPX 把重复的 PyInstaller 和安装器配置收进 ppx-py。应用开发者维护业务、配置和图片,框架在构建时生成其余文件。
打包前准备
先确认:
ppx doctor
pnpm -C gui run build至少检查:
ppx.toml中的名称、版本、标识符和开发者信息正确;python.modules包含所有业务入口;api/requirements.txt中的业务依赖已安装;ppx/assets/中四张必要图片存在;- 当前平台安装器工具已安装;
- GUI 的生产构建可以完成。
不要等到正式发布当天才第一次运行 PyInstaller。动态导入、原生库和模型资源的问题通常只有打包后才能发现。
调试构建与正式构建
ppx build --console # 调试应用
ppx build # 正式应用、安装包、自动校验--console 保留控制台,方便观察 Python 导入错误、缺失动态库和业务异常。它只生成当前平台应用,不继续制作正式安装器。
正式构建在应用成功后继续制作安装包,并执行当前平台可用的基础校验。正式构建失败会返回非零退出码。
构建过程
构建顺序固定为:
- 执行
pnpm -C gui run build; - 在
build/cache/生成框架内部入口ppx_entry.py; - 根据当前平台生成 PyInstaller spec;
- 把 GUI 产物映射到包内
web/; - 把
api/resources/映射到包内resources/; - 收集
ppx.toml和python.modules中的业务模块; - 生成当前系统可执行应用;
- 正式模式继续生成安装器;
- 校验安装包文件存在、大小和格式头,macOS 额外运行
hdiutil verify。
框架不会把 api/requirements.txt 本身当成运行依赖安装。必须先在打包使用的虚拟环境中执行 ppx init。
开发者需要维护的文件
开发者只维护 ppx.toml 与 ppx/assets/。Windows 使用 logo.ico 和系统安装的 Inno Setup 6;macOS 使用 logo.icns、dmg-background.png 和 dmgbuild,完成后调用 hdiutil 校验;Linux 使用 logo.png 和 dpkg-deb。spec、iss、DMG 配置、control 与 desktop 文件都由 ppx-py 临时生成。
构建缓存可以删除,不应作为业务源码修改:
build/cache/
├── ppx_entry.py
├── ppx.spec
├── installer.iss # Windows
├── dmg_settings.py # macOS
└── deb/ # Linux如果需要新的通用打包能力,应修改 ppx-py 并补测试;不要把缓存文件复制回普通项目作为长期模板。
用一张主图生成三端图标
不需要分别制作三种图标。准备一张至少 512×512 的方形 PNG、JPEG 或 WebP 主图;需要透明背景时使用 PNG 或 WebP。然后运行:
ppx icon ./app-icon.pngPPX 会在 ppx/assets/ 生成 1024 像素 PNG、多尺寸 ICO 和 ICNS。dmg-background.png 及其他业务图片不会被覆盖;建议把设计主图保存在 ppx/assets/ 之外。
Pillow 只用于执行 ppx icon。PPX 的打包配置会跳过 Pygments 中未使用的图片格式化器,避免仅仅因为图标工具就把整套 Pillow 收进成品;如果你的 api/ 业务代码主动导入 Pillow,PyInstaller 仍会识别并完整收集它。
Windows
要求
- Windows 构建机;
- Python、Node、pnpm 和项目依赖;
- Inno Setup 6;
- 用于运行页面的 WebView2 Runtime。
PyInstaller 先生成应用目录,Inno Setup 再生成:
build/应用名-V版本_Windows.exeproject.windowsAppId 决定安装器是否把新版本识别为同一应用。脚手架会生成 GUID;应用发布后不要更改。发布前应在普通用户和管理员环境分别测试安装、覆盖、卸载和桌面快捷方式。
基础校验只检查输出存在、大小合理和 MZ 文件头,不能替代真实安装、代码签名和 SmartScreen 测试。
macOS
PyInstaller 生成:
build/应用名.app正式构建继续生成:
build/应用名-V版本_macOS.dmgDMG 使用 logo.icns 和 dmg-background.png,并放置指向 /Applications 的快捷方式。完成后运行 hdiutil verify 检查镜像结构和校验和。
PyInstaller 的临时签名或 codesign --verify 通过,不等于可以公开分发。正式发布通常还需要:
- Apple Developer ID Application 证书;
- 对
.app及嵌套内容正确签名; - 提交 Apple 公证;
- stapler 附加公证票据;
- 在一台没有开发环境的 Mac 上测试 Gatekeeper。
还要分别考虑 Apple Silicon 和 Intel 架构。当前机器生成的应用不会自动变成另一架构版本。
Linux
Linux 使用 PyInstaller 单文件模式,再放入 Debian 包:
build/应用名-V版本_Linux.deb构建机需要 GTK3、WebKitGTK、PyGObject 和 dpkg-deb。包会把应用安装到 /opt/<slug>/bin/,生成 desktop 文件和图标。
可先检查包内容:
dpkg-deb --info build/*_Linux.deb
dpkg-deb --contents build/*_Linux.debLinux 二进制对 glibc 和系统 WebKitGTK 比较敏感。尽量在目标发行版或更旧的兼容基线构建,并至少选择一个干净系统安装测试。
为什么不能在一个系统打出全部安装包?
PyInstaller 不是通用交叉编译器。Windows 应用依赖 Windows 引导程序和 DLL,macOS 依赖 Mach-O、应用 bundle 和签名,Linux 依赖 ELF 与发行版系统库。
正确做法是使用三端 CI:
同一 Git 提交
├── windows-latest → Windows.exe
├── macos-latest → macOS.dmg
└── ubuntu-latest → Linux.deb三个任务必须使用同一应用版本和锁文件。任何一个平台失败,都不要发布“部分成功”的正式版本。
业务资源和第三方模块
python.modules 中声明的入口会作为 hidden imports 收集。业务资源放入 api/resources/,代码使用 resource_path() 访问。
第三方库如果在运行时动态导入插件,PyInstaller 可能无法自动识别。排查顺序:
- 用
ppx build --console查看缺失模块名; - 确认模块安装在当前虚拟环境;
- 检查第三方库官方 PyInstaller hook;
- 在框架层增加通用 hook/hidden import 支持;
- 为该场景增加打包后启动测试。
不要为了修一个缺失模块,无选择地收集整个 Python 环境;这会显著增加包体和隐藏不必要依赖。
输出文件
默认正式安装包名称:
应用名-V应用版本_Windows.exe
应用名-V应用版本_macOS.dmg
应用名-V应用版本_Linux.deb版本来自 [project].version,不是 PPX 框架版本。
发布前真机验收
发布前还要在真机完成:安装/卸载、首次启动、Python RPC、文件选择、存储、业务资源读取、升级覆盖、代码签名与系统安全提示检查。CI 构建成功不能替代真机验收。
建议按以下顺序验收:
- 在无源码、无开发依赖的干净机器安装;
- 第一次启动并完成核心 RPC;
- 测试打开/保存文件与目录选择;
- 写入存储并重启验证;
- 读取至少一个
api/resources/文件; - 从上一版本覆盖升级;
- 确认用户数据仍存在;
- 测试卸载和残留策略;
- 检查系统安全提示和签名信息;
- 记录产物 SHA-256。
发布流程继续阅读 CI 与发布。