[CMake] Question about add_custom_command
Michael Hertling
mhertling at online.de
Sat Sep 11 23:56:52 EDT 2010
On 09/10/2010 05:25 PM, Ingolf Steinbach wrote:
> 2010/9/10 Michael Wild <themiwi at gmail.com>:
>>> Does this also create dependencies on the multitude of header files
>>> included by the .c files in SRCS (which would probably be desired in
>>> case of the OP)?
>>>
>>> Ingolf
>>
>> No, it will not. But usually you have anyways something like:
>>
>> set(SRCS a.c b.c c.h d.c e.c)
>> set(HDRS a.h b.h c.h d.h e.h)
>
> Which would still fail if some of the .c files also depend on, say, a
> headers-only library (C++ templates) from another part of the project.
Yes, one has to explicitly mention *all* files the modification of
which should trigger a regeneration of the custom command's output.
> Isn't there some simple mechanism which
> - creates an auto_created.c file
> - compiles this auto_created.c file with the default flags for the project
> - links the target "foo" using the object files derived from the
> "normal" sources and this auto_created.c file
> whenever "foo" needs to be re-built (or maybe whenever make enters the
> directory containing "foo")?
That's difficult as a custom command isn't triggered if any file not
mentioned in the DEPENDS clause has changed, and a custom target is
triggered each time even if no file has changed. Nevertheless, it
can be achieved by a somewhat adventurous approach:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(AUTO_CREATED C)
FILE(WRITE ${CMAKE_BINARY_DIR}/rebuild.cmake "
IF(NOT EXISTS ${CMAKE_BINARY_DIR}/rebuild.touch)
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E
touch ${CMAKE_BINARY_DIR}/rebuild.touch)
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E
remove ${CMAKE_BINARY_DIR}/auto_created.c)
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} --build
${CMAKE_CURRENT_BINARY_DIR} --target foo)
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E
remove ${CMAKE_BINARY_DIR}/rebuild.touch)
ENDIF()
")
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E
touch ${CMAKE_BINARY_DIR}/auto_created.c)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_BINARY_DIR}/auto_created.c
COMMAND ${CMAKE_COMMAND} -E
echo "/* auto_created.c */" > ${CMAKE_BINARY_DIR}/auto_created.c
VERBATIM)
FILE(WRITE ${CMAKE_BINARY_DIR}/foo.c "int main(void){return 0;}\n")
ADD_EXECUTABLE(foo foo.c auto_created.c)
ADD_CUSTOM_COMMAND(TARGET foo PRE_LINK
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/rebuild.cmake)
The rebuild.cmake script is executed before the target foo is linked.
Effectively, it removes auto_created.c and rebuilds foo using CMake's
--build option; rebuild.touch is necessary to break the recursion as a
cached variable can't be used in a script invoked by "-P". Finally, the
missing auto_created.c triggers its regeneration by the custom command.
Thus, touching foo.c causes the regeneration of auto_created.c although
the former isn't mentioned in the DEPENDS clause of the latter's custom
command. The downside is that foo gets linked twice; however, no file
is compiled or generated more than once during a rebuild of foo.
Whether this mechanism is simple... [left to your judgement]
> Maybe there is a way to derive the name of the object files resulting
> from SRCS and then have auto_created.c depend on those object files?
The object files reside in the CMakeFiles subdirectories, so I would
advise against referring to them unless it is officially documented.
Regards,
Michael
More information about the CMake
mailing list