[cmake-developers] [CMake 0013057]: Dependencies do not work (well) across directories

Mantis Bug Tracker mantis at public.kitware.com
Wed Mar 21 07:48:23 EDT 2012


The following issue has been SUBMITTED. 
====================================================================== 
http://public.kitware.com/Bug/view.php?id=13057 
====================================================================== 
Reported By:                Remko
Assigned To:                
====================================================================== 
Project:                    CMake
Issue ID:                   13057
Category:                   CMake
Reproducibility:            always
Severity:                   major
Priority:                   normal
Status:                     new
====================================================================== 
Date Submitted:             2012-03-21 07:48 EDT
Last Modified:              2012-03-21 07:48 EDT
====================================================================== 
Summary:                    Dependencies do not work (well) across directories
Description: 
When a project is spread over a main directory and a subdirectory it becomes
virtually impossible to properly set dependencies in the main directory on
targets built in a
subdirectory. Although the target in the subdirectory is made, there is no
"knowledge" in the main directory whether that target was REmade so that
dependent targets in
the main directory should be remade as well.

Steps to Reproduce: 
Consider the following example which only needs a CMakeLists.txt file and some
dummy c.txt file:
# CMakeLists.txt
cmake_minimum_required (VERSION 2.8)
add_custom_target (a_txt DEPENDS a.txt)
add_custom_command (OUTPUT a.txt COMMAND cat {b,b}.txt > a.txt DEPENDS b.txt)
add_custom_command (OUTPUT b.txt COMMAND paste {c,c}.txt > b.txt DEPENDS c.txt)

After running cmake, "make a_txt" will properly make "b.txt", then "c.txt". And
if I later change "c.txt", both "b.txt" and "a.txt" are updated as well when
running "make
a_txt" again.

Now split this over one file CMakeLists.txt and one in subdirectory sub:
# CMakeLists.txt
cmake_minimum_required (VERSION 2.8)
add_subdirectory (sub)
add_custom_target (a_txt DEPENDS a.txt)
add_custom_command (OUTPUT a.txt COMMAND cat sub/{b,b}.txt > a.txt DEPENDS
sub/b.txt)

# sub/CMakeLists.txt
add_custom_command (OUTPUT b.txt COMMAND paste {c,c}.txt > b.txt DEPENDS c.txt)

One would expect this to work exactly the same. However, this doesn't work. You
well get an error "do not know how to build sub/b.txt".
Instead, one now needs to create a target b_txt. That's not a problem. So we
create this:

# CMakeLists.txt
cmake_minimum_required (VERSION 2.8)
add_custom_target (a_txt DEPENDS a.txt)
add_custom_command (OUTPUT a.txt COMMAND cat sub/{b,b}.txt > a.txt DEPENDS
b_txt)
add_subdirectory (sub)

# sub/CMakeLists.txt
add_custom_target (b_txt DEPENDS b.txt)
add_custom_command (OUTPUT b.txt COMMAND paste {c,c}.txt > b.txt DEPENDS c.txt)

It it true that when running "make a_txt", we do get a "b.txt" and "c.txt".
However, when I update c.txt, then run "make a_txt", then b.txt is updated, but
NOT a.txt. This
is DISASTROUS if you build, say, some library in a subdirectory, but there no
longer is a WORKING dependency on that library in the main directory.

The ONLY solution to this is that dependency in the main directory should
INCLUDE NOT ONLY the target but ALSO the files in the subdirectory. EITHER one
is not sufficient.
The solution is this:
# CMakeLists.txt
cmake_minimum_required (VERSION 2.8)
add_subdirectory (sub)
add_custom_target (a_txt DEPENDS a.txt)
add_custom_command (OUTPUT a.txt COMMAND cat sub/{b,b}.txt > a.txt DEPENDS b_txt
sub/b.txt)

# sub/CMakeLists.txt
add_custom_target (b_txt DEPENDS b.txt)
add_custom_command (OUTPUT b.txt COMMAND paste {c,c}.txt > b.txt DEPENDS c.txt)

In this example this is an annoyance, though still tractable. However, when
depending on a lot of targets, this becomes much more complex. Besides, in the
SUBdirectory it
already says the b_txt depends on b.txt, why would I need to repeat that in the
main directory AGAIN. Isn't that exactly one of those things CMake was intended
to avoid.

Additional Information: 
This problem is mainly caused by the way CMake creates makefiles. What CMake
basically does in the case of the split directories is to create the following
Makefile:

a_txt:    b_txt
    make a.txt

a.txt:
    cat sub/{b,b}.txt > $@

b_txt:
    make sub/b.txt

sub/b.txt: sub/c.txt
    paste {c,c}.txt > $@

Here you clearly see the problem. The b_txt target spawns its own "make"
command, but without dependencies, b_txt really doesn't know whether an update
took place or now.
Thus I can update c.txt without updating a.txt
====================================================================== 

Issue History 
Date Modified    Username       Field                    Change               
====================================================================== 
2012-03-21 07:48 Remko          New Issue                                    
======================================================================



More information about the cmake-developers mailing list