Context:
I have been struggling with this for a while, and it was working when I happened to be generating “.cpp” files, but now with c++17 and the ability to move everything generated to static inline, I no longer require generating cpp fragments, only headers.
I have developed a pre-compiler system that parses ANY source/header files, and generates a header file. (It actually generates two, but that’s an implementation detail)
You declare a target, add your SOURCES AND HEADERS as target_sources, and then pass the target to a function.
Sidenote - The precompiler is written itself with llvm’s libtooling, and understands msvc and gcc style arguments. If there is some other way to register a precompiler that I do not know, please inform me.
Finally, after setting up your target, you invoke pre_compile_target(my_target)
which goes through all the source files added (headers and sources), and generates a custom command that looks like this:
add_custom_command(
OUTPUT ${output_refl_in} ${output_rb_refl_in}
COMMAND
reflector -i ${source_dir} -o ${output_dir} -f ${relpath} #
--driver-mode ${refl_driver_mode} #
${rt_flag} ${ct_flag} # generation flags
${ct_static_init_args} ${rt_static_init_args} #
"$<$<BOOL:${id}>:-I$<SEMICOLON>$<JOIN:${id},$<SEMICOLON>-I$<SEMICOLON>>>" #
"$<$<BOOL:${iid}>:-I$<SEMICOLON>$<JOIN:${iid},$<SEMICOLON>-I$<SEMICOLON>>>" #
"$<$<BOOL:${co}>:-O$<SEMICOLON>\"$<JOIN:${co},\"$<SEMICOLON>-O$<SEMICOLON>\">\">" #
"$<$<BOOL:${ico}>:-O$<SEMICOLON>\"$<JOIN:${ico},\"$<SEMICOLON>-O$<SEMICOLON>\">\">" #
"$<$<BOOL:${cd}>:-D$<SEMICOLON>$<JOIN:${cd},$<SEMICOLON>-D$<SEMICOLON>>>" #
"$<$<BOOL:${icd}>:-D$<SEMICOLON>$<JOIN:${icd},$<SEMICOLON>-D$<SEMICOLON>>>" #
DEPENDS reflector ${abspath}
VERBATIM COMMAND_EXPAND_LISTS)
target_is_interface(is_interface ${target})
if(is_interface)
set(link_type INTERFACE)
set(static_link_type PUBLIC)
else()
set(link_type PUBLIC)
set(static_link_type PRIVATE)
endif()
target_sources(${target} ${link_type} ${output_refl_in}
${output_rb_refl_in})
The generated files end in .refl.in
, the dependent file is either a c++ source file, or header file.
Note that if a.cpp
requires a.h
, and a.h
→ a.h.refl.in
, that a.h.refl.in
must be generated before any source compilation command runs.
Despite adding the a.h.refl.in
as a target_source, cmake simply ignores the dependency and never generates the file.
As far as I know cmake uses implicit dependency scanning (assuming it uses ninja in this case) to find out that a.cpp
depends on a.h
, so why cant I tell cmake that a.h
depends on a.h.refl.in
which is dependent on a.h
itself?