Reputation: 38912
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.
Upvotes: 11
Views: 8240
Reputation: 34401
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.
Upvotes: 6
Reputation: 38912
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
Upvotes: 9