跟随第一章比较路线,第二至第八章完成实践。每个示例都需要替换为项目真实参数。
目标:让开发者从一台 Windows 开发机和一台构建 Mac 出发,完成可重复的 iOS 构建,拿到最终 IPA、与它匹配的完整主程序 dSYM Bundle,以及可追溯的日志与版本记录。
实践主线:UE 5.6 C++ Game 项目 → Windows UAT → 远程 Mac 原生编译 → Windows 打包 → Shipping / Ad Hoc IPA + dSYM ZIP → macOS 核验 → 已注册真机验收。
核对日期:2026-11-11。配置和产物处理已对照 Epic 官方 5.6.1-release 源码,提交 6978b63c8951e57d97048d8424a0bebd637dde1d。命令和脚本是工程实践模板;本次没有你的 UE 项目,没有执行真实的 Windows→Mac 打包或真机验收。
Windows + 远程 Mac,与纯 macOS 构建有什么区别
iOS 原生 C++ 的编译、链接仍在 Mac。 Windows 路线的价值是把开发、资源处理和构建调度留在 Windows,由 Mac 提供 Apple 工具链能力。Windows 不会把 Visual C++ 编译出的 Win64 程序转换成 iOS 程序。[1][3]
两条路线的工作分工
| 工作 | Windows 发起 + 远程 Mac | 纯 macOS 构建 |
|---|---|---|
| UE 编辑、编辑器 / 插件构建 | Windows 编辑器 / Win64 模块 | Mac 编辑器 / Mac 模块 |
| iOS 资源 Cook | 本指南在 Windows 执行 | 在 Mac 执行,也可使用已有 Cook 数据 |
| Metal 着色器 | Windows 安装匹配工具后本地处理 | Mac 的 Apple 工具链处理 |
| iOS C++ 编译、链接 | 远程 Mac | 本地 Mac |
| 主程序 dSYM | Mac 生成,按 manifest 回传 Windows | Mac 生成并保留 |
| 签名材料 | Windows 导入证书私钥 / Profile;所需材料同步给 Mac | Mac 管理签名身份与 Profile |
| 最终 IPA | Windows 默认 Legacy / iPhonePackager:stub 加入 Cook 内容并按配置重新签名 | 默认 Modern Xcode 可生成归档,再导出 IPA;也可走 Legacy |
| 环境维护 | Windows UE / C++、SSH、Mac Xcode | Mac UE / C++、Xcode |
| Apple 原生调试 | Xcode 在 Mac;两端查看日志 | Xcode 与 UE 集中在 Mac |
Windows UAT 在 5.6.1 源码中默认选择 Legacy;Mac 的 Modern/Legacy 由配置与参数决定。不能把 Mac 上“Archive 后导出 IPA”的操作,直接写成 Windows Package Project 的固定后续步骤。 本指南显式传递 Legacy 参数,固定打包主机和远程编译端的路线。[3][4][5][6]
收益与成本
| 判断点 | 实际影响 |
|---|---|
| 团队主要使用 Windows | 保留 UE、VS、资源处理与多平台工作区 |
| 已有高性能 Windows 机器 | Cook / Windows Metal 能利用其资源;iOS C++ 仍受 Mac 性能限制 |
| 多名开发者共享 Mac | 能统一 Apple 工具链、复用机器;要管理并发、签名、存储和排队 |
| Mac 是否必须安装 UE | 官方说明日常远程构建不要求预装 UE / 完整项目,所需构建文件会同步过去 |
| 初次全量构建 | 多了同步与多机协调,不保证比同等性能 Mac 本地构建更快 |
| 后续增量构建 | 可复用缓存;纯 Mac 同样支持缓存与增量构建 |
| 原生 SDK / 签名错误定位 | Windows 与 Mac 两端都有日志,链路更长 |
性能取舍属于工程判断,没有固定加速倍数。比较时用相同项目、配置、资源、SDK 和冷 / 热缓存;不要拿远程缓存命中与 Mac 每次从零编译整个引擎作比较。[1][6]
选型建议: Windows 是团队主要开发平台时,使用 Windows + 主构建 Mac;个人以 iOS SDK 和 Xcode 调试为主、Mac 性能足够时,纯 macOS 通常更容易维护。下面完成 Windows 路线的全部交付步骤。
明确交付目标,准备环境与参数
第一次实践建议使用 Shipping + Ad Hoc:优化后的发布配置,Apple Distribution 签名,Profile 包含测试设备 UDID,可直接安装到这些已注册设备。先用 Development 跑通连接 / 签名,再切到 Shipping / Ad Hoc。[9][10]
| 模式 | 编译配置 | 证书 / Profile | -distribution | 用途 |
|---|---|---|---|---|
| Development | Development | Apple Development / iOS App Development | 否 | 开发和设备调试 |
| AdHoc(主线) | Shipping | Apple Distribution / Ad Hoc | 是 | 安装到 Profile 中的设备 |
| AppStore | Shipping | Apple Distribution / App Store Connect | 是 | TestFlight / App Store 提交 |
Shipping 是编译配置,-distribution 是分发打包,Profile 决定签名用途。三者要匹配。App Store Profile 的包不能当作 Ad Hoc 包直接安装。[4][9][10]
工具版本
| 机器 | 安装 / 准备 |
|---|---|
| Windows | UE 5.6,安装 iOS 平台支持;VS 2022 推荐 17.14(最低 17.8),C++ 游戏开发组件;Apple 官网版 iTunes / iOS 支持组件 |
| Windows C++ 工具链 | UE文档推荐 MSVC 14.38.33130、Windows SDK 10.0.22621.0 或更新版本,.NET 8.0 |
| Windows Metal | Apple Metal Developer Tools for Windows 4.4 |
| Mac | UE 5.6 文档推荐 Sonoma 14.7 + Xcode 16.1;最低列出 Sonoma 14.5 + Xcode 16 |
| Mac 核验 | Python 3.9+、Xcode Command Line Tools |
| Apple 团队 / 设备 | 有证书与 Profile 管理权限,至少一台登记 UDID 的 iPhone / iPad |
VS / MSVC 工具集需要满足 UE 5.6 官方兼容要求;不能只按“装了 VS”判断。.NET 组件按实际引擎安装处理。[7][8][9][11]
当前商店提交要求: Apple 自 2026-04-28 起要求上传 App Store Connect 的应用使用 Xcode 26 或更新版本和 iOS 26 等对应 SDK。Xcode 16.1 是 UE 5.6 文档基线,不能据此保证 2026 年的上架提交。若目标是当前上架,先完成 UE 5.6 分支与全部插件对所需新工具链的兼容验证,再使用本文 AppStore 模式。[13]
填好全文使用的参数
| 参数 | 示例 | 如何确定 |
|---|---|---|
| EngineRoot | C:\Epic\UE_5.6 | 内部存在 Engine\Build\BatchFiles\RunUAT.bat |
| ProjectFile | D:\UEProjects\MyGame\MyGame.uproject | 完整 .uproject 路径 |
| TargetName | MyGame | Source\MyGame.Target.cs 的 Game Target,不能填 MyGameEditor |
| BundleIdentifier | com.example.MyGame | 与 Apple App ID 完全一致 |
| Team ID | ABCDE12345 | 示例占位值,替换为真实团队 ID |
| Mac / user | 192.168.1.20 / uebuild | 可连接的地址与用户名 |
| Development Profile | MyGame_Development.mobileprovision | 实际安装的文件名 |
| Ad Hoc Profile | MyGame_AdHoc.mobileprovision | 实际安装的文件名 |
| SigningCertificate | Apple Distribution: Example Company (ABCDE12345) | UE 识别到的完整名称 |
| OutputRoot | D:\IOSDeliveries | 交付输出父目录 |
脚本针对 有自己 C++ Game Target 的普通 App。纯 Blueprint 会复用 UnrealGame 目标与符号;不要拿其他引擎版本的 dSYM 配它。要直接使用本文脚本,可先添加空 C++ 类,形成项目自己的 Game / Editor Target,并验证编辑器构建。Framework 输出、多 Target、自定义输出路径需按实际 receipt 调整。[6]
在 Mac 准备 Xcode、签名身份与 SSH
3.1 确认完整 Xcode 与 iOS SDK
打开 Xcode 完成首次启动、组件和许可证处理,安装 iOS 平台支持。在 Terminal 执行:
xcode-select -p
xcodebuild -version
xcodebuild -showsdks
xcrun --sdk iphoneos --show-sdk-path
xcodebuild -checkFirstLaunchStatus
检查点:Developer 路径指向完整 Xcode,版本正确,存在 iphoneos,首次启动检查通过。仅安装 Command Line Tools 不等于完整 iOS 构建环境。[8]
选错 Xcode 时,按真实路径切换并重新检查:
sudo xcode-select --switch /Applications/Xcode_16.1.app/Contents/Developer
示例路径必须替换。构建期间保持同一 Xcode / SDK;切换后重建、重验。
3.2 创建标识、签名与 Profile
在 Apple Developer 的 Certificates, Identifiers & Profiles 中:
- 注册 App ID
com.example.MyGame,启用实际 capabilities。 - 登记测试设备 UDID。
- 准备 Apple Development 证书和 iOS App Development Profile。
- 准备 Apple Distribution 证书和 Ad Hoc Profile,加入测试设备。
- 从 Keychain Access 导出证书及对应私钥为
.p12,设置密码;下载.mobileprovision。
只有 .cer 不能代替含私钥的 .p12。按远程文档要求把签名身份装到 Mac 的 System Keychain,Profile 装到构建用户可访问的位置。[1][9][10]
Xcode 16 常用 Profile 目录:
~/Library/Developer/Xcode/UserData/Provisioning Profiles/
5.6.1 源码按 Xcode 版本识别该路径;不要只检查旧版的 ~/Library/MobileDevice/Provisioning Profiles/。[3]
确认 Mac 识别有效签名身份:
security find-identity -v -p codesigning
3.3 启用 Remote Login
Sonoma 中打开 System Settings > General > Sharing > Remote Login,允许构建账号登录。记录 IP / 用户,保证 Windows→Mac 22 端口互通,账号能写构建目录。[1]
默认远程根目录为 ~/UE5/Builds/<Windows机器名>;可设置 RemoteServerOverrideBuildPath。真实目录以 [Remote] Using base directory ... 日志为准。[1][3]
官方推荐先在 Mac 本地构建一次,排除工具链 / 签名问题。如果临时用 UE 做这一检查,它与“日常远程 Mac 不必预装完整 UE”并不冲突。[1]
在 Windows 导入签名,验证实际 UE 连接
4.1 Windows 编辑器先能正常构建
安装 UE iOS 支持与 VS C++ 组件,确认项目 C++ / 插件的 Win64 编辑器模块可构建,地图可打开。本文示例的 Editor 构建:
$EngineRoot = 'C:\Epic\UE_5.6'
$ProjectFile = 'D:\UEProjects\MyGame\MyGame.uproject'
& "$EngineRoot\Engine\Build\BatchFiles\Build.bat" `
MyGameEditor Win64 Development "-Project=$ProjectFile" -WaitMutex
if ($LASTEXITCODE -ne 0) { throw 'Windows Editor build failed' }
MyGameEditor 要替换为真实 Editor Target。这是编辑 / Cook 前置准备,不生成 iOS IPA。[7][11]
安装官方要求的 iTunes / iOS 支持组件与 Metal Developer Tools 4.4。[1][8]
4.2 Windows 导入 .p12 与 .mobileprovision
打开 Project Settings > Platforms > iOS:
- 设置 Bundle Identifier。
- 用 Provision 导入按钮导入
.mobileprovision。 - 用 Certificate 导入按钮导入含私钥的
.p12,在提示框输入密码。 - 手动选本轮对应的 Profile / 证书,确认 UE 显示有效状态。
Windows 要有可使用的签名私钥。 5.6.1 远程代码会在 Windows 找 Profile、导出临时 P12 并送到 Mac;最终 Windows iPhonePackager 的重新签名也使用对应身份。只在 Mac 安装证书,不能完成本文的 Windows 手工签名路线。[3][4][9]
Windows Profile 常用目录:
%LOCALAPPDATA%\Apple Computer\MobileDevice\Provisioning Profiles\
MobileProvision / ProvisionFile 要填实际安装的文件名,而不是 Apple 页面上的显示名。[3]
4.3 生成并测试 UE 的 SSH Key
在 Remote Build 设置填 192.168.1.20、用户名 uebuild,关闭 Enable Secondary Remote Mac,点击 Generate SSH Key 并完成安装。第一次连接确认目标机器与主机指纹,密钥位置以 UE 显示值为准。[1]
默认候选路径:
%APPDATA%\Unreal Engine\UnrealBuildTool\SSHKeys\192.168.1.20\uebuild\RemoteToolChainPrivate.key
先测端口:
Test-NetConnection -ComputerName 192.168.1.20 -Port 22
再用 UE 随附 cwrsync SSH 测密钥;替换路径 / 用户:
$EngineRoot = 'C:\Epic\UE_5.6'
$RemoteHost = 'uebuild@192.168.1.20'
$Key = Join-Path $env:APPDATA `
'Unreal Engine\UnrealBuildTool\SSHKeys\192.168.1.20\uebuild\RemoteToolChainPrivate.key'
$KeyForCygwin = '/cygdrive/' + $Key.Substring(0, 1).ToLower() + `
($Key.Substring(2) -replace '\\', '/')
& "$EngineRoot\Engine\Extras\ThirdPartyNotUE\cwrsync\bin\ssh.exe" `
-i $KeyForCygwin -o BatchMode=yes $RemoteHost 'xcodebuild -version'
if ($LASTEXITCODE -ne 0) { throw 'UE SSH / Xcode preflight failed' }
预期无需交互就能输出目标 Mac 的 Xcode 版本。系统 OpenSSH 通过不代表 UE 的 cwrsync / 密钥权限也通过。[3]
UNPROTECTED PRIVATE KEY FILE / 0660 按官方文档修复密钥权限,再测试。私钥 / P12 保存在受控凭据位置,不放到网站或公开仓库。[1]
配置项目:签名、Cook、dSYM 与构建路线
5.1 开启完整 dSYM Bundle
Project Settings > Platforms > iOS > Build 启用两个选项:
- Generate dSYMs for code debugging and profiling。
- Generate dSYMs as a bundle for third party crash tools。[2]
第一个启用生成,第二个输出标准目录形式的 .dSYM Bundle,并生成可回传的 .dSYM.zip。[2][3]
本文单主 Mac、手工签名的 Config/DefaultEngine.ini:
[/Script/IOSRuntimeSettings.IOSRuntimeSettings]
BundleIdentifier=com.example.MyGame
RemoteServerName=192.168.1.20
RSyncUsername=uebuild
bUseRSync=True
bSupportSecondaryMac=False
bAutomaticSigning=False
MobileProvision=MyGame_AdHoc.mobileprovision
SigningCertificate="Apple Distribution: Example Company (ABCDE12345)"
bGeneratedSYMFile=True
bGeneratedSYMBundle=True
bGenerateXCArchive=False
bShipForBitcode=False
首次 Development 换成 Development Profile / 证书,Ad Hoc 再换回 Distribution 身份。bGenerateXCArchive=False 与 dSYM 生成无关;Windows 的该选项不能生成 XCArchive。[3][4]
不要在 Config/IOS/IOSEngine.ini 等位置覆盖成不同值。脚本以 DefaultEngine.ini 为实践配置来源;已有平台覆盖需先明确有效配置再调整检查。
5.2 配置实际发布内容
在 Project Settings > Packaging:选对应 Build Configuration;Ad Hoc / App Store 勾 For Distribution,Development 取消;Pak / IoStore 与 UAT 参数一致;实际发布地图进入 Maps to Cook,Game Default Map 正确;动态 / 软引用资源通过 Asset Manager、Primary Asset Label 或额外 Cook 目录覆盖。[11]
Config/DefaultGame.ini 示例:
[/Script/UnrealEd.ProjectPackagingSettings]
BuildConfiguration=PPBC_Shipping
ForDistribution=True
bUsePakFile=True
bUseIoStore=True
+MapsToCook=(FilePath="/Game/Maps/Main")
/Game/Maps/Main 是占位地图。编辑器可运行不代表 Cook 资源完整;实际登录、支付 / SDK 资源、关卡和动态加载路径都要验收。
5.3 固定 stub → Windows IPA 流程
本文显式使用 -legacyxcode,并用 -ubtargs=-legacyxcode 传给 UBT / 远程编译端,固定已核对的路线,不要求改引擎 BaseEngine.ini。不要同时传 -modernxcode。[3][4]
从 Windows 发起完整构建
6.1 构建实际做什么
- Windows UAT / UBT 读项目、目标、Profile 和签名配置。
- 所需构建文件和签名材料同步到主 Mac。
- Mac 编译 / 链接 iOS C++,生成 dSYM 和签名 stub;产物按 manifest 回传。
- Windows Cook 内容,Stage 组织发布资源。
- Windows iPhonePackager 把内容加入 stub,按配置签名最终 IPA。
- UAT Archive 收集 IPA,随后独立收集本次 receipt 的 dSYM ZIP。[3][4][11]
6.2 Shipping / Ad Hoc 完整 UAT 命令
使用 PowerShell,替换变量,确保上一章已选 Ad Hoc 签名:
$EngineRoot = 'C:\Epic\UE_5.6'
$ProjectFile = 'D:\UEProjects\MyGame\MyGame.uproject'
$TargetName = 'MyGame'
$ArchiveDir = 'D:\IOSDeliveries\MyGame-AdHoc-FirstBuild\UATArchive'
$UatArgs = @(
'BuildCookRun', '-installed', '-nop4',
"-project=$ProjectFile", "-target=$TargetName",
'-platform=IOS', '-clientconfig=Shipping',
'-build', '-cook', '-stage', '-pak', '-iostore',
'-package', '-distribution', '-archive', "-archivedirectory=$ArchiveDir",
'-nodebuginfo', '-unattended', '-utf8output',
'-legacyxcode', '-ubtargs=-legacyxcode',
'-provision=MyGame_AdHoc.mobileprovision',
'-certificate=Apple Distribution: Example Company (ABCDE12345)'
)
& "$EngineRoot\Engine\Build\BatchFiles\RunUAT.bat" @UatArgs
if ($LASTEXITCODE -ne 0) { throw 'UAT failed: inspect the earliest failed stage' }
| 参数 | 本次作用 |
|---|---|
| -installed | Launcher / Installed Build;源码引擎移除此参数 |
| -target | 发布的 Game Target,不是 Editor |
| -build -cook -stage -package | 原生构建、转换资源、组织内容、打包 |
| -pak -iostore | 本例资源容器形式 |
| -distribution | 分发打包,匹配 Distribution 证书 / Profile |
| -archive -archivedirectory | 收集发布包,不是 Xcode Archive,不自动收集 dSYM |
| -nodebuginfo | 不把调试文件复制进 Stage;不关闭 dSYM 生成和远程产物回传 |
| -legacyxcode / -ubtargs | 固定打包主机和编译端的实践路线 |
此处 -nodebuginfo 把符号与 App 内容分开。第五章开启生成,第七章从原始 Binaries / receipt 收集;不要把这个参数理解成“完全不生成 dSYM”。[3][4]
6.3 用随附脚本一起完成构建和收集
把 Build-IOS.ps1 与 Verify-IOS.py 放在同一目录,如 D:\BuildTools\UE56IOS\。脚本检查版本 / 关键配置,创建唯一输出目录,保存日志,检查 UAT 返回值,按本次 receipt 收集 dSYM ZIP,并生成哈希清单。
先预览:
& 'D:\BuildTools\UE56IOS\Build-IOS.ps1' `
-EngineRoot 'C:\Epic\UE_5.6' `
-ProjectFile 'D:\UEProjects\MyGame\MyGame.uproject' `
-TargetName 'MyGame' `
-BundleIdentifier 'com.example.MyGame' `
-ProvisionFile 'MyGame_AdHoc.mobileprovision' `
-SigningCertificate 'Apple Distribution: Example Company (ABCDE12345)' `
-OutputRoot 'D:\IOSDeliveries' `
-Mode AdHoc -DryRun
确认后去掉 -DryRun 执行。源码引擎加 -SourceEngine。如果团队 PowerShell 策略限制脚本,按团队已有授权方式执行,不要全局放宽策略。
Development 用 -Mode Development、Development 证书 / Profile,并同步改项目设置;AppStore 同理。只改 -Mode 不够,远程编译读取的项目签名配置也必须匹配。
6.4 判断本次成功
检查日志中的 Mac / 用户、base directory、Xcode / SDK、编译和链接、dSYM 生成、Downloading build products、Cook、iPhonePackager、Package 与 Archive,最终成功退出。[3][4]
独立输出目录、当前日志、receipt 和第八章 UUID 核验一起排除旧产物。“目录里已有一个 IPA”不能证明本次成功。
收集 IPA 与完整 dSYM,形成交付目录
7.1 原始产物位置
普通 C++ Game、Target MyGame 的典型结果:
D:\UEProjects\MyGame\Binaries\IOS\
Distro_MyGame-IOS-Shipping.ipa
MyGame-IOS-Shipping.dSYM.zip
MyGame-IOS-Shipping.target
名字受 Target、配置、架构和项目类型影响,以本次 receipt / 日志为准,不在所有项目硬编码。[3][4]
脚本从本次 UATArchive 找最终 IPA,从对应 *.target 的 BuildProducts 找符号。不要手选其他配置 / Target 的同名文件。
7.2 为什么 -archive 不够
5.6.1 Windows Legacy GetFilesToArchive 收集 IPA;dSYM ZIP 属于 Mac 编译产物,由 dsymutil 生成,按 manifest 回传,需要独立收集。[3][4]
符号 ZIP 应保留完整 Bundle:
MyGame-IOS-Shipping.dSYM/
Contents/
Info.plist
Resources/
DWARF/
MyGame-IOS-Shipping
保留原始 .dSYM.zip,在 Mac 用 ditto 解包,避免 Windows 复制改变结构或符号链接。崩溃平台需要 Bundle / ZIP 时,上传与该 IPA 配对的一份。[3][12]
7.3 交付结构
MyGame-Shipping-AdHoc-<时间>-<唯一ID>/
build.log
UATArchive/
...本次 UAT 的 IPA...
delivery/
Distro_MyGame-IOS-Shipping.ipa
symbols/
MyGame-IOS-Shipping.dSYM.zip
...receipt 列出的其他 dSYM ZIP...
build.target
Build.version
build.json
build.log
artifact-manifest.json
Verify-IOS.py
verification.json ← 第八章成功后生成
收集完成只表示文件存在、有哈希。build.json 标记尚未通过签名 / UUID 核验;成功核验后才确认主程序符号与最终包匹配。
7.4 第三方动态 Framework 的符号
主程序 dSYM 不覆盖每个独立动态 Framework。需要供应商提供 与该 Framework 二进制 UUID 匹配 的 dSYM。参与主程序静态链接的代码与独立 Framework 要区分。[12]
需要 SDK 符号时,先把该版本供应商的 .dSYM.zip 放进独立目录,构建脚本增加 -AdditionalSymbolDirectory 'D:\SDKSymbols\CurrentVersion'。脚本将其与 UE 符号一起收集并生成哈希清单,然后运行 --require-framework-symbols。如果供应商只有 .dSYM 目录,可先在 Mac 用 ditto -c -k --keepParent Foo.framework.dSYM Foo.framework.dSYM.zip 保留 Bundle 打包。脚本不会凭空生成供应商已剥离的符号。
核验签名与 UUID,再做真机验收
8.1 传输整个交付目录
用团队已有文件共享 / SFTP 工具,把 delivery/ 整体复制到 Mac,如 ~/IOSDeliveries/MyGame-AdHoc/,保持 IPA、原始 dSYM ZIP、receipt 和 manifest 一起移动。
8.2 运行核验脚本
替换 Bundle ID、Team ID、设备 UDID:
python3 "$HOME/IOSDeliveries/MyGame-AdHoc/Verify-IOS.py" \
"$HOME/IOSDeliveries/MyGame-AdHoc" \
--bundle-id com.example.MyGame \
--team-id ABCDE12345 \
--mode ad-hoc \
--device-udid YOUR_REGISTERED_DEVICE_UDID
脚本核对文件哈希、ZIP 完整性、receipt、Bundle ID、arm64、主程序与 dSYM 全部 UUID / 架构、代码签名、Profile 有效期、Team、签名模式和设备覆盖。它不会重新签名、修改 IPA 或安装应用。
成功生成 verification.json,列出 IPA 哈希与 UUID,并明确 真机验收尚待执行。需要完整动态 Framework 符号覆盖时,在同一命令最后加 --require-framework-symbols。默认报告会列出 Framework 符号缺口;主程序匹配不等于所有 SDK 符号齐全。
8.3 手工检查 UUID 的命令
替换 IPA、符号 ZIP、.app 的真实文件名:
Delivery="$HOME/IOSDeliveries/MyGame-AdHoc"
CheckDir=$(mktemp -d /tmp/mygame-verify.XXXXXX)
ditto -x -k "$Delivery/Distro_MyGame-IOS-Shipping.ipa" "$CheckDir/ipa"
ditto -x -k "$Delivery/symbols/MyGame-IOS-Shipping.dSYM.zip" "$CheckDir/symbols"
App="$CheckDir/ipa/Payload/MyGame.app"
Executable=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "$App/Info.plist")
xcrun dwarfdump --uuid "$App/$Executable"
xcrun dwarfdump --uuid "$CheckDir/symbols/MyGame-IOS-Shipping.dSYM"
codesign --verify --deep --strict --verbose=2 "$App"
security cms -D -i "$App/embedded.mobileprovision" > "$CheckDir/profile.plist"
/usr/libexec/PlistBuddy -c 'Print :Name' "$CheckDir/profile.plist"
/usr/libexec/PlistBuddy -c 'Print :ExpirationDate' "$CheckDir/profile.plist"
先看 Payload/ 再设置 App;两个 dwarfdump 的 UUID / 架构逐项一致。文件名相同、时间接近、都是 Shipping 都不能替代配对。[12]
8.4 真机安装与功能验收
Ad Hoc / Development 通过 Xcode Window > Devices and Simulators 或团队设备工具安装。检查 UDID 覆盖,完成设备所需开发者模式 / 信任,再启动。[9][14]
至少验收:启动地图、登录 / 支付 / SDK 初始化、网络与权限、关键关卡、动态资源加载、真实设备画面与性能。安装、启动、符号核验分别记录。需要符号化验收时,用可控测试崩溃或已知报告验证崩溃平台的 UUID 与堆栈解析。[12]
8.5 App Store / TestFlight 分支
先满足第二章工具链要求与项目兼容性,再换 App Store 证书 / Profile,脚本 -Mode AppStore,Mac 核验 --mode app-store,无需设备 UDID。该 IPA 用于渠道提交,不做 Ad Hoc 安装。
用团队提交工具或 Mac Transporter 提交 IPA,保留本版本 dSYM、日志、receipt 和报告。Windows Legacy 已生成 IPA,不必为“得到 IPA”重新完整 Mac 构建;团队另需 .xcarchive 时,再规划 Mac Modern / Archive 交付。[6][10][13]
排障与交付完成核对
| 最早失败阶段 / 症状 | 首先检查 | 通过条件 |
|---|---|---|
| SSH / RSync | Remote Login、用户、UE 密钥、cwrsync 权限 | UE SSH 可无交互执行 Xcode 命令 |
| Profile / ExportCertificate | Windows Profile、匹配证书私钥、模式配置 | 签名材料同步成功 |
| SDK invalid / 无 iphoneos | xcode-select、完整 Xcode、SDK 与 UE 兼容 | 实际 Xcode / SDK 正确 |
| C++ 编译 / 链接 | 最早错误、iOS插件、架构、库 | Mac 编译 / 链接完成 |
| Metal / Cook | Metal 4.4、shader日志、资源规则 | 本次 Cook 完成 |
| IPA有、dSYM无 | 两个生成配置、receipt、Mac动作、回传 | 找到主程序 dSYM ZIP |
| Archive只有IPA | Windows Legacy 正常边界 | 独立收集符号完成 |
| UUID不匹配 | 旧符号、配置 / Target / SDK混用 | UUID / 架构完全对应 |
| 签名核验失败 | 最终重签、Profile / entitlements、嵌入签名 | 最终IPA核验通过 |
| 安装失败 | AppStore误当AdHoc、UDID、过期、信任 | 目标真机安装成功 |
交付完成核对
勾选记录开发者实际执行结果,网站不会自动检测 UE 环境。
官方依据与模板验证范围
| 编号 | 官方来源 | 支撑内容 |
|---|---|---|
| S1 | UE 5.6 Remote Mac Builds | 主Mac、SSH与准备 |
| S2 | UE 5.6 iOS Settings | dSYM和远程配置 |
| S3 | Epic 5.6.1官方UBT源码 | AppleExports、ToolChain/RemoteMac、IOSToolChain、UEBuildIOS、TargetReceipt |
| S4 | iOS UAT源码 / ProjectParams | IPP、命名、Archive边界、nodebuginfo、UAT参数 |
| S5 | iPhonePackager CookTime | stub重打包与重签 |
| S6 | UE Modernized Xcode Workflow | Mac归档 / 导出与内容目标 |
| S7 | UE 5.6 Visual Studio Setup | Windows C++环境 |
| S8 | UE Development Requirements / Windows Metal | 工具链基线、Metal4.4 |
| S9 | UE Provisioning and Signing | 签名材料与项目标识 |
| S10 | Apple Ad Hoc Provisioning | 证书、设备与Profile |
| S11 | UE 5.6 Build Operations | Build / Cook / Stage / Package / Archive |
| S12 | Apple Crash Symbolication | 主程序与Framework符号、UUID匹配 |
| S13 | Apple Upcoming Requirements | 2026-04-28 SDK提交要求 |
| S14 | UE Packaging iOS Projects | IPA安装;OS标签主要差在安装说明 |
Epic GitHub需要关联Epic的账号权限。网站不包含引擎源码或签名材料;随附脚本是独立工程模板。
官方文档和指定源码已核对。网站、下载及脚本参数 / 核验逻辑可单独验证;真实UE编译、Windows证书导入、Mac远程构建、IPA运行和新SDK兼容性,需要开发者在自己的环境按检查点完成,不能把网站发布当成这些验收通过。