MantisBT - CMake
View Issue Details
0011332CMakeCMakepublic2010-10-19 06:552011-01-12 07:42
Rolf Eike Beer 
Brad King 
normalminoralways
closedfixed 
CMake-2-8 
CMake 2.8.4CMake 2.8.4 
0011332: No dependency from ADD_CUSTOM_COMMAND to external project
The idea is like this: we have an project that generates a couple of
files. In a special configuration of another project we need those files
as input for a special build step. Those step will take those files,
mangle them and will generate a source file at the end. I simulate this by a simple copy below. This is then added as usual to a library (in my example below to a executable, but that doesn't matter). When I run the example below I get:

[ 80%] Built target Subdir_Build
make[2]: *** No rule to make target `Subdir_Build', needed by `main.c'.
Stop.

The project "Subdir_Build" indeed exists, as "make Subdir_Build" runs fine. And it looks for me as it is properly build before the target depending on it. I have found no way to set a dependency on the external project (tried ADD_CUSTOM_COMMAND(DEPENDS), ADD_DEPENDENCIES, and SET_SOURCE_FILES_PROPERTIES). If CMake can't do this it should give at least an error at CMake time.

Put this into CMakeLists.txt
=== snip ===
PROJECT(MaindirThing C)

CMAKE_MINIMUM_REQUIRED(VERSION 2.8.2)

INCLUDE(ExternalProject)

ExternalProject_Add(Subdir_Build
                PREFIX "${CMAKE_CURRENT_BINARY_DIR}/build_subdir"
                SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/subdir"
                CMAKE_ARGS
"-DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/build_subdir/install"
                INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/build_subdir/install"
)

ADD_CUSTOM_COMMAND(
        OUTPUT "main.c"
        COMMAND ${CMAKE_COMMAND}
        ARGS -E copy ${CMAKE_CURRENT_BINARY_DIR}/build_subdir/install/foo
${CMAKE_CURRENT_BINARY_DIR}/main.c
        DEPENDS Subdir_Build
)

ADD_EXECUTABLE(simple_exe main.c)
=== snap ===

And this goes to subdir/CMakeLists.txt
=== snip ===
PROJECT(SubdirThing NONE)

CMAKE_MINIMUM_REQUIRED(VERSION 2.6)

FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/foo_file "int main(void)\n{\n
return 0;\n}\n")

INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/foo_file DESTINATION .)
=== snap ===
No tags attached.
has duplicate 0012057closed Brad King add_custom_command can not depend on a custom target 
Issue History
2010-10-19 06:55Rolf Eike BeerNew Issue
2010-10-19 07:08Michael WildNote Added: 0022532
2010-10-19 07:09Michael WildNote Edited: 0022532
2010-10-19 07:09Michael WildNote Edited: 0022532
2010-10-19 07:28Michael WildNote Edited: 0022532
2010-10-19 09:12Rolf Eike BeerNote Added: 0022534
2010-10-19 09:32Michael WildNote Added: 0022535
2010-10-19 10:40Rolf Eike BeerNote Added: 0022540
2010-10-19 11:15Michael WildNote Added: 0022541
2010-10-19 12:01Rolf Eike BeerNote Added: 0022543
2010-10-19 13:23Michael WildNote Added: 0022544
2010-11-10 13:11David ColeAssigned To => David Cole
2010-11-10 13:11David ColeStatusnew => assigned
2010-11-10 13:11David ColeTarget Version => CMake 2.8.4
2010-12-08 16:43Brad KingAssigned ToDavid Cole => Brad King
2010-12-08 17:38Brad KingNote Added: 0023827
2010-12-08 17:39Brad KingStatusassigned => closed
2010-12-08 17:39Brad KingResolutionopen => fixed
2011-01-12 07:42David ColeFixed in Version => CMake 2.8.4
2011-04-08 08:56Brad KingRelationship addedhas duplicate 0012057

Notes
(0022532)
Michael Wild   
2010-10-19 07:08   
(edited on: 2010-10-19 07:28)
AFAIK this is a documentation bug. The DEPENDS option of ADD_CUSTOM_COMMAND only works for top-level targets producing a file (i.e. ADD_EXECUTABLE and ADD_LIBRARY). It does not work with custom targets. For this one needs to create a special custom target which DEPENDS on the custom command, and then use ADD_DEPENDENCIES to make the custom target depend on the external project.

This has been discussed on the mailing list already: http://www.mail-archive.com/cmake%40cmake.org/msg32029.html. [^] Eike (the OP and reporter) so far hasn't answered the question whether it works with the custom target.

(0022534)
Rolf Eike Beer   
2010-10-19 09:12   
I tried:

ADD_CUSTOM_TARGET(Subdir_Build_Foo DEPENDS Subdir_Build)
ADD_CUSTOM_COMMAND(OUTPUT "main.c"
     ...
     DEPENDS Subdir_Build_Foo)

I also tried

SET_SOURCE_FILES_PROPERTIES(main.c PROPERTIES OBJECT_DEPENDS Subdir_Build_Foo)

Nothing worked.
(0022535)
Michael Wild   
2010-10-19 09:32   
Wrong:

ADD_CUSTOM_COMMAND(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/main.c"
  ...)
ADD_CUSTOM_TARGET(build_main
  DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/main.c")
ADD_DEPENDENCIES(build_main Subdir_Build_Foo)

Always use absolute paths when dealing with custom commands!
(0022540)
Rolf Eike Beer   
2010-10-19 10:40   
Yes, this works. But honestly, this is butt ugly and beyond the imagination of everyone reading the documentation. Especially since all other ways do not give any error at CMake time but cause build failures.

I still wonder if the Subdir_Build dependency is guaranteed to be built before the main.c dependency when doing parallel builds.
(0022541)
Michael Wild   
2010-10-19 11:15   
It may be ugly, that's true, and it's also not very intuitive, and consequently the documentation of ADD_CUSTOM_COMMAND should be amended and that of ExternalProject_Add could be expanded to explain this pattern.

Also, you can "un-uglify" this if main.c is used in another top-level target:

ADD_CUSTOM_COMMAND(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/main.c"
  ...)
ADD_EXECUTABLE(main "${CMAKE_CURRENT_BINARY_DIR}/main.c")
ADD_DEPENDENCIES(main Subdir_Build_Foo)

This causes Subdir_Build_Foo to be built before the main target.

It works for me in parallel builds.
(0022543)
Rolf Eike Beer   
2010-10-19 12:01   
What I need is that it is build before main.c. In real life that is no simple copy operation but mangling of the output of the external command.
(0022544)
Michael Wild   
2010-10-19 13:23   
Ah, yes, sorry about that. But on the up-side, you can use that custom target to provide a convenience target, e.g:

ADD_CUSTOM_TARGET(mangle
  DEPENDS ${MANGLED_SRCS})
(0023827)
Brad King   
2010-12-08 17:38   
I published a fix:

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

It depends on its parent commit for some minor refactoring:

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