[CMake] feed parsed information from source files into compile process

Michael Hertling mhertling at online.de
Thu Feb 10 10:45:22 EST 2011


On 02/10/2011 02:11 PM, Verweij, Arjen wrote:
> Thanks Tyler,
> 
>> -----Original Message-----
>> From: Tyler Roscoe [mailto:tyler at cryptio.net]
> 
>> You can't use add_custom_command() to drive this because the results of
>> any custom commands will only be available at build time. You need stuff
>> to happen at CMake configure time.
> 
> I noticed. Add_custom_target(foo ALL ... ) results are only processed at make+1 and not immediately :(
> 
>> Hence, I would use execute_process() to run your python script at
>> configure time. It would deposit its results into a file, which you
>> could then include() (or file(READ ...)).
> 
> While this does work, it will only function properly if cmake needs to run. If for whatever reason (say a -O2/-O3 omp compiler bug in xlf_r ;) ) you change the in-file compiler flags they will not be picked up until you run cmake.
> 
> I'm gonna try a few things, but I'm not too hopeful :P
> 
> Regards,
> Arjen

Possibly, you might do the following in your top-level CMakeLists.txt:

IF(NOT EXITST <file-to-include>)
    EXECUTE_PROCESS(COMMAND <generate-file-to-include>)
ENDIF()
INCLUDE(<file-to-include>)
...
# Add targets/subdirectories/etc.
...
ADD_CUSTOM_TARGET(world
    COMMAND <generate-file-to-include>
    COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}
)

The initial CMake run generates <file-to-include>, includes it and
proceeds as usual. Each following "make world" regenerates <file-to-
include> and rebuilds the project, and if <file-to-include> has been
actually touched, CMake will notice this via the INCLUDE() command and
reconfigure-before-rebuild. Furthermore, if <generate-file-to-include>
takes care of not touching <file-to-include> as long as the latter does
not change - cf. CONFIGURE_FILE() - you will avoid most of the overhead.
If I got your concern right, <file-to-include> is your override.cmake,
and <generate-file-to-include> is your Python script.

The downside is that you can't say just "make" anymore. However, you
may mark the custom target "world" with "ALL", establish dependencies
of the ordinary targets on "world" and find a way to avoid an infinite
recursion. So, you can just say "make", and the ordinary targets will
be built and finally checked for being up to date once more. To avoid
the recursion you could use a CMake script in junction with a marker
file, e.g.

ADD_CUSTOM_TARGET(world ALL
    COMMAND ${CMAKE_COMMAND}
        -D BINDIR=${CMAKE_BINARY_DIR}
        -P ${CMAKE_SOURCE_DIR}/world.cmake
)

and a ${CMAKE_SOURCE_DIR}/world.cmake like:

IF(NOT EXISTS <marker-file>)
    FILE(WRITE <marker-file> "")
    EXECUTE_PROCESS(COMMAND <generate-file-to-include>)
    EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} --build ${BINDIR})
    FILE(REMOVE <marker-file>)
ENDIF()

Of course, this approach is not of maximum elegance, but if your
CMakeLists.txt's dependency on extractable contents of your source
files really matters, there's at least one option how to address it.

'hope that helps.

Regards,

Michael


More information about the CMake mailing list