WINDOWS → iOS · 开发者实践指南

在 Windows 发起,
交付 IPA 与 dSYM。

先看与纯 macOS 构建的区别,再一步步完成环境、签名、远程编译、产物收集和真机验收。

版本依据 UE 5.6.1Shipping / Ad Hoc 主线附完整实践脚本
完整交付链路BUILD → COLLECT → VERIFY
01 / WINDOWS发起构建与处理资源

UAT · Project / Signing · Cook

SSH / RSync · 文件与签名材料
02 / REMOTE MAC原生编译与符号生成

C++ · Link · dSYM · Signed stub

回传产物 · Windows 打包与收集
03 / WINDOWS DELIVERYIPA + 完整 dSYM ZIP

IPP · Receipt · Logs · Hash manifest

最后在 Mac 核验签名 / UUID,再执行真机验收
01
理解两条构建路线

编译、Cook、签名与打包分别在哪执行。

02
Windows 发起完整构建

复制命令,或使用构建与收集脚本。

03
交付匹配的 IPA 与符号

验证 UUID、签名、Profile 和真实设备。

i

跟随第一章比较路线,第二至第八章完成实践。每个示例都需要替换为项目真实参数。

目标:让开发者从一台 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 打包或真机验收。

01

Windows + 远程 Mac,与纯 macOS 构建有什么区别

iOS 原生 C++ 的编译、链接仍在 Mac。 Windows 路线的价值是把开发、资源处理和构建调度留在 Windows,由 Mac 提供 Apple 工具链能力。Windows 不会把 Visual C++ 编译出的 Win64 程序转换成 iOS 程序。[1][3]

相同目标,不同分工比较构建发生在哪台机器
Windows 调度和打包,Mac 提供原生工具链
Windows · UAT / CookMac · C++ / dSYM / stubWindows · IPA / 符号收集

本指南固定 Legacy 流程:签名材料在 Windows 可用,Mac 构建产物回传,Windows iPhonePackager 输出最终 IPA。

两条路线的工作分工

工作 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 路线的全部交付步骤。

02

明确交付目标,准备环境与参数

第一次实践建议使用 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]

03

在 Mac 准备 Xcode、签名身份与 SSH

3.1 确认完整 Xcode 与 iOS SDK

打开 Xcode 完成首次启动、组件和许可证处理,安装 iOS 平台支持。在 Terminal 执行:

macOS · 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 时,按真实路径切换并重新检查:

macOS · Terminal
sudo xcode-select --switch /Applications/Xcode_16.1.app/Contents/Developer

示例路径必须替换。构建期间保持同一 Xcode / SDK;切换后重建、重验。

3.2 创建标识、签名与 Profile

在 Apple Developer 的 Certificates, Identifiers & Profiles 中:

  1. 注册 App ID com.example.MyGame,启用实际 capabilities。
  2. 登记测试设备 UDID。
  3. 准备 Apple Development 证书和 iOS App Development Profile。
  4. 准备 Apple Distribution 证书和 Ad Hoc Profile,加入测试设备。
  5. 从 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 识别有效签名身份:

macOS · Terminal
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]

04

在 Windows 导入签名,验证实际 UE 连接

4.1 Windows 编辑器先能正常构建

安装 UE iOS 支持与 VS C++ 组件,确认项目 C++ / 插件的 Win64 编辑器模块可构建,地图可打开。本文示例的 Editor 构建:

Windows · PowerShell
$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:

  1. 设置 Bundle Identifier。
  2. 用 Provision 导入按钮导入 .mobileprovision。
  3. 用 Certificate 导入按钮导入含私钥的 .p12,在提示框输入密码。
  4. 手动选本轮对应的 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

先测端口:

Windows · PowerShell
Test-NetConnection -ComputerName 192.168.1.20 -Port 22

再用 UE 随附 cwrsync SSH 测密钥;替换路径 / 用户:

Windows · PowerShell
$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]

05

配置项目:签名、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:

项目配置 · 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 示例:

项目配置 · 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]

06

从 Windows 发起完整构建

6.1 构建实际做什么

  1. Windows UAT / UBT 读项目、目标、Profile 和签名配置。
  2. 所需构建文件和签名材料同步到主 Mac。
  3. Mac 编译 / 链接 iOS C++,生成 dSYM 和签名 stub;产物按 manifest 回传。
  4. Windows Cook 内容,Stage 组织发布资源。
  5. Windows iPhonePackager 把内容加入 stub,按配置签名最终 IPA。
  6. UAT Archive 收集 IPA,随后独立收集本次 receipt 的 dSYM ZIP。[3][4][11]

6.2 Shipping / Ad Hoc 完整 UAT 命令

使用 PowerShell,替换变量,确保上一章已选 Ad Hoc 签名:

Windows · PowerShell
$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 用随附脚本一起完成构建和收集

选择这次交付的签名用途示例参数需要替换
本轮配置Shipping / Ad Hoc

项目设置选择 Ad Hoc Profile 和 Apple Distribution 身份;需要安装的设备必须在 Profile 中。下面命令调用随附脚本,构建并收集产物。

Windows · PowerShell · 示例调用

把 Build-IOS.ps1 与 Verify-IOS.py 放在同一目录,如 D:\BuildTools\UE56IOS\。脚本检查版本 / 关键配置,创建唯一输出目录,保存日志,检查 UAT 返回值,按本次 receipt 收集 dSYM ZIP,并生成哈希清单。

先预览:

Windows · PowerShell
& '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”不能证明本次成功。

07

收集 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 打包。脚本不会凭空生成供应商已剥离的符号。

08

核验签名与 UUID,再做真机验收

8.1 传输整个交付目录

用团队已有文件共享 / SFTP 工具,把 delivery/ 整体复制到 Mac,如 ~/IOSDeliveries/MyGame-AdHoc/,保持 IPA、原始 dSYM ZIP、receipt 和 manifest 一起移动。

8.2 运行核验脚本

替换 Bundle ID、Team ID、设备 UDID:

macOS · Terminal
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 的真实文件名:

macOS · Terminal
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]

09

排障与交付完成核对

最早失败阶段 / 症状 首先检查 通过条件
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、过期、信任 目标真机安装成功

交付完成核对

0 / 8 项已手工确认

勾选记录开发者实际执行结果,网站不会自动检测 UE 环境。

10

官方依据与模板验证范围

编号 官方来源 支撑内容
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兼容性,需要开发者在自己的环境按检查点完成,不能把网站发布当成这些验收通过。