Share pre-compiled header object

I have a whole bunch of unit tests that share the headers of Google Test and a bunch of common includes. Many targets, same PCH. I noticed that inheriting an INTERFACE library as per the docs will create multiple PCH files, one for each target with identical content. The REUSE_FROM method promotes an arbitrary target as something other targets depend on. It’s problematic from an both logical perspective and it precludes writing macros to declare unit tests, because the target to reuse from has not been declared (fed to the macro) yet.

As a test I resorted to a similar method depicted here by creating an object library that I link to. The following sample has two source files sharing the same pre-compiled header consisting of Common.hpp

cmake_minimum_required(VERSION 3.16)

project(InheritPCH LANGUAGES CXX)

file(GENERATE
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/PCH.cpp
  CONTENT ""
)

add_library(PCH OBJECT
  ${CMAKE_CURRENT_BINARY_DIR}/PCH.cpp
)

target_precompile_headers(PCH
  PRIVATE
    Common.hpp
)

target_include_directories(PCH
  PRIVATE
    ${CMAKE_CURRENT_LIST_DIR}
)

foreach(Target IN ITEMS
  Main1
  Main2
)
  add_executable(${Target}
    ${Target}.cpp
  )

  target_precompile_headers(${Target}
    REUSE_FROM
      PCH
  )
endforeach()

The problem with this approach is that it requires a dummy empty source file, because OBJECT libraries cannot be empty. Building this project with Ninja looks like:

[main] Building folder: CPPTest 
[build] Starting build
[proc] Executing command: C:\Kellekek\Kitware\CMake\3.17.2\bin\cmake.exe --build c:/Users/mnagy/Source/CPPTest/.vscode/build --config Debug --target all -- -j 18
[build] [1/6  16% :: 0.635] Building CXX object CMakeFiles\PCH.dir\cmake_pch.cxx.obj
[build] [2/6  33% :: 0.691] Building CXX object CMakeFiles\PCH.dir\PCH.cpp.obj
[build] [4/6  50% :: 0.748] Building CXX object CMakeFiles\Main1.dir\Main1.cpp.obj
[build] [5/6  66% :: 0.755] Building CXX object CMakeFiles\Main2.dir\Main2.cpp.obj
[build] [6/6  83% :: 1.453] Linking CXX executable Main1.exe
[build] [6/6 100% :: 1.453] Linking CXX executable Main2.exe
[build] Build finished with exit code 0

But PCH.cpp.obj is totally unnecessary.

Would it be possible to create a target with no extra object files, just cmake_pch.cxx.obj to share with correct /Yu and /Yc respectively?

The target needs to have a source file in order to know which type of language the target supports.

I have tried fixing this issue in the past and gave up due to the solution being more complicated than having an empty source file added to the build.

You can use file(GENERATE) to generate the file so that you won’t get rebuilds after running cmake.