PCH: TARGET_OBJECTS contains precompiled headers
Description
I recently tried the new cmake feature Linking Object Libraries via $<TARGET_OBJECTS>, but I had some issues to make it work properly with gcc precompiled headers.
I would expect the following cmake code to produce a valid build:
# create an object library
add_library(lib1 OBJECT)
...
target_precompile_headers(lib1 PRIVATE ${CMAKE_SOURCE_DIR}/lib1/precompiledheaders.h)
# create an interface library via TARGET_OBJECTS
target_link_libraries(lib1-interface INTERFACE lib1 $<TARGET_OBJECTS:lib1>)
# create the main target, reuse precompiled headers
add_executable(cmake_bug main.cpp)
target_precompile_headers(cmake_bug REUSE_FROM lib1)
target_link_libraries(cmake_bug PRIVATE lib1-interface)
But instead it fails with the following log:
cmake --build <build-dir> --target cmake_bug
Scanning dependencies of target lib1
[ 25%] Building CXX object CMakeFiles/lib1.dir/cmake_pch.hxx.gch
[ 50%] Building CXX object CMakeFiles/lib1.dir/lib1/lib1.cpp.o
[ 50%] Built target lib1
Scanning dependencies of target cmake_bug
[ 75%] Building CXX object CMakeFiles/cmake_bug.dir/main.cpp.o
[100%] Linking CXX executable cmake_bug
CMakeFiles/lib1.dir/cmake_pch.hxx.gch: file not recognized: file format not recognized
collect2: error: ld returned 1 exit status
make[3]: *** [CMakeFiles/cmake_bug.dir/build.make:97: cmake_bug] Error 1
make[2]: *** [CMakeFiles/Makefile2:111: CMakeFiles/cmake_bug.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:118: CMakeFiles/cmake_bug.dir/rule] Error 2
make: *** [Makefile:137: cmake_bug] Error 2
If you try to compile the minimal reproducible example I crafted and have a look at the generated debug file in <build_dir>/debug
, you will notice that the expansion of $<TARGET_OBJECTS:lib1>
contains the following:
<build_dir>/CMakeFiles/lib1.dir/cmake_pch.hxx.gch;
<build_dir>/CMakeFiles/lib1.dir/lib1/lib1.cpp.o
As a consequence, the cmake generated command in <build_dir>/CMakeFiles/cmake_bug.dir/link.txt
contains a.gch
file
/usr/local/bin/g++ -g CMakeFiles/cmake_bug.dir/main.cpp.o -o cmake_bug CMakeFiles/lib1.dir/cmake_pch.hxx.gch CMakeFiles/lib1.dir/lib1/lib1.cpp.o
while IMO it should just contain the *.o
object files
/usr/local/bin/g++ -g CMakeFiles/cmake_bug.dir/main.cpp.o -o cmake_bug CMakeFiles/lib1.dir/lib1/lib1.cpp.o
Known workarounds
I managed to obtain a successful gcc build by filtering out the gch files with a generator expression such as
target_link_libraries(lib1-interface INTERFACE lib1 $<FILTER:$<TARGET_OBJECTS:lib1>,EXCLUDE,.*\\.gch>)
the generator expression now correctly expands to
<build_dir>/CMakeFiles/lib1.dir/lib1/lib1.cpp.o
and the content of the link.txt
file in this case is the same as if I did
+ target_link_libraries(cmake_bug PRIVATE lib1)
- target_link_libraries(cmake_bug PRIVATE lib1-interface)
You can trigger the successful build in the minimal example by passing -DCOMPILE_WITH_WORKAROUND=on
System Info and toolchain
- OS: Ubuntu 20.04
- Cmake: 3.21.4, 3.22.0-rc2
- Compiler: gcc-9.3.0, gcc-11.1