I originally asked this question on CMake mailing list: How to configure target or command to preprocess C file?
I'm porting build configuration based on GNU Autotools to CMake and I have to deal with C preprocessing to generate a file.
The input for preprocessor is SQL file with C preprocessor directives used, like #include "another.sql"
, etc.
Currently, Makefile
uses the following rule to generate plain SQL
file as output:
myfile.sql: myfile.sql.in.c
cpp -I../common $< | grep -v '^#' > $@
So, the myfile.sql
is meant to be one of products of the build process, similar to share libraries or executables.
What CMake tools should I use to achieve the same effect?
It's unclear to me if I should use add_custom_command
, add_custom_target
or combine both.
Obviously, I'm looking for a portable solution that would work at least with GNU GCC and Visual Studio toolsets. I presume I will have to define platform-specific custom commands, one for cpp
preprocessor, one for cl.exe /P
.
Or, does CMake provide any kind of abstraction for C preprocessor?
I scanned the archives, but I only found preprocessing of fortran files or solutions based on make capabilities: make myfile.i
So, it's not quite what I'm looking for.
UPDATE: Added answer based on solution received from Petr Kmoch on CMake mailing list.
I'm answering the question to myself by copying essential parts of solution received from Petr Kmoch as response to my post in the mailing list.
First, create a custom command using add_custom_command
(version with the OUTPUT signature) to actually do the preprocessing.
For example:
add_custom_command(
OUTPUT myfile.sql
COMMAND "${CMAKE_C_COMPILER}" -E myfile.sql.in -I ../common
MAIN_DEPENDENCY myfile.sql.in
COMMENT "Preprocessing myfile.sql.in"
VERBATIM)
Second, configure the command trigger:
If the command output file (myfile.sql
) is used in another target, added as a source
file added to add_library
or add_executable
, it is enough to specify it in these commands. CMake will find it as a dependency and run the custom command as required.
If the command output file is a final output not used as dependency in
any other targets, then add a custom target to drive the command using add_custom_target
For example:
add_custom_target(
ProcessSQL ALL
DEPENDS myfile.sql
COMMENT "Preprocessing SQL files"
VERBATIM)
Credits: Petr Kmoch
To take advantage of CMake' make myfile.i
feature, you can do this:
add_library(sql_cpp_target EXCLUDE_FROM_ALL myfile.sql.in.c)
Now running make myfile.sql.in.c.i
will produce preprocessed source for you, using defined CMAKE_C_FLAGS
. It might be possible to change output name and dir for preprocessed file.
At any rate, you'd need to wrap these make
invocations into add_custom_target(ALL ...)
to make CMake run them during build.
Use CMAKE_MAKE_PROGRAM
variable in targets definitions.
If you want to abstract from build tool, you can call cmake itself to build a target for you. Use ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target targetname
when defining custom target.
Alternatively, you can just add_custom_command()
which runs specified compiler to preprocess files and put them at the appropriate place. But this seems to be less flexible, IMO.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With