[CMake] Recompiles everything every time

Michael Hertling mhertling at online.de
Thu Feb 10 19:30:31 EST 2011


On 02/10/2011 09:47 PM, Collier, Jack wrote:
> I have a large project that I recently converted from autotools to cmake.  Everything works great save for the fact that everytime I make the project every single source file is recompiled.  I think the reason is that my build relies on a number of custom targets this generate a bunch of header files that are used by almost all the other sources in the project.  According to the documentation for add_custom_target the target is always considered out of date so it will recompile everytime.  Is there anyway to get around this and only compile if something has changed?  I have included one of the custom targets and the associated custom command below:
> 
> 
> #Add command to compile IDL files
> ADD_CUSTOM_TARGET(CompileIdl ALL)
> ADD_CUSTOM_COMMAND(
>         DEPENDS ${TAO_IDL}
>         COMMAND ${TAO_IDL} -in -hc C.h -cs C.cpp -ci C.i.h -hs S.h -hT S_T.h -ss S.cpp -sT S_T.cpp -si S.i.h  ${IDL_INCLUDES} ${SRC_FINAL}
>         TARGET CompileIdl
>         OUTPUTS ${IDL_CLIENT_CPP} ${IDL_CLIENT_H} ${IDL_CLIENT_IH} ${IDL_SERVER_CPP} ${IDL_SERVER_H} ${IDL_SERVER_IH}
>         )
> 
> #Now compile the generated sources
> SET(BUILT_SOURCES ${IDL_CLIENT_CPP} ${IDL_CLIENT_H} ${IDL_CLIENT_IH} ${IDL_SERVER_CPP} ${IDL_SERVER_H} ${IDL_SERVER_IH} )
> SET_SOURCE_FILES_PROPERTIES(${BUILT_SOURCES} PROPERTIES GENERATED true)

Don't attach the custom command to the custom target, but make the
latter depend on the former, i.e. don't use the TARGET signature:

ADD_CUSTOM_COMMAND(
    OUTPUT ${IDL_CLIENT_CPP} ${IDL_CLIENT_H} ${IDL_CLIENT_IH}
           ${IDL_SERVER_CPP} ${IDL_SERVER_H} ${IDL_SERVER_IH}
    COMMAND <whatever-necessary-to-generate-the-output-files>
    DEPENDS <all-prerequisites-of-the-output-files-to-generate>
)
ADD_CUSTOM_TARGET(CompileIdl ALL
    DEPENDS ${IDL_CLIENT_CPP} ${IDL_CLIENT_H} ${IDL_CLIENT_IH}
            ${IDL_SERVER_CPP} ${IDL_SERVER_H} ${IDL_SERVER_IH}
)

Although the custom target is always out of date, the custom command
runs only if an OUTPUT file doesn't exist or a prerequisite after the
DEPENDS clause is newer. For this to work well, it is inevitable that:

1) The custom command carefully denotes all OUTPUT files - BTW, the
   option is named OUTPUT, not OUTPUTS, and you don't need to set the
   GENERATED property for these files explicitly.
2) The custom command carefully denotes all prerequisites of the OUTPUT
   files after the DEPENDS clause, i.e. everything that should trigger
   the OUTPUT files' regeneration when it's changed.
3) The custom target carefully denotes the custom command's OUTPUT
   files as prerequisites after its DEPENDS clause.

If not all of the OUTPUT files depend on each prerequisite after the
DEPENDS clause, consider to use multiple custom commands in order to
reduce the dependency graph as far as possible, but no further. ;)

'hope that helps.

Regards,

Michael


More information about the CMake mailing list