View Issue Details Jump to Notes ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0012311CMakeCMakepublic2011-06-30 03:522016-06-10 14:31
ReporterMarcel Loose 
Assigned ToMarcel Loose 
PrioritynormalSeveritymajorReproducibilityalways
StatusclosedResolutionmoved 
PlatformOSOS Version
Product VersionCMake 2.8.4 
Target VersionFixed in Version 
Summary0012311: add_custom_command documentation should warn against use in multiple independent targets
DescriptionWhen two or more targets depend on a source that is generated by a custom command, then the rule to create this source is executed more than once when doing a parallel build. This may even result in a corrupt source as can be demonstrated (see Steps to Reproduce)
Steps To Reproduce1. Create the following files:

::::::::::::::
CMakeLists.txt
::::::::::::::
cmake_minimum_required(VERSION 2.6)
project(Parallel_Generated)

add_custom_command(OUTPUT hello.cc
  COMMAND ${CMAKE_COMMAND}
          -DINFILE=${CMAKE_SOURCE_DIR}/hello.txt
          -P ${CMAKE_SOURCE_DIR}/generate.cmake
  DEPENDS hello.txt
)

set_source_files_properties(hello.cc PROPERTIES GENERATED TRUE)
include_directories(${CMAKE_BINARY_DIR})

add_executable(one one.cc hello.cc)
add_executable(two two.cc hello.cc)

::::::::::::::
generate.cmake
::::::::::::::
file(WRITE hello.cc "
#include <iostream>
void hello(const char* prefix)
{
")
file(STRINGS "${INFILE}" lines)
foreach(line ${lines})
  file(APPEND hello.cc "
  std::cout << prefix << \": ${line}\" << std::endl;
  ")
endforeach(line)
file(APPEND hello.cc "
}
")
::::::::::::::
hello.txt
::::::::::::::
Hello World.
I'm foo bar baz.

::::::::::::::
one.cc
::::::::::::::
extern void hello(const char*);
int main()
{
  hello("one");
  return 0;
}
::::::::::::::
two.cc
::::::::::::::
extern void hello(const char*);
int main()
{
  hello("two");
  return 0;
}

2. Create a build directory and run cmake from there.

3. Run the following bash-command line

   $ while true; do make clean; make -j2 || break; done

You'll notice that for each build there are two lines "Generating ..."
Sooner or later, after a few (re)builds, the build fail. Checking the generated source will explain why.
Additional InformationReferences:
http://www.mail-archive.com/cmake@cmake.org/msg37021.html [^]
http://www.mail-archive.com/cmake@cmake.org/msg36403.html [^]
http://www.mail-archive.com/cmake@cmake.org/msg32782.html [^]
TagsNo tags attached.
Attached Files

 Relationships

  Notes
(0026998)
Brad King (manager)
2011-06-30 08:49

This comes up somewhat frequently, but CMake does not have enough information to resolve the case in all generators. It must choose a target in which to put the command. It cannot introduce extra inter-target dependencies or new targets arbitrarily.

I consider this a documentation issue, so I've updated the summary accordingly.
(0026999)
Brad King (manager)
2011-06-30 08:51

Documentation updated:

  http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0ece8f79 [^]

This warning is now prominent in the documentation. Future mailing list queries about this problem can now be answered by pointing at it.
(0027001)
Marcel Loose (developer)
2011-07-01 07:29

IMHO, this issue is not resolved by only updating the documentation.

I understand from your note that, although CMake doesn't have enough information to resolve the case, it can at least detect it. A CMake WARNING or ERROR would be more appropriate, because the logic of the CMakeLists.txt files is apparently wrong.
(0027002)
Brad King (manager)
2011-07-01 08:45

That's like asking Make to warn if it thinks there is a missing dependency.

It may be possible, but will require non-trivial analysis. One will need to extract a subgraph of the target dependency graph consisting only of targets that include a given custom command. Then make sure the graph forms a DAG leading to exactly one "root" target that generates the file. The analysis will need to be repeated for every custom command.

(0027003)
Marcel Loose (developer)
2011-07-01 09:31

Just out of curiosity. But how does CMake handle situations where two targets depend on the same library to be built. Isn't that situation comparable?
(0027004)
Brad King (manager)
2011-07-01 09:35

Inter-target dependencies are explicit:

  target_link_libraries(myexe1 mylib)
  target_link_libraries(myexe2 mylib)

The generated build system will not even start evaluating the file-level dependencies of either executable until the mylib target has been fully evaluated and completed. By the time myexe1 and myexe2 even start to build the library is up to date.
(0041856)
Kitware Robot (administrator)
2016-06-10 14:28

Resolving issue as `moved`.

This issue tracker is no longer used. Further discussion of this issue may take place in the current CMake Issues page linked in the banner at the top of this page.

 Issue History
Date Modified Username Field Change
2011-06-30 03:52 Marcel Loose New Issue
2011-06-30 08:49 Brad King Note Added: 0026998
2011-06-30 08:49 Brad King Assigned To => Brad King
2011-06-30 08:49 Brad King Status new => assigned
2011-06-30 08:49 Brad King Summary Parallel builds may fail when using add_custom_command => add_custom_command documentation should warn against use in multiple independent targets
2011-06-30 08:51 Brad King Note Added: 0026999
2011-06-30 08:51 Brad King Status assigned => resolved
2011-06-30 08:51 Brad King Resolution open => fixed
2011-07-01 07:29 Marcel Loose Note Added: 0027001
2011-07-01 07:29 Marcel Loose Status resolved => feedback
2011-07-01 07:29 Marcel Loose Resolution fixed => reopened
2011-07-01 08:45 Brad King Note Added: 0027002
2011-07-01 08:45 Brad King Assigned To Brad King => Marcel Loose
2011-07-01 08:45 Brad King Status feedback => backlog
2011-07-01 09:31 Marcel Loose Note Added: 0027003
2011-07-01 09:35 Brad King Note Added: 0027004
2016-06-10 14:28 Kitware Robot Note Added: 0041856
2016-06-10 14:28 Kitware Robot Status backlog => resolved
2016-06-10 14:28 Kitware Robot Resolution reopened => moved
2016-06-10 14:31 Kitware Robot Status resolved => closed


Copyright © 2000 - 2018 MantisBT Team