MantisBT - CMake
View Issue Details
0013592CMakeCMakepublic2012-10-16 10:002013-10-07 10:03
Frank Miller 
Peter Kuemmel 
normalminoralways
closedfixed 
x86Linux
 
CMake 2.8.11 
0013592: Ninja: Inefficient Ninja DAG with add_custom_command
The ninja generator is not handling dependencies of custom commands
efficiently. As far as I can tell, it is producing correct builds but
with an only overly conservative DAG.

Here is a toy project:

    cmake_minimum_required( VERSION 2.8.0 )
    project( ndep )

    file( WRITE ${CMAKE_BINARY_DIR}/main.cpp "
    #include <iostream>
    #include \"foo.h\"
    int bar();
    int main()
    {
        std::cout << foo() << bar() << std::endl;
    }
    ")

    file( WRITE ${CMAKE_BINARY_DIR}/foo.in "
    int foo() { return VALUE; }
    ")

    file( WRITE ${CMAKE_BINARY_DIR}/bar.in "
    int bar() { return VALUE; }
    ")

    add_custom_command(
      OUTPUT foo.h
      COMMAND cat ${CMAKE_BINARY_DIR}/foo.in | sed 's/VALUE/4/' > ${CMAKE_BINARY_DIR}/foo.h
      DEPENDS ${CMAKE_BINARY_DIR}/foo.in
    )

    add_custom_command(
      OUTPUT bar.cpp
      COMMAND cat ${CMAKE_BINARY_DIR}/bar.in | sed 's/VALUE/2/' > ${CMAKE_BINARY_DIR}/bar.cpp
      DEPENDS ${CMAKE_BINARY_DIR}/bar.in
    )

    add_executable( ndep main.cpp foo.h bar.cpp )

For this case, using git master, the generated object dependencies are
(in Ninja syntax):
  build main.cpp.o: main.cpp | foo.h bar.cpp
  build bar.cpp.o: bar.cpp | foo.h bar.cpp

If foo.h changes (because of foo.in) then bar.cpp.o will be recompiled
when it need not be. Similarly, main.cpp need not be recompiled if
bar.cpp changes. Also, bar.cpp is stated to be both an explicit and an
implicit dependency of bar.cpp.o.

What we want here is:
  build main.cpp.o: main.cpp || foo.h
  build bar.cpp.o: bar.cpp

I have studied the Ninja generator code a bit and found the logic
responsible for writing the object build statements in
cmNinjaTargetGenerator::WriteObjectBuildStatement(.) on line 554 in
cmNinjaTargetGenerator.cxx. I see that this logic recently changed.
Previously the generated files would have showed up as order-only
dependencies. This is closer to the desired result but still not
perfect. There must be a better way but I am not familiar enough with
cmake internals to know what that is.
No tags attached.
related to 0013559closed Peter Kuemmel Ninja: Wrong dependency with PCH support 
related to 0013988closed Peter Kuemmel Ninja: generated files like moc, huge deps list (bis) 
related to 0013874closed Peter Kuemmel Ninja: generated files like moc, huge deps list 
Issue History
2012-10-16 10:00Frank MillerNew Issue
2012-11-20 16:26Peter KuemmelRelationship addedrelated to 0013559
2013-02-09 07:01Peter KuemmelSummaryInefficient Ninja DAG with add_custom_command => Ninja: Inefficient Ninja DAG with add_custom_command
2013-03-09 06:11Peter KuemmelRelationship addedrelated to 0013988
2013-03-09 06:12Peter KuemmelRelationship addedrelated to 0013874
2013-03-09 06:12Peter KuemmelAssigned To => Peter Kuemmel
2013-03-09 06:12Peter KuemmelStatusnew => assigned
2013-03-09 06:14Peter KuemmelNote Added: 0032551
2013-03-09 06:14Peter KuemmelStatusassigned => resolved
2013-03-09 06:14Peter KuemmelFixed in Version => CMake 2.8.11
2013-03-09 06:14Peter KuemmelResolutionopen => fixed
2013-10-07 10:03Robert MaynardNote Added: 0033988
2013-10-07 10:03Robert MaynardStatusresolved => closed

Notes
(0032551)
Peter Kuemmel   
2013-03-09 06:14   
It's "order only" again, also see other bugs.
(0033988)
Robert Maynard   
2013-10-07 10:03   
Closing resolved issues that have not been updated in more than 4 months.