[CMake] custom target isn't rebuilt if depending on another custom target
Michael Hertling
mhertling at online.de
Mon Sep 13 23:55:43 EDT 2010
On 09/13/2010 05:46 PM, Gerhard Stengel wrote:
> Hi,
>
> I have a strange problem with custom targets and their dependencies. I do as follows:
>
> 1) create a file 1 and add it to a custom target 1
> 2) create a file 2 and add it to a custom target 2
> 3) create a 3rd file by packing #1 and #2 together
> 4) the 3rd file is added to a custom target which depends on custom targets 1 and 2
>
> This is an example CMakeLists.txt:
>
> ----snip ---
>
> add_custom_command(OUTPUT Demo1.out
> COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/Demo1.in Demo1.out
> DEPENDS Demo1.in)
> add_custom_target(cust1 ALL DEPENDS Demo1.out)
>
> add_custom_command(OUTPUT Demo2.out
> COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/Demo2.in Demo2.out
> DEPENDS Demo2.in)
> add_custom_target(cust2 ALL DEPENDS Demo2.out)
>
> #this would work correctly in all cases
> #add_custom_command(OUTPUT Demo.tar
> # COMMAND ${CMAKE_COMMAND} -E tar cvf Demo.tar Demo1.out Demo2.out
> # DEPENDS Demo1.out Demo2.out)
>
> #without file level dependencies it isn't correctly rebuilt
> add_custom_command(OUTPUT Demo.tar
> COMMAND ${CMAKE_COMMAND} -E tar cvf Demo.tar Demo1.out Demo2.out)
>
> add_custom_target(cust3 ALL DEPENDS Demo.tar)
> add_dependencies(cust3 cust1 cust2)
>
> ----snip ---
>
> If I create Demo.tar from a clean project, everything's fine. However, the rebuilt isn't performed completely, that is
> if I touch Demo1.in, just Demo1.out is rebuilt, but not Demo.tar that depends on it! [...]
Demo.tar does *not* depend on Demo1.out; it has no dependencies at all.
As a proof - if on *nix - issue "find . -exec grep "Demo\.tar" {} \;"
in the build directory after cmaking, and you'll see that Demo.tar's
dependency line doesn't mention any prerequisites after the colon.
> [...] This seems wrong to me because I
> expect that if the target cust1 is rebuild, even the target cust3 has to be rebuilt due to the relation established by
> the add_dependencies() command!
Rebuilding cust3 doesn't regenerate Demo.tar due to its lack of
dependencies if it already exists. So, Demo.tar is generated at
the first time and that's it, unless the file is removed later.
> The problem seems to be that add_dependencies() doesn't realize that if cust1 or cust2 becomes out of date cust3 has to
> be rebuilt, too.
It does, but rebuilding cust3 doesn't do what you expect, see above.
> The solution using file level dependencies (see commented out command) would work, [...]
...and is the correct one...
> [...] but in my project it's not really
> possible to do so because the "source" custom targets which the "final" custom target takes as input contain lots of
> files.
First of all, is it possible to simplify your CMakeLists.txt? Unless
you really need cust{1,2} as top-level targets they aren't necessary
if Demo{1,2}.out are mentioned as dependencies in Demo.tar's custom
command and if these commands all reside in the same CMakeLists.txt.
Furthermore, you could even use
ADD_CUSTOM_TARGET(Demo.tar ALL
COMMAND ${CMAKE_COMMAND} -E tar cvf Demo.tar Demo1.out Demo2.out
DEPENDS Demo1.out Demo2.out)
instead of Demo.tar's custom command if you don't need Demo.tar as an
ingredient for another target and, again, if these commands/targets
are defined in the same CMakeLists.txt.
> Is there an easy workaround or is this a cmake bug?
No bug. ;) Without further knowledge of your project, the best advice
one can give is to use lists, loops, functions and properties to cope
with large numbers of files in the CMakeLists.txt.
'hope that helps.
Regards,
Michael
More information about the CMake
mailing list