View Issue Details Jump to Notes ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0013592CMakeCMakepublic2012-10-16 10:002013-10-07 10:03
ReporterFrank Miller 
Assigned ToPeter Kuemmel 
PrioritynormalSeverityminorReproducibilityalways
StatusclosedResolutionfixed 
Platformx86OSLinuxOS Version
Product Version 
Target VersionFixed in VersionCMake 2.8.11 
Summary0013592: Ninja: Inefficient Ninja DAG with add_custom_command
DescriptionThe 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

Additional InformationI 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.
TagsNo tags attached.
Attached Files

 Relationships
related to 0013559closedPeter Kuemmel Ninja: Wrong dependency with PCH support 
related to 0013988closedPeter Kuemmel Ninja: generated files like moc, huge deps list (bis) 
related to 0013874closedPeter Kuemmel Ninja: generated files like moc, huge deps list 

  Notes
(0032551)
Peter Kuemmel (developer)
2013-03-09 06:14

It's "order only" again, also see other bugs.
(0033988)
Robert Maynard (manager)
2013-10-07 10:03

Closing resolved issues that have not been updated in more than 4 months.

 Issue History
Date Modified Username Field Change
2012-10-16 10:00 Frank Miller New Issue
2012-11-20 16:26 Peter Kuemmel Relationship added related to 0013559
2013-02-09 07:01 Peter Kuemmel Summary Inefficient Ninja DAG with add_custom_command => Ninja: Inefficient Ninja DAG with add_custom_command
2013-03-09 06:11 Peter Kuemmel Relationship added related to 0013988
2013-03-09 06:12 Peter Kuemmel Relationship added related to 0013874
2013-03-09 06:12 Peter Kuemmel Assigned To => Peter Kuemmel
2013-03-09 06:12 Peter Kuemmel Status new => assigned
2013-03-09 06:14 Peter Kuemmel Note Added: 0032551
2013-03-09 06:14 Peter Kuemmel Status assigned => resolved
2013-03-09 06:14 Peter Kuemmel Fixed in Version => CMake 2.8.11
2013-03-09 06:14 Peter Kuemmel Resolution open => fixed
2013-10-07 10:03 Robert Maynard Note Added: 0033988
2013-10-07 10:03 Robert Maynard Status resolved => closed


Copyright © 2000 - 2018 MantisBT Team