Precompiled headers don't work when CMAKE_OSX_ARCHITECTURES has more than one value (iOS multi-arch)
Here's the sample project:
# Configure with
# $ cmake . -DCMAKE_SYSTEM_NAME=iOS
# Build with
# $ ninja -v
cmake_minimum_required(VERSION 3.17)
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "")
project(ios_pch_multi_arch LANGUAGES CXX)
set(source "${CMAKE_CURRENT_BINARY_DIR}/source.cpp")
file(WRITE "${source}" "void foo() {}\n")
set(header "${CMAKE_CURRENT_BINARY_DIR}/header.h")
file(WRITE "${header}" "void foo();\n")
add_library(foo STATIC "${source}")
target_precompile_headers(foo PRIVATE "${header}")
target_compile_options(foo PRIVATE "-v")
And the build failure:
Building CXX object CMakeFiles/foo.dir/cmake_pch.hxx.pch
FAILED: CMakeFiles/foo.dir/cmake_pch.hxx.pch
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -arch arm64 -arch x86_64 -Xarch_arm64 -isysroot/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk -Xarch_x86_64 -isysroot/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.2.sdk -miphoneos-version-min=10 -v -Xclang -emit-pch -Xclang -include -Xclang /Volumes/T3/Dev/projects/cmake/ios/pch_multi_arch_failure/build/CMakeFiles/foo.dir/cmake_pch.hxx -MD -MT CMakeFiles/foo.dir/cmake_pch.hxx.pch -MF CMakeFiles/foo.dir/cmake_pch.hxx.pch.d -o CMakeFiles/foo.dir/cmake_pch.hxx.pch -c CMakeFiles/foo.dir/cmake_pch.hxx.cxx
Apple clang version 11.0.0 (clang-1100.0.33.17)
Target: x86_64-apple-darwin19.2.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple arm64-apple-ios10.0.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -Werror=implicit-function-declaration -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name cmake_pch.hxx.cxx -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fno-strict-return -masm-verbose -munwind-tables -faligned-alloc-unavailable -target-sdk-version=13.2 -target-cpu cyclone -target-feature +fp-armv8 -target-feature +neon -target-feature +crypto -target-feature +zcm -target-feature +zcz -target-feature +sha2 -target-feature +aes -target-abi darwinpcs -fallow-half-arguments-and-returns -dwarf-column-info -debugger-tuning=lldb -ggnu-pubnames -target-linker-version 530 -v -coverage-notes-file /Volumes/T3/Dev/projects/cmake/ios/pch_multi_arch_failure/build/CMakeFiles/foo.dir/cmake_pch.hxx.gcno -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.0 -dependency-file CMakeFiles/foo.dir/cmake_pch.hxx.pch.d -skip-unused-modulemap-deps -sys-header-deps -MT CMakeFiles/foo.dir/cmake_pch.hxx.pch -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk -stdlib=libc++ -internal-isystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1 -Wno-framework-include-private-from-public -Wno-atimport-in-framework-header -Wno-extra-semi-stmt -Wno-quoted-include-in-framework-header -fdeprecated-macro -fdebug-compilation-dir /Volumes/T3/Dev/projects/cmake/ios/pch_multi_arch_failure/build -ferror-limit 19 -fmessage-length 0 -stack-protector 1 -mdarwin-stkchk-strong-link -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fobjc-runtime=ios-10.0.0 -fcxx-exceptions -fexceptions -fmax-type-align=16 -fdiagnostics-show-option -emit-pch -include /Volumes/T3/Dev/projects/cmake/ios/pch_multi_arch_failure/build/CMakeFiles/foo.dir/cmake_pch.hxx -o /var/folders/b0/d9_cv_011jvdl2kt9z25np080000gn/T/cmake_pch-8db374.o -x c++ CMakeFiles/foo.dir/cmake_pch.hxx.cxx
clang -cc1 version 11.0.0 (clang-1100.0.33.17) default target x86_64-apple-darwin19.2.0
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/usr/include/c++/v1"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/usr/local/include"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/Library/Frameworks"
#include "..." search starts here:
#include <...> search starts here:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.0/include
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/usr/include
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/System/Library/Frameworks (framework directory)
End of search list.
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple x86_64-apple-ios10.0.0-simulator -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -Werror=implicit-function-declaration -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name cmake_pch.hxx.cxx -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fno-strict-return -masm-verbose -munwind-tables -faligned-alloc-unavailable -target-sdk-version=13.2 -target-cpu core2 -dwarf-column-info -debugger-tuning=lldb -ggnu-pubnames -target-linker-version 530 -v -coverage-notes-file /Volumes/T3/Dev/projects/cmake/ios/pch_multi_arch_failure/build/CMakeFiles/foo.dir/cmake_pch.hxx.gcno -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.0 -dependency-file CMakeFiles/foo.dir/cmake_pch.hxx.pch.d -skip-unused-modulemap-deps -sys-header-deps -MT CMakeFiles/foo.dir/cmake_pch.hxx.pch -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.2.sdk -stdlib=libc++ -internal-isystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1 -Wno-framework-include-private-from-public -Wno-atimport-in-framework-header -Wno-extra-semi-stmt -Wno-quoted-include-in-framework-header -fdeprecated-macro -fdebug-compilation-dir /Volumes/T3/Dev/projects/cmake/ios/pch_multi_arch_failure/build -ferror-limit 19 -fmessage-length 0 -stack-protector 1 -mdarwin-stkchk-strong-link -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fobjc-runtime=ios-10.0.0 -fcxx-exceptions -fexceptions -fmax-type-align=16 -fdiagnostics-show-option -emit-pch -include /Volumes/T3/Dev/projects/cmake/ios/pch_multi_arch_failure/build/CMakeFiles/foo.dir/cmake_pch.hxx -o /var/folders/b0/d9_cv_011jvdl2kt9z25np080000gn/T/cmake_pch-06eb0e.o -x c++ CMakeFiles/foo.dir/cmake_pch.hxx.cxx
clang -cc1 version 11.0.0 (clang-1100.0.33.17) default target x86_64-apple-darwin19.2.0
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.2.sdk/usr/include/c++/v1"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.2.sdk/usr/local/include"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.2.sdk/Library/Frameworks"
#include "..." search starts here:
#include <...> search starts here:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.0/include
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.2.sdk/usr/include
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.2.sdk/System/Library/Frameworks (framework directory)
End of search list.
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo -create -output
CMakeFiles/foo.dir/cmake_pch.hxx.pch /var/folders/b0/d9_cv_011jvdl2kt9z25np080000gn/T/cmake_pch-8db374.o /var/folders/b0/d9_cv_011jvdl2kt9z25np080000gn/T/cmake_pch-06eb0e.o
fatal error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo: can't figure out the architecture type of: /var/folders/b0/d9_cv_011jvdl2kt9z25np080000gn/T/cmake_pch-8db374.o
clang: error: lipo command failed with exit code 1 (use -v to see invocation)
The compilation of the precompiled header fails when lipo tries to create the fat pch file. It's interesting that Apple provided support for fat libraries / object files, but not pch files.
In any case in Qt5 with qmake we handle this by compiling a .pch file for each combination of language * architecture * configuration, and then consuming them via -Xarch flags.
e.g.
# produce
clang++ -x c++-header -c qt_pch.h -o .pch/debug/Qt5Core_debug_x86_64.pch/c++_x86_64.pch .........
# repeat for c,cxx,obj-c,obj-cxx * debug/release * arm64/x86_46
# consume
clang++ -c -Xarch_arm64 -include.pch/debug/Qt5Core_debug_arm64.pch/c++_arm64 -Xarch_x86_64 -include.pch/debug/Qt5Core_debug_x86_64.pch/c++_x86_64 .....
When implementing the fix for #19534 (closed) we kind of forgot about PCH, so it was an oversight in that regard.
Would such a fix be acceptable for CMake? This only really affects iOS multi-arch in CMake at the moment.