Issue
EDIT This is a known CMake issue.
With Xcode 11 (specifically Xcode 11.2.1) I used to be able to cross-compile my project for iOS with this command:
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
This created a build with two slices, one slice for the arm64
architecture (for running on a real device) and one slice for the x86_64
architecture (for running in a simulator on an Intel-based dev environment).
After upgrading to Xcode 12 (specifically Xcode 12.3) this no longer works. The build consistently fails with this error message (line break added by me):
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.
The issue seems to be a post-build rule that CMake creates for the install
target. In that post-build rule a second build is initiated while the first one is still in progress.
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
The build succeeds when I no longer set CMAKE_IOS_INSTALL_COMBINED
to YES
, but then the resulting build only contains one slice (arm64
in my case, presumably because this is the first architecture that is listed in CMAKE_OSX_ARCHITECTURES
).
I'm considering making a separate build for each architecture, and then stitching the slices together manually. Before I go down that road, has anyone been able to find a more elegant solution?
Environment: macOS 11.1, Xcode 12.3, CMake 3.19.2
Solution
EDIT 3 years later The Xcode legacy build system has been removed in Xcode 14, and CMake also has made some internal changes. So with modern CMake and Xcode versions (3.28.1 and 15.1, respectively) the solution that uses CMAKE_IOS_INSTALL_COMBINED
now looks like this:
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
cmake --build . --config Release
cmake --install . --prefix `pwd`/install
The change is that the --build
and --install
steps now must be done separately, and of course the -T buildsystem=1
workaround no longer applies.
Note: CMake has deprecated CMAKE_IOS_INSTALL_COMBINED
, so the above solution is doomed. The reason for the deprecation is that on Silicon Macs simulator and device builds both use the arm64
architecture, so a combined build that generates a universal library is no longer viable (the same architecture can exist only once in an universal library). It looks as if the way forward is to 1) build a separate framework for the two platforms; and then 2) create an XCFramework with the platform-specific frameworks. Currently CMake has no built-in support for all of this.
The CMake 3.19 release notes contain this hint:
The Xcode generator now uses the Xcode “new build system” when generating for Xcode 12.0 or higher. See the
CMAKE_XCODE_BUILD_SYSTEM
variable. One may use-T buildsystem=1
to switch to the legacy build system.
The workaround, for the moment, is therefore to add the -T
option to the build system generation command line:
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
This should work as long as Xcode still supports the legacy build system. The Xcode 12 Release Notes have this to say on the matter:
The legacy build system is deprecated, and will be removed in a future release. (62742902)
So the -T buildsystem=1
option can only be considered a temporary workaround.
Answered By - herzbube Answer Checked By - Clifford M. (WPSolving Volunteer)