为 Apple Silicon mac 模拟器构建静态库

fic*_*fic 6 simulator static-libraries silicon ios arm64

我的静态库是使用 xcodebuild 构建的,然后根据模拟器和设备构建结果创建一个胖库。这是我的 xcodebuild 命令:

xcodebuild OTHER_CFLAGS="-fembed-bitcode" -configuration "iphoneos" -target "${LIB_NAME}Common" -sdk iphoneos

xcodebuild OTHER_CFLAGS="-fembed-bitcode" -configuration "iphonesimulator" -target "${LIB_NAME}Common" -sdk iphonesimulator
Run Code Online (Sandbox Code Playgroud)

溶脂命令:

lipo -create "${DEVICE_DIR}/lib${LIB_NAME}Common.a" "${SIMULATOR_DIR}/lib${LIB_NAME}Common.a" -output "${INSTALL_DIR}/include/${LIB_NAME}/lib${LIB_NAME}Common.a"
Run Code Online (Sandbox Code Playgroud)

检查 fat lib 中的体系结构后,我得到:

$ lipo -info MyLibCommon.a 
Architectures in the fat file: MyLibCommon.a are: armv7 i386 x86_64 arm64
Run Code Online (Sandbox Code Playgroud)

然而,当我通过 cocoapods 将 lib 添加到项目并在模拟器上的 Apple 新 Silicon(带有 arm64 芯片组)上运行该项目时,出现以下编译错误:

building for iOS Simulator, but linking in object file built for iOS, file 'MyLibCommon.a' for architecture arm64
Run Code Online (Sandbox Code Playgroud)

排除模拟器的arm64架构不是一个选项,因为Apple Silicon Mac上有arm64芯片组。

知道如何为 Apple Silicon Simulator 构建静态库吗?

Sig*_*uza 7

这不可能。

您的模拟器二进制文件很可能只是 i386 和 x86_64。如果您确实拥有arm64 iOS 二进制文件和arm64 macOS 二进制文件,lipo则会出现错误:

致命错误:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo:test.a.ios 和 test.a.macos 具有相同的体系结构(arm64)并且不能位于相同的 fat 输出文件

无论您尝试使用成熟的二进制文件、未链接的目标文件还是静态库,这种情况都会发生。原因很简单,就是 fat 文件格式的一个缺点:每个架构只能有一个切片。您需要arm64 iOS 和Apple Silicon 模拟器,但这将是2x arm64。

您可能会想尝试构建一个可在 iOS 和 macOS 上运行的单一精简 arm64 二进制文件,但这也是不可能的。二进制文件是平台锁定的:

% otool -l test.o.ios | fgrep -B1 -A5 LC_BUILD_VERSION
Load command 1
       cmd LC_BUILD_VERSION
   cmdsize 24
  platform 2
       sdk 14.2
     minos 14.2
    ntools 0
% otool -l test.o.macos | fgrep -B1 -A5 LC_BUILD_VERSION
Load command 1
       cmd LC_BUILD_VERSION
   cmdsize 24
  platform 1
       sdk 11.0
     minos 11.0
    ntools 0
Run Code Online (Sandbox Code Playgroud)

注意platform 2vs platform 1。内核实际上会忽略这个加载命令,但dyld不会。而且你也不能在一个二进制文件中有两个这样的加载命令,这也被认为是无效的。

您可能还记得苹果公司声明中提到的“Universal 2”文件格式或引用的内容 - 但他们撒了谎。不存在“universal 2”,它与十年前的文件格式完全相同。当他们说“universal 2”时,他们的意思是“将arm64切片添加到您的macOS二进制文件中”。

在我看来,你有三个选择:

  1. 您构建单独的库并保持名称分开。
  2. 你永远不会同时构建两种架构。
  3. 您为 x86_64 构建模拟器目标并在 Rosetta 下运行它。

后两者在互联网上得到了广泛的建议,其中第二个是“仅针对活动架构构建”,第三个是“排除arm64”。鉴于罗塞塔预计最终会消失,第三种选择从长远来看似乎不可行。

  • 第四种选择是重新打包该库,使其成为 xcframework,而不是普通的静态库;那么 xcframework 可以包含一个包含与之相关的任何和所有架构的 ios 版本,另一个包含所有必要架构的 ios 模拟器版本,还可能包含其他平台的版本,例如 tvOS 和 watchOS,其中您也有架构重叠在一个普通的 lipo'd 静态库中。 (10认同)