相关文章推荐

本篇文章的主要内容是介绍UE在Mac上的开发环境部署、配置iOS远程出包、UPL在iOS上的应用(介入ipa出包过程)、工具和开发技巧、以及分析相关的引擎代码等内容,记录了一些在项目中遇到的坑,主要从我之前的 笔记 中整理而来,后续Mac和iOS相关的内容也都会更新到这篇文章里。

远程构建iOS

UE可以在Windows可以直接出Android和Win的包(Android需要配置JDK/SDK/NDK/Gradle等环境)。打包iOS则需要一台Mac,如果是每次打包iOS都要在Mac上进行操作,其实就是与Win上完全相同的操作,但是流程上不能复用就显得很繁琐,尤其是在修改了引擎的情况下,需要先更新引擎代码并编译,然后再更新项目、执行打包。好在UE提供了远程构建iOS,可以把Win/Android/iOS三端的包在相同的构建流程里出完。

前置需求:

  • 内网搭载MacOS的电脑一台(白黑都可)
  • 申请p12证书和mobileprovision
  • PC和Mac需要在网络内可以相互访问(在相同网段)
  • IOS证书申请

    打包iOS之前需要申请iOS的开发者账号来创建证书,可以在 developer.apple.com 申请。需要得到p12证书和mobileprovision,然后在UE的项目设置中导入它们。需要注意创建的证书是 Developer 还是 Distribution 证书,在出包的时候要匹配,否则会打包失败。

    申请证书的流程网上有很多文章,我这里是简单记录了下我申请证书的流程,步骤不是最详细的,仅供参考。

    首先在Mac上导出一个证书:
    打开软件 钥匙串访问 - 证书助理 - 从证书颁发机构请求证书

    选择存储到磁盘,会生成一个 CertificateSigningRequest.certSigningRequest 的文件。
    然后登录 Apple Developer ,进入 Account - Certificates

    进去之后创建 Apple Development 或者 iOS App Development ,创建过程中需要把上面生成的 CertificateSigningRequest.certSigningRequest 文件上传。

    添加设备:

    可以使用UE的 IPhonePackager.exe 来查看ios设备的uuid:

    生成Provision:

    生成之后要下载 provision 文件:

    在Apple Developer上只能下载cer证书,但是引擎需要p12,需要把cer证书导入到Mac的钥匙串中,再导出为p12的证书:

    注意:一定要选在“证书”分类下,不然p12选项是灰的。

    配置远程构建

    UE打包iOS需要在项目设置中导入证书和 provision ,以及把 BundleName Bundle Identifier 设置为在Apple开发者网站上设置的Bundle ID,格式为 com.xxxxx.yyyyyy

    p12证书和mobileprovision导入之后如图:

    导入证书之后就可以开始远程打包的配置了。

    首先在MAC的 系统偏好设置 - 共享 中启用远程登录:

    然后在Windows上对项目添导入 mobileproversion 和设置 BundleName Bundle Identifier
    之后继续往下拉找到 IOS - Build 下的 Remote Build Options :

    填入目标MAC机器的IP地址(如果不指定端口则默认为22,如果指定端口则使用 xx.xx.xx.xx:2222 这种形式,以冒号分隔)和用户名。

    然后点击 Generated SSH Key 会弹出一个窗口:

    按任意键继续。
    会提示你输入一个密码,按照提示输入,之后会提示你输入 MAC 电脑的密码,输入之后会提示:

    1
    Enter passphrase (empty for no passphrase):

    这是让你输入生成的ssh Key的密码,默认情况下可以不输,直接Enter就好。
    按照提示一直 Enter 会提示你ssh key生成成功:

    再继续会提示让你输入第一次设置的密码,和目标MAC机器的密码,执行完毕之后就会提示没有错误,就ok了:

    生成的SSH Key的存放路径为:

    1
    C:\Users\imzlp\AppData\Roaming/Unreal Engine/UnrealBuildTool/SSHKeys/192.168.2.89/imzlp/RemoteToolChainPrivate.key

    如果要将其共享给组内的其他成员,则把这个 RemoteToolChainPrivate.key 共享,然后让他们把 IOS - Build - RemoteBuildOptions 下的 Override existing SSH Permissions file 设置为 RemoteToolChainPrivate.key 的路径即可。

    之后就可以像打包Windows或者在Win上打包IOS一样了:

    远程到Mac打包分了几个阶段:

  • 把本机的引擎和工程代码上传至Mac
  • 在Mac上执行编译
  • 编译完毕之后在Mac上生成ipa包(但不包含Cook资源)
  • 把生成的ipa包拉回本地,解包,Cook美术资源,再合并为ipa
  • 其中第一步,把本机引擎和工程的代码上传至Mac是通过rsync来实现的,引擎中的 Engine\Build\Rsync 目录下包含了远程构建时需要上传至目标机器的过滤器。
    对于项目,可以在工程目录的 <ProjectDir>/Build/Rsync/RsyncProject.txt 创建该文件,添加自己想要上传至Mac的文件过滤器,可以解决执行远程打包时有些文件被遗漏掉的问题。
    UE上传时默认使用的RsyncProject.txt过滤器有引擎和项目目录的,具体的代码看:
    UnrealBuildTool/ToolChain/RemoteMac.cs#L927

  • Building for iOS on Windows
  • WWise常见问题解答
  • SSH使用key登录失败

    如果SSH连接时提示以下错误:

    1
    [email protected]: Permission denied (publickey,password,keyboard-interactive).

    可以修改Mac的SSH配置( /etc/ssh/sshd_config ):

    1
    2
    RSAAuthentication yes
    PubkeyAuthentication yes

    然后重载配置:

    1
    2
    sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
    sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist
  • Unable to login with SSH-RSA key
  • linux下sshd_config的StrictModes参数
  • iOS打包证书配置报错问题

    在UE的项目设置中添加 Provision Certificate Bundle Identifier 要和证书能对应上,但是在设置完之后选择打包还是会提示以下错误:

    1
    2
    Provision not found. A provision is required for deploying your app to the device.  
    Signing key not found. The app could not be digitally signed, because the signing key is not configured.

    配置完证书和 Provision 之后出现这种情况需要检查下证书是 开发(Development)**还是 发行(Distribution) ,默认情况下项目设置中是不勾选 发行(Distribution) 的,如果导入的证书是发行证书则 只能打包Shipping 并且 需要勾上发行(Distribution)**。

    如果使用发行证书不勾选**发行(For Distribution)**则打包时会有以下错误:

    1
    2
    3
    Check dependencies
    Code Signing Error: Provisioning profile "com.tencent.tmgp.zyhx_Production_SignProvision" doesn't match the entitlements file's value for the get-task-allow entitlement.
    Code Signing Error: Code signing is required for product type 'Application' in SDK 'iOS 13.6'

    SSHKey路径查找的bug

    前面提到了在 Project Settings - Platforms - iOS 中可以在 Override Existing SSH Permissions file 中指定SSHKey,如果不指定会默认使用引擎查找路径,默认情况下会从以下路径中查找:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const FString DefaultKeyFilename = TEXT("RemoteToolChainPrivate.key");
    const FString RelativeFilePathLocation = FPaths::Combine(TEXT("SSHKeys"), *RemoteServerName, *RSyncUsername, *DefaultKeyFilename);
    TArray<FString> PossibleKeyLocations;
    PossibleKeyLocations.Add(FPaths::Combine(*FPaths::ProjectDir(), TEXT("Build"), TEXT("NotForLicensees"), *RelativeFilePathLocation));
    PossibleKeyLocations.Add(FPaths::Combine(*FPaths::ProjectDir(), TEXT("Build"), TEXT("NoRedist"), *RelativeFilePathLocation));
    PossibleKeyLocations.Add(FPaths::Combine(*FPaths::ProjectDir(), TEXT("Build"), *RelativeFilePathLocation));
    PossibleKeyLocations.Add(FPaths::Combine(*FPaths::EngineDir(), TEXT("Build"), TEXT("NotForLicensees"), *RelativeFilePathLocation));
    PossibleKeyLocations.Add(FPaths::Combine(*FPaths::EngineDir(), TEXT("Build"), TEXT("NoRedist"), *RelativeFilePathLocation));
    PossibleKeyLocations.Add(FPaths::Combine(*FPaths::EngineDir(), TEXT("Build"), *RelativeFilePathLocation));
    PossibleKeyLocations.Add(FPaths::Combine(*Path, TEXT("Unreal Engine"), TEXT("UnrealBuildTool"), *RelativeFilePathLocation));

    但是在RemoveServerName包含端口的情况下,希望使用引擎查找路径时,UE的实现有Bug。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    void UIOSRuntimeSettings::PostInitProperties()
    {
    Super::PostInitProperties();

    // We can have a look for potential keys
    if (!RemoteServerName.IsEmpty() && !RSyncUsername.IsEmpty())
    {
    SSHPrivateKeyLocation = TEXT("");

    const FString DefaultKeyFilename = TEXT("RemoteToolChainPrivate.key");
    const FString RelativeFilePathLocation = FPaths::Combine(TEXT("SSHKeys"), *RemoteServerName, *RSyncUsername, *DefaultKeyFilename);

    FString Path = FPlatformMisc::GetEnvironmentVariable(TEXT("APPDATA"));

    TArray<FString> PossibleKeyLocations;
    PossibleKeyLocations.Add(FPaths::Combine(*FPaths::ProjectDir(), TEXT("Build"), TEXT("NotForLicensees"), *RelativeFilePathLocation));
    PossibleKeyLocations.Add(FPaths::Combine(*FPaths::ProjectDir(), TEXT("Build"), TEXT("NoRedist"), *RelativeFilePathLocation));
    PossibleKeyLocations.Add(FPaths::Combine(*FPaths::ProjectDir(), TEXT("Build"), *RelativeFilePathLocation));
    PossibleKeyLocations.Add(FPaths::Combine(*FPaths::EngineDir(), TEXT("Build"), TEXT("NotForLicensees"), *RelativeFilePathLocation));
    PossibleKeyLocations.Add(FPaths::Combine(*FPaths::EngineDir(), TEXT("Build"), TEXT("NoRedist"), *RelativeFilePathLocation));
    PossibleKeyLocations.Add(FPaths::Combine(*FPaths::EngineDir(), TEXT("Build"), *RelativeFilePathLocation));
    PossibleKeyLocations.Add(FPaths::Combine(*Path, TEXT("Unreal Engine"), TEXT("UnrealBuildTool"), *RelativeFilePathLocation));

    // Find a potential path that we will use if the user hasn't overridden.
    // For information purposes only
    for (const FString& NextLocation : PossibleKeyLocations)
    {
    if (IFileManager::Get().FileSize(*NextLocation) > 0)
    {
    SSHPrivateKeyLocation = NextLocation;
    break;
    }
    }
    }
    // ...
    }

    这个代码在Windows上有bug,因为当 RemoteServerName 具有指定端口时,在Windows上就会找不到SSHKey,因为Windows上路径中不能包含冒号,所以在查找Key路径的时候会有问题,这个问题需要修改引擎才能解决。
    修改上面的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    SSHPrivateKeyLocation = TEXT("");
    FString RealRemoteServerName = RemoteServerName;
    if(RemoteServerName.Contains(TEXT(":")))
    {
    FString RemoteServerPort;
    RemoteServerName.Split(TEXT(":"),&RealRemoteServerName,&RemoteServerPort);
    }
    const FString DefaultKeyFilename = TEXT("RemoteToolChainPrivate.key");
    const FString RelativeFilePathLocation = FPaths::Combine(TEXT("SSHKeys"), *RealRemoteServerName, *RSyncUsername, *DefaultKeyFilename);

    重新编译引擎即可。

    远程编译Shader的Key查找bug

    注意:在4.26及之后的引擎版本支持在Windows上编译metal的Shader了,详情见文档:

  • Using the Windows Metal Shader Compiler for iOS
  • Metal Developer Tools for Windows
  • Project Settings - Platforms - IOS 中开启 Enable Remote Shader Compile 后,如果填入的构建机地址具有指定端口,在查找SSHkey时会有问题:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    // Developer/Apple/MetalShaderFormat/Private/MetalShaderCompiler.cpp
    bool IsRemoteBuildingConfigured(const FShaderCompilerEnvironment* InEnvironment)
    {
    // ...
    GRemoteBuildServerSSHKey = "";
    if (InEnvironment != nullptr && InEnvironment->RemoteServerData.Contains(TEXT("SSHPrivateKeyOverridePath")))
    {
    GRemoteBuildServerSSHKey = InEnvironment->RemoteServerData[TEXT("SSHPrivateKeyOverridePath")];
    }
    if (GRemoteBuildServerSSHKey.Len() == 0)
    {
    GConfig->GetString(TEXT("/Script/IOSRuntimeSettings.IOSRuntimeSettings"), TEXT("SSHPrivateKeyOverridePath"), GRemoteBuildServerSSHKey, GEngineIni);

    GConfig->GetString(TEXT("/Script/IOSRuntimeSettings.IOSRuntimeSettings"), TEXT("SSHPrivateKeyOverridePath"), GRemoteBuildServerSSHKey, GEngineIni);
    if (GRemoteBuildServerSSHKey.Len() == 0)
    {
    if (!FParse::Value(FCommandLine::Get(), TEXT("serverkey"), GRemoteBuildServerSSHKey) && GRemoteBuildServerSSHKey.Len() == 0)
    {
    if (GRemoteBuildServerSSHKey.Len() == 0)
    {
    // RemoteToolChain.cs in UBT looks in a few more places but the code in FIOSTargetSettingsCustomization::OnGenerateSSHKey() only puts the key in this location so just going with that to keep things simple
    FString Path = FPlatformMisc::GetEnvironmentVariable(TEXT("APPDATA"));
    GRemoteBuildServerSSHKey = FString::Printf(TEXT("%s\\Unreal Engine\\UnrealBuildTool\\SSHKeys\\%s\\%s\\RemoteToolChainPrivate.key"), *Path, *GRemoteBuildServerHost, *GRemoteBuildServerUser);
    }
    }
    }
    }
    // ...
    }

    可以看到这里查找的Key路径时直接通过 GRemoteBuildServerHost 拼接的,但是如果在配置中指定了端口,那么 GRemoteBuildServerHost 的值为这种格式 xxx.xx.xx.xx:1234 ,但是Win上目录名不能带 : ,就会导致Key查找失败。

    还有在同文件的 ExecRemoteProcess 函数中,没有针对具有指定端口的情况做处理:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    bool ExecRemoteProcess(const TCHAR* Command, const TCHAR* Params, int32* OutReturnCode, FString* OutStdOut, FString* OutStdErr)
    {
    #if PLATFORM_MAC && !UNIXLIKE_TO_MAC_REMOTE_BUILDING
    return FPlatformProcess::ExecProcess(Command, Params, OutReturnCode, OutStdOut, OutStdErr);
    #else
    if (GRemoteBuildServerHost.IsEmpty())
    {
    return false;
    }
    FString CmdLine = FString(TEXT("-i \"")) + GRemoteBuildServerSSHKey + TEXT("\" \"") + GRemoteBuildServerUser + '@' + GRemoteBuildServerHost + TEXT("\" ") + Command + TEXT(" ") + (Params != nullptr ? Params : TEXT(""));
    return ExecProcess(*GSSHPath, *CmdLine, OutReturnCode, OutStdOut, OutStdErr);

    #endif
    }

    需要做一些处理:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    bool ExecRemoteProcess(const TCHAR* Command, const TCHAR* Params, int32* OutReturnCode, FString* OutStdOut, FString* OutStdErr)
    {
    #if PLATFORM_MAC && !UNIXLIKE_TO_MAC_REMOTE_BUILDING
    return FPlatformProcess::ExecProcess(Command, Params, OutReturnCode, OutStdOut, OutStdErr);
    #else
    if (GRemoteBuildServerHost.IsEmpty())
    {
    return false;
    }

    FString RemoteBuildServerIP = GRemoteBuildServerHost;
    FString RemoteBuildServerPort = TEXT("22");

    if(GRemoteBuildServerHost.Contains(TEXT(":")))
    {
    GRemoteBuildServerHost.Split(TEXT(":"),&RemoteBuildServerIP,&RemoteBuildServerPort);
    }

    FString CmdLine = FString(TEXT("-i \"")) + GRemoteBuildServerSSHKey + TEXT("\" \"") + GRemoteBuildServerUser + '@' + RemoteBuildServerIP + TEXT("\" ") TEXT("-p ") + RemoteBuildServerPort +TEXT(" ")+ Command + TEXT(" ") + (Params != nullptr ? Params : TEXT(""));
    return ExecProcess(*GSSHPath, *CmdLine, OutReturnCode, OutStdOut, OutStdErr);

    #endif
    }

    签名错误

    开发者签名到期

    如果在打包时输出下列日志,则是因为IOS证书过期了导致的:

    1
    2
    3
    /Users/buildmachine/UE4/Builds/lipengzha-PCb/C/BuildAgent/workspace/FGameEngine/Client/Intermediate/ProjectFilesIOS/FGame.xcodeproj: error: No certificate for team '6H9S4KQ3C9' matching 'iPhone Developer: Created via API (7ZQD4FUW73)' found: Select a different signing certificate for CODE_SIGN_IDENTITY, a team that matches your selected certificate, or switch to automatic provisioning. (in target 'FGame' from project 'FGame')
    warning: Run script build phase 'Sign Manual Frameworks' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'FGame' from project 'FGame')
    ** BUILD FAILED **

    只需要更新证书就好。

    苹果中级证书到期

    如果在Windows上打包时提示下面错误:

    1
    2
    IPP ERROR: Application exception: System.Security.Cryptography.CryptographicException
    A certificate chain could not be built to a trusted root authority.

    同样也是苹果中级证书过期了导致的,更新即可。详见: BuildGraph:构建支持多平台打包的二进制引擎

    注意事项

    在Windows上远程构建IOS,有几个约束:

  • IPA内单个文件大小不能超过2G,如Pak文件
  • IPA总大小不能超过4G
  • 不然会有下面这种错误:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    IPP ERROR: Application exception: Ionic.Zip.ZipException: Compressed or Uncompressed size, or offset exceeds the maximum value. Consider setting the UseZip64WhenSaving property on the ZipFile instance.
    Ionic.Zip.ZipEntry.SetZip64Flags()
    Ionic.Zip.ZipEntry.PostProcessOutput(Stream s)
    Ionic.Zip.ZipEntry._WriteEntryData(Stream s)
    Ionic.Zip.ZipEntry.Write(Stream s)
    Ionic.Zip.ZipFile.Save()
    iPhonePackager.FileOperations.ZipFileSystem.Close()
    iPhonePackager.CookTime.RepackageIPAFromStub()
    iPhonePackager.Program.Main(String[] args)

    Mac开发环境

    MacOS安装UE

    UE要求MacOS的分区格式为 不区分大小写 (不然EpicLauncher也无法安装),而且安装引擎的要求是系统版本大于 10.13.5 ,否则会出现引擎崩溃和一些不支持的情况(尝试忽略错误无法安装成功)。
    编译依赖xcode,就像依赖VS一样,需要安装编译环境。
    如果安装完UE和Xcode之后创建项目提示下列错误:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    An error occurred while trying to generate project files.
    Running Mono...
    Setting up Mono
    /Users/Shared/UnrealEngine/4.22/Engine /Users/Shared/UnrealEngine/4.22/Engine/Binaries/Mac
    Discovering modules, targets and source code for project...
    Compiling with non-standard Xcode (xcode-select): /Library/Developer/CommandLineTools/
    Triggered an exception while looking for SDK directory in Xcode.app
    System.IO.DirectoryNotFoundException: Directory '/Library/Developer/CommandLineTools/Platforms/MacOSX.platform/Developer/SDKs' not found.
    at System.IO.Directory.ValidateDirectoryListing (System.String path, System.String searchPattern, System.Boolean& stop) [0x00000] in <filename unknown>:0
    at System.IO.Directory.GetFileSystemEntries (System.String path, System.String searchPattern, FileAttributes mask, FileAttributes attrs) [0x00000] in <filename unknown>:0
    at System.IO.Directory.GetDirectories (System.String path, System.String searchPattern) [0x00000] in <filename unknown>:0
    at System.IO.Directory.GetDirectories (System.String path) [0x00000] in <filename unknown>:0
    at UnrealBuildTool.AppleToolChain.SelectSDK (System.String BaseSDKDir, System.String OSPrefix, System.String& PlatformSDKVersion, Boolean bVerbose) [0x00000] in <filename unknown>:0
    ERROR: Invalid SDK MacOSX.sdk, not found in /Library/Developer/CommandLineTools/Platforms/MacOSX.platform/Developer/SDKs

    则安装 Xcode Command Line Tools ,然后执行以下命令即可:

    1
    $ sudo ln -s /Applications/Xcode.app/Contents/Developer/Platforms /Library/Developer/CommandLineTools/
  • OS X: Can’t create new project
  • I can’t build a c++ program on my Mac with Xcode
  • Mac修改SSHD默认端口

    有些内网有端口限制,低于xxxx的端口默认不开放,所以在22端口被限制的情况下如何进行远程构建?修改SSH的默认端口!

    编辑 /etc/services 文件中的ssh的端口:

    1
    $ vim /etc/services

    把SSH的端口改为其他的:

    1
    2
    ssh              22/udp     # SSH Remote Login Protocol
    ssh 22/tcp # SSH Remote Login Protocol
    1
    2
    ssh              2222/udp     # SSH Remote Login Protocol
    ssh 2222/tcp # SSH Remote Login Protocol

    保存退出。
    还需要重新加载配置使端口生效:

    1
    2
    sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
    sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist

    然后测试端口是否可以连接:

    1
    ssh localhost -p 2222
  • Can’t change PORT listen on macOS X Mojave for built-in SSH
  • 为xcode开启多线程编译

    首先看一下Mac的硬件配置:

    1
    sysctl machdep.cpu

    找到 machdep.cpu.core_count 字段,其中的数值就是Mac的核心数。

    然后可以给xcode开启多线程,数量数为核心数*2,如我的是8核,就可以开启16线程:

    1
    defaults write com.apple.Xcode PBXNumberOfParallelBuildSubtasks 16

    Mac系统内置的Framework

    有时候需要在UE的模块中引入系统的Framework,那么Mac默认包含哪些Framework呢?可以通过以下方式查看。
    我使用的系统版本为 10.15.2 ,可以通过 sw_vers 查看:

    1
    2
    3
    4
    buildmachine@LIPENGZHA-MC0 ~ % sw_vers
    ProductName: Mac OS X
    ProductVersion: 10.15.2
    BuildVersion: 19C57

    系统内置的Framework在以下目录中:

    1
    /System/Library/Frameworks

    10.15.2 版本中包含以下framework:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    AGL.framework                           ColorSync.framework                     CoreVideo.framework                    GameKit.framework
    LinkPresentation.framework OpenGL.framework SoundAnalysis.framework
    AVFoundation.framework Combine.framework CoreWLAN.framework GameplayKit.framework
    LocalAuthentication.framework PCSC.framework Speech.framework
    AVKit.framework Contacts.framework CryptoKit.framework HIDDriverKit.framework
    MapKit.framework PDFKit.framework SpriteKit.framework
    Accelerate.framework ContactsUI.framework CryptoTokenKit.framework Hypervisor.framework
    MediaAccessibility.framework PencilKit.framework StoreKit.framework
    Accounts.framework CoreAudio.framework DVDPlayback.framework ICADevices.framework
    MediaLibrary.framework Photos.framework SwiftUI.framework
    AdSupport.framework CoreAudioKit.framework DeviceCheck.framework IMServicePlugIn.framework
    MediaPlayer.framework PhotosUI.framework SyncServices.framework
    AddressBook.framework CoreAudioTypes.framework DirectoryService.framework IOBluetooth.framework
    MediaToolbox.framework PreferencePanes.framework System.framework
    AppKit.framework CoreBluetooth.framework DiscRecording.framework IOBluetoothUI.framework
    Message.framework PushKit.framework SystemConfiguration.framework
    AppleScriptKit.framework CoreData.framework DiscRecordingUI.framework IOKit.framework
    Metal.framework Python.framework SystemExtensions.framework
    AppleScriptObjC.framework CoreDisplay.framework DiskArbitration.framework IOSurface.framework
    MetalKit.framework QTKit.framework TWAIN.framework
    ApplicationServices.framework CoreFoundation.framework DriverKit.framework IOUSBHost.framework
    MetalPerformanceShaders.framework Quartz.framework Tcl.framework
    AudioToolbox.framework CoreGraphics.framework EventKit.framework IdentityLookup.framework
    MetricKit.framework QuartzCore.framework Tk.framework
    AudioUnit.framework CoreHaptics.framework ExceptionHandling.framework ImageCaptureCore.framework
    ModelIO.framework QuickLook.framework USBDriverKit.framework
    AudioVideoBridging.framework CoreImage.framework ExecutionPolicy.framework ImageIO.framework
    MultipeerConnectivity.framework QuickLookThumbnailing.framework UserNotifications.framework
    AuthenticationServices.framework CoreLocation.framework ExternalAccessory.framework InputMethodKit.framework
    NaturalLanguage.framework RealityKit.framework VideoDecodeAcceleration.framework
    Automator.framework CoreMIDI.framework FWAUserLib.framework InstallerPlugins.framework
    NetFS.framework Ruby.framework VideoSubscriberAccount.framework
    BackgroundTasks.framework CoreMIDIServer.framework FileProvider.framework InstantMessage.framework
    Network.framework SafariServices.framework VideoToolbox.framework
    BusinessChat.framework CoreML.framework FileProviderUI.framework Intents.framework
    NetworkExtension.framework SceneKit.framework Vision.framework
    CFNetwork.framework CoreMedia.framework FinderSync.framework JavaFrameEmbedding.framework
    NetworkingDriverKit.framework ScreenSaver.framework WebKit.framework
    CalendarStore.framework CoreMediaIO.framework ForceFeedback.framework JavaScriptCore.framework
    NotificationCenter.framework ScriptingBridge.framework iTunesLibrary.framework
    CallKit.framework CoreMotion.framework Foundation.framework JavaVM.framework
    OSAKit.framework Security.framework vecLib.framework
    Carbon.framework CoreServices.framework GLKit.framework Kerberos.framework
    OSLog.framework SecurityFoundation.framework vmnet.framework
    CloudKit.framework CoreSpotlight.framework GLUT.framework Kernel.framework
    OpenAL.framework SecurityInterface.framework
    Cocoa.framework CoreTelephony.framework GSS.framework LDAP.framework
    OpenCL.framework ServiceManagement.framework
    Collaboration.framework CoreText.framework GameController.framework LatentSemanticMapping.framework
    OpenDirectory.framework Social.framework

    安装CommandLineTool

    Xcode’s metal shader compiler was not found, verify Xcode has been installed on this Mac and that it has been selected in Xcode > Preferences > Locations > Command-line Tools.

    相关问题:

  • Unreal Engine inaccurately reports “XCode is too old” when CommandLineTools installed
  • 离线安装 XCode Command Line Tools for Xcode 可以从苹果的开发者网站下载: More Downloads for Apple Developers

    在安装完 Command Line Tools 之后,如果cook时还是提示这个错误,则需要执行下列命令(当然要首先确保 /Library/Developer/CommandLineTools 路径存在,一般 Command Line Tools 的默认安装路径是这个):

    1
    $ sudo xcode-select -s /Library/Developer/CommandLineTools

    当设置 CommandLineTools 之后打包时可能会提示:

    1
    ERROR: Invalid SDK MacOSX.sdk, not found in /Library/Developer/CommandLineTools/Platforms/MacOSX.platform/Developer/SDKs

    这是因为通过 xcode-select 设置为 CommandLineTools 之后,打包时找不到Xcode里的库了。
    解决的办法是在 CommandLineTools 的目录下创建一个Xcode中的 Platforms 目录的软连接:

    1
    sudo ln -s /Applications/Xcode.app/Contents/Developer/Platforms /Library/Developer/CommandLineTools/Platforms

    actool错误

    1
    2
    UATHelper: Packaging (iOS):   xcrun: error: unable to find utility "actool", not a developer tool or in PATH
    PackagingResults: Error: unable to find utility "actool", not a developer tool or in PATH

    这是因为把 CommandLinTool 设置为默认的命令行工具之后, CommandLinTool/use/bin 下并没有 actool 等工具。
    这是个十分坑爹的问题,用xcode作为默认的命令行工具导致Cook不过,用CommandLineTool又在编译时有问题。
    我的解办法是把 /Applications/Xcode.app/Contents/Developer/usr/bin 通过软连接方式链接到 /Library/Developer/CommandLineTools/usr :

    1
    2
    3
    4
    # 当然要先备份CommandLineTool/usr/bin
    $ mv /Library/Developer/CommandLineTools/usr/bin /Library/Developer/CommandLineTools/usr/Command_bin
    # 创建xcode的bin目录的软连接
    $ sudo ln -s /Applications/Xcode.app/Contents/Developer/usr/bin /Library/Developer/CommandLineTools/usr/bin

    解除MacOS安装软件的限制

     
    推荐文章