CMakePCHCompiler icon indicating copy to clipboard operation
CMakePCHCompiler copied to clipboard

Alternative to separate CXXPCH compiler definition

Open drizt opened this issue 5 years ago • 8 comments

In project README

CMake does not allow to insert source file to existing target once it has been defined.

But source can be insert before add_executable/library.

Even if it was possible, we could not ensure precompiled header is built first in main target, but adding it as subtarget we can.

It's possible with OBJECT_DEPENDS property on source files.

We cannot prevent header.pch, which is output of CPCH/CXXPCH compiler from being linked when it is in part of main target, but if we put it into OBJECT library, then by definition we skip linking process. Also we take the result object to be a recompiled header for main target.

Output can be changed witho dummy .o file without code.

project(pchtest CXX)
set(CMAKE_VERBOSE_MAKEFILE ON)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

add_executable(${PROJECT_NAME} "main.cpp" "pch.cpp" "pch.h" "pch_dummy.cpp")
add_compile_options(${PROJECT_NAME} PUBLIC -Wall -Werror -Winvalid-pch)

set_source_files_properties(pch.cpp PROPERTIES COMPILE_OPTIONS "-x;c++-header" OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/pchtest.dir/pch_dummy.cpp.o)

add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/pch.h.gch
    COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/pchtest.dir/pch.cpp.o ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/pch.h.gch
    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/pchtest.dir/pch_dummy.cpp.o ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/pchtest.dir/pch.cpp.o
    COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/pch.h.gch

    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/pchtest.dir/pch.cpp.o
    COMMENT "Copy PCH"
)

set_source_files_properties(main.cpp PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/pch.h.gch COMPILE_OPTIONS "-include;${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/pch.h")

Full example here.

Works with CMake 3.14.3, gcc 8.3.1 and Makefile generator. Ninja generator doesn't works but it seems a CMake bug. I opened an issue here.

drizt avatar May 02 '19 00:05 drizt

Okay, your idea is really fine. But this is completely different approach that one here, so it should be rather brand new project than addition to this one.

If what your are saying it true and there is no caveat and it works better then I am happy and okay to shutdown this repo. 👍

Now you if can provide CMAKE module that does that job, rather than fixed CMakeLists then all I can say is great!

However, note that so far you have generated the PCH but it still has to be included for all other source files which I believe does not happen in the example above. And of course the dependency cycle for Ninja has to be fixed too I believe.

nanoant avatar May 03 '19 14:05 nanoant

My approach doesn't work with Ninja only Make. Also I didn't (and can't) test it with MSVC. I opened an issue on CMake bugtracker. -include doesn't apply for AUTOMOC'ed sources and I can't find how to workaround this.

drizt avatar May 03 '19 14:05 drizt

I rewrite my pch with compile_commands.json. Now it can be build with Makefiles or Ninja on Linux or macOS (Windows MinGW doesn't tested yet). https://travis-ci.org/drizt/pchtest

drizt avatar May 05 '19 19:05 drizt

My PCHLinkTarget module now is almost finished. Yes, it moved to new repository. I tested it with macOS, Linux, MinGW on Windows and MSYS in both Ninja and Makefiles modes. All works file. Also I suscessfully aplied it to my complex project with many modules and pch files.

drizt avatar May 07 '19 18:05 drizt

Great to see the progress. But also keep in mind that you may want to support MSVC. Also wanted to ask why PCHLinkTarget/pch_link_target name? I don't get why there is a word "link" there.

nanoant avatar May 08 '19 10:05 nanoant

I just saved/used your function name. It does the same work but in another way.

drizt avatar May 08 '19 11:05 drizt

That one caught my eye:

CMake does not allow to insert source file to existing target once it has been defined.

It does via target_sources() and maybe directly via the SOURCES target property.

gjasny avatar May 11 '19 13:05 gjasny

target_sources added in CMake 3.1

drizt avatar May 11 '19 13:05 drizt