19

I'm noticing some potential incorrect behavior in cmake when working with add_custom_command and multiple output files. I've been able to isolate the problem to a minimal example (see below). It seems that when I have two output files specified in my add_custom_command, the second output file's upstream dependencies are not being tracked correctly in some cases. The cmake documentation clearly mentions that multiple output files are allowed. What's interesting here is that swapping the order of the output files causes different behavior, suggesting that the first OUTPUT file is being treated differently.

Please refer to the toy example below that exhibits this behavior. The first call to make runs just fine. After touching a.txt, the Copying baz.cpp to baz2.cpp rule doesn't execute on the first call to make, but runs on the second call to make. This means that the build will still be stale after a single call to make. Note that this issue is fixed by changing the order of the outputs in add_custom_command to OUTPUT baz.cpp bar.cpp

Example CMakeLists.txt:

cmake_minimum_required(VERSION 2.8)

add_library(mybaz baz.cpp)

add_custom_command(
  OUTPUT  baz2.cpp
  COMMAND cp baz.cpp baz2.cpp
  DEPENDS baz.cpp
  COMMENT "Copying baz.cpp to baz2.cpp")

add_custom_target(mytarget
  DEPENDS baz2.cpp
  COMMENT "Running mytarget")

add_dependencies(mybaz mytarget)

add_custom_command(
  OUTPUT  bar.cpp baz.cpp
  COMMAND cat a.txt > bar.cpp
  COMMAND cat a.txt > baz.cpp
  DEPENDS a.txt
  COMMENT "Generating bar.cpp and baz.cpp")

Below are the commands that I run:

> touch a.txt
> cmake .
    ...snip... (configuration runs fine)
> make
Scanning dependencies of target mytarget
[ 20%] Generating bar.cpp and baz.cpp
[ 40%] Copying baz.cpp to baz2.cpp
[ 60%] Running mytarget
[ 60%] Built target mytarget
Scanning dependencies of target mybaz
[ 80%] Building CXX object CMakeFiles/mybaz.dir/baz.cpp.o
Linking CXX static library libmybaz.a
[100%] Built target mybaz
  (everything looks good)

> touch a.txt
> make
[ 20%] Generating bar.cpp and baz.cpp
[ 40%] Running mytarget
[ 60%] Built target mytarget
Scanning dependencies of target mybaz
[ 80%] Building CXX object CMakeFiles/mybaz.dir/baz.cpp.o
Linking CXX static library libmybaz.a
[100%] Built target mybaz
  (I seem to be missing the 'Copying baz.cpp to baz2.cpp' line)

> make
[ 20%] Copying baz.cpp to baz2.cpp
[ 40%] Running mytarget
[ 60%] Built target mytarget
[100%] Built target mybaz
  ( The 'Copying baz.cpp to baz2.cpp' executes this time )

This has been tested using CMake version 2.8.12.2 on a linux machine.

Thanks in advance for your help!

6
  • 1
    +1 for example, IMHO it is a bug Commented Jun 26, 2014 at 18:24
  • I have a couple questions. 1) Is the custom target mytarget necessary to reproduce the problem? 2) Why aren't the files bar.cpp and baz2.cpp added to the library? Commented Aug 8, 2014 at 17:57
  • This may not be a bug in CMake, it could be a filesystem race condition. Have you filed a bug report with CMake? Commented Aug 28, 2014 at 16:44
  • @Beanz Could you maybe explain what you mean by a filesystem race condition? My understanding was that Make is designed to deal with these issues. That is, Make is designed to wait to run the next command until its source files exist. Commented Aug 29, 2014 at 17:16
  • @Beanz Good call regarding filing a bug report with CMake. It's now available here: cmake.org/Bug/view.php?id=15116 Commented Aug 29, 2014 at 17:18

1 Answer 1

8

This is in fact a bug in CMake 2.8.12.1. According to the CMake folks, the first output is being treated specially by the Makefile generator (though, there probably isn't a reason for it to be treated specially). A fix to CMake has been made, and is targeted for CMake 3.2.

See the CMake bugreport: http://www.cmake.org/Bug/view.php?id=15116

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.