CMake 构建失败,Xcode 12 和 CMAKE_IOS_INSTALL_COMBINED=YES

时间:2021-01-03 13:50:17

标签: cmake xcode12

编辑这是一个known CMake issue


使用 Xcode 11(特别是 Xcode 11.2.1),我曾经能够使用以下命令为 iOS 交叉编译我的项目:

cd /path/to/project
mkdir build
cd build
cmake .. -G Xcode -DCMAKE_SYSTEM_NAME=iOS \
                 "-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" \
                  -DCMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH=NO \
                  -DCMAKE_IOS_INSTALL_COMBINED=YES \
                  -DCMAKE_INSTALL_PREFIX=install
cmake --build . --config Release --target install

这创建了一个包含两个切片的构建,一个切片用于 arm64 架构(用于在真实设备上运行),另一个切片用于 x86_64 架构(用于在 Intel-基于开发环境)。

升级到 Xcode 12(特别是 Xcode 12.3)后,这不再有效。构建始终失败并显示此错误消息(我添加了换行符):

error: unable to attach DB: error: accessing build database "/path/to/project/build/ios/build/XCBuildData/build.db":
  database is locked Possibly there are two concurrent builds running in the same filesystem location.

问题似乎是 CMake 为 install 目标创建的构建后规则。在该构建后规则中,当第一个构建仍在进行中时,将启动第二个构建。

if test "$CONFIGURATION" = "Release"; then :
  cd /path/to/project/build/ios
  /usr/local/Cellar/cmake/3.19.2/bin/cmake -DBUILD_TYPE=$CONFIGURATION -DEFFECTIVE_PLATFORM_NAME=$EFFECTIVE_PLATFORM_NAME -P cmake_install.cmake
fi

当我不再将 CMAKE_IOS_INSTALL_COMBINED 设置为 YES 时构建成功,但生成的构建仅包含一个切片(在我的情况下为 arm64,大概是因为这是第一个架构列在 CMAKE_OSX_ARCHITECTURES 中)。

我正在考虑为每个架构单独构建,然后手动将切片拼接在一起。在我走那条路之前,有没有人能够找到更优雅的解决方案?

环境:macOS 11.1、Xcode 12.3、CMake 3.19.2

1 个答案:

答案 0 :(得分:3)

CMake 3.19 release notes 包含以下提示:

<块引用>

Xcode 生成器现在在为 Xcode 12.0 或更高版本生成时使用 Xcode“新构建系统”。请参阅 CMAKE_XCODE_BUILD_SYSTEM 变量。可以使用 -T buildsystem=1 切换到旧版构建系统。

因此,目前的解决方法是将 -T 选项添加到构建系统生成命令行:

cmake .. -G Xcode -T buildsystem=1
                  -DCMAKE_SYSTEM_NAME=iOS \
                 "-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" \
                  -DCMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH=NO \
                  -DCMAKE_IOS_INSTALL_COMBINED=YES \
                  -DCMAKE_INSTALL_PREFIX=install

只要 Xcode 仍然支持遗留构建系统,这应该可以工作。 Xcode 12 Release Notes 有话要说:

<块引用>

旧版构建系统已弃用,并将在未来版本中移除。 (62742902)

因此 -T buildsystem=1 选项只能被视为一种临时解决方法。