随着 macOS 用户数量的增长,越来越多的开发者希望将自己的桌面应用或游戏上架到 Mac App Store ,以便触达更多用户并获得官方的分发优势。但 Apple 的上架流程相比其他平台要严格得多,涉及签名、打包、沙盒、审核、公证 等环节。本文将以博文的形式,详细梳理常见跨平台框架(Flutter / Electron / Qt / Tauri / Python)以及游戏引擎(Unity / Unreal / Godot)的 打包、签名、公证与上架流程。
A. Mac App Store 与非商店分发的区别
1. Mac App Store (MAS)
- 分发产物:
.pkg
(Product Archive) - 必须:App 沙盒 + 正确的签名(Apple Distribution / 3rd Party Mac Developer Installer)
- 上传方式:Transporter (GUI)、Xcode Organizer 或 iTMSTransporter CLI
- 公证(Notarization):不需要开发者自己跑,Apple 在审核过程中会自动完成。
2. 非商店分发(官网直下 / 第三方渠道)
- 分发产物:
.dmg
/.zip
/.pkg
- 必须:Developer ID 签名 + Hardened Runtime
- 还需:Notarization 公证 + Stapler 钉票,才能通过 Gatekeeper 校验。
B. 核心步骤总览
Mac App Store 流程
- 生成
.app
- 签名(Apple Distribution)
- 打包
.pkg
(productbuild) - Transporter / Xcode 上传 App Store Connect
非商店分发流程
- 生成
.app
- 签名(Developer ID Application + Hardened Runtime)
- 打包(
.dmg
/.zip
/.pkg
) notarytool submit
公证stapler staple
钉票spctl --assess
自测
C. 各平台构建方式
1) Flutter(macOS 桌面)
bash
flutter config --enable-macos-desktop
flutter build macos --release
# 输出: build/macos/Build/Products/Release/MyApp.app
- MAS:签名 →
productbuild
→ Transporter 上传 - 非商店:签名 → 打包
.dmg
/.pkg
→ 公证 + stapler
2) Electron
bash
# MAS 构建
electron-builder --mac mas
# 非商店构建 (DMG)
electron-builder --mac dmg
- 提供
entitlements.mas.plist
/entitlements.mas.inherit.plist
- MAS 签名 & 沙盒要求较高
3) Qt(C++ / PyQt / PySide)
bash
# 生成 .app
depoyqt MyApp.app -appstore-compliant
- MAS:签名 → productbuild → Transporter 上传
- 非商店:签名 → dmg/pkg → 公证
4) Tauri
bash
cargo tauri build
- 输出 universal2
.app
- MAS / 非商店均按签名 & 打包流程继续
5) Python(PyInstaller / py2app)
bash
# PyInstaller universal2
pyinstaller --windowed --target-arch universal2 main.py
# 输出 dist/MyApp.app
# py2app\python3
setup.py py2app
- MAS:签名(Apple Distribution)→ productbuild → Transporter
- 非商店:签名(Developer ID)→ dmg/pkg → 公证
6) Unity
bash
# Build Settings → Platform: macOS → Build
# 输出: MyGame.app
- MAS:签名
.app
→productbuild
→ Transporter - 非商店:签名 → 打包
.dmg
→ 公证 + stapler
7) Unreal Engine
bash
# File → Package Project → macOS
# 输出: MyUnrealGame.app
- 后续步骤与 Unity 相同
8) Godot
bash
# Editor → Export → macOS → MyGodotGame.zip
- MAS:解压 zip → 签名
.app
→ productbuild - 非商店:签名 → zip/dmg → 公证
D. 签名与打包命令示例
签名(MAS - Apple Distribution)
bash
codesign --deep --force --timestamp \
--entitlements Entitlements.plist \
--sign "Apple Distribution: Your Name (TEAMID)" \
"MyApp.app"
productbuild \
--component "MyApp.app" /Applications \
--product "MyApp.app/Contents/Info.plist" \
--sign "3rd Party Mac Developer Installer: Your Name (TEAMID)" \
"MyApp.pkg"
签名(非商店 - Developer ID + Hardened Runtime)
bash
codesign --deep --force --timestamp \
--options runtime \
--entitlements Entitlements.plist \
--sign "Developer ID Application: Your Name (TEAMID)" \
"MyApp.app"
公证 + Staple
bash
xcrun notarytool submit MyApp.dmg \
--apple-id "your@appleid.com" \
--team-id "TEAMID" \
--password "app-specific-password" \
--wait
xcrun stapler staple MyApp.dmg
spctl --assess --type install -vv MyApp.dmg
E. 常见 Entitlements 配置(MAS 必须)
xml
<dict>
<key>com.apple.security.app-sandbox</key><true/>
<key>com.apple.security.network.client</key><true/>
<key>com.apple.security.files.user-selected.read-write</key><true/>
</dict>
F. 审核前自检清单
- ✅ App 使用 Universal Binary (x86_64 + arm64)
- ✅ 正确的 版本号 与 分类 (LSApplicationCategoryType)
- ✅ 沙盒权限最小化
- ✅ 签名验证通过 (
codesign -dv
,pkgutil --check-signature
) - ✅ (非商店)公证 + stapler 成功
总结
- 上架 MAS :签名(Apple Distribution)→
productbuild
→ Transporter → 审核(Apple 自动公证) - 非商店分发 :签名(Developer ID + Hardened Runtime)→ 打包 → 公证 (
notarytool
) → stapler → Gatekeeper 校验
掌握这些步骤,你就能让 Flutter 应用、Electron 桌面端、Qt 工具、Tauri 应用、Python 应用,甚至 Unity/Unreal/Godot 游戏,顺利通过 Apple 的严格审查,上架 Mac App Store 或安全分发给用户。