将跨平台框架或游戏引擎开发的 macOS 应用上架 Mac App Store

随着 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 OrganizeriTMSTransporter CLI
  • 公证(Notarization):不需要开发者自己跑,Apple 在审核过程中会自动完成。

2. 非商店分发(官网直下 / 第三方渠道)

  • 分发产物:.dmg / .zip / .pkg
  • 必须:Developer ID 签名 + Hardened Runtime
  • 还需:Notarization 公证 + Stapler 钉票,才能通过 Gatekeeper 校验。

B. 核心步骤总览

Mac App Store 流程

  1. 生成 .app
  2. 签名(Apple Distribution)
  3. 打包 .pkg(productbuild)
  4. Transporter / Xcode 上传 App Store Connect

非商店分发流程

  1. 生成 .app
  2. 签名(Developer ID Application + Hardened Runtime)
  3. 打包(.dmg / .zip / .pkg
  4. notarytool submit 公证
  5. stapler staple 钉票
  6. 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:签名 .appproductbuild → 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 或安全分发给用户。