[CMake] DEPENDS fails on a target created by add_custom_target

Giampiero Salvi giampi at kth.se
Thu Aug 28 15:39:16 EDT 2008


Giampiero Salvi wrote:
> Here is some valuable info:
> cmake version 2.6-patch 1
> system: Ubuntu Hardy
> 
> Giampiero
> 
> Giampiero Salvi wrote:
>> Dear list,
>> I am a bit confused on the use of add_custom_target, I hope someone 
>> can help me.
>>
>> Here is what I am trying to do:
>> I have a number of subdirectories that build libraries, and then I 
>> build the final executable with a custom command (I am wrapping all 
>> the libraries in a tclkit executable). Some libraries consist of c++ 
>> code, others of just tcl code (I just need to copy the tcl files at 
>> compilation time).
>>
>> Here is how I tried to do it:
>> - In case of c++ libraries I use add_library,
>> - in case of pure tcl libraries I use add_custom_command and 
>> add_custom_target to copy the files (I do not use configure_file 
>> because I want to copy the files at build time and not configuration 
>> time).
>> - In the main CMakeLists.txt I use add_custom_command and 
>> add_custom_target to wrap the libraries into an tclkit executable.
>>
>> Here is the problem:
>> when I use DEPENDS in the main add_custom_command, it finds the 
>> targets generated by add_library, but it complains about the ones 
>> generated by add_custom_target with a "No rule to make target" even 
>> though the targets are built ("[ 82%] Built target targetB")
>>
>> Here is a simplified example (in case the above didn't make too much 
>> sense):
>>
>> main_dir/CMakeLists.txt: --------------------
>> PROJECT(main)
>> subdirs(dirA dirB)
>> ADD_CUSTOM_COMMAND(
>>   OUTPUT ${EXECUTABLE_OUTPUT_PATH}/main_custom${CMAKE_EXECUTABLE_SUFFIX}
>>   COMMAND wrap_libs_to_tclkit_exe
>>   DEPENDS targetA targetB
>> )
>> ADD_CUSTOM_TARGET(main_custom ALL
>>   DEPENDS ${EXECUTABLE_OUTPUT_PATH}/main_custom${CMAKE_EXECUTABLE_SUFFIX}
>> )
>>
>> main_dir/dirA/CMakeLists.txt: -----------------
>> PROJECT(targetA)
>> ADD_LIBRARY(${PROJECT_NAME} SHARED file1.cxx file2.cxx file3.cxx)
>> TARGET_LINK_LIBRARIES(${PROJECT_NAME} blabla)
>>
>> main_dir/dirB/CMakeLists.txt: -----------------
>> PROJECT(targetB)
>> SET(TCL_FILES file1.tcl file2.tcl file3.tcl)
>> ADD_CUSTOM_TARGET(${PROJECT_NAME} ALL)
>> FOREACH(file ${TCL_FILES})
>>   GET_FILENAME_COMPONENT(name ${file} NAME)
>>   SET(tgt ${LIBRARY_OUTPUT_PATH}/${name})
>>   SET(src ${file})
>>   ADD_CUSTOM_COMMAND(
>>     TARGET ${PROJECT_NAME}
>>     COMMAND ${CMAKE_COMMAND}
>>     ARGS -E copy_if_different ${src} ${tgt}
>>     DEPENDS ${src}
>>     COMMENT "copying file: ${src} ${tgt}"
>>     )
>> ENDFOREACH(file)
>>
>> The result is that both targetA and targetB are built, but when 
>> building main_custom I get the "No rule to make target `targetB'" 
>> problem. I don't get any error with only targets on the same type as 
>> targetA.
>>
>> What am I doing wrong?

Hi again, using ADD_DEPENDENCIES works, but I don't understand why. In 
fact, from many posts in the list, it is clarified that DEPENDS in 
ADD_CUSTOM_TARGET only works for file-level dependencies, whereas 
DEPENDS in ADD_CUSTOM_COMMAND also works at target-level deps. I was 
using DEPENDS in ADD_CUSTOM_COMMAND and thus expected it to work.

The fix in the above example is to move the dependencies from 
ADD_CUSTOM_COMMAND to ADD_CUSTOM_TARGET by changing 
main_dir/CMakeLists.txt this way:

PROJECT(main)
SUBDIRS(dirA dirB)
ADD_CUSTOM_COMMAND(
  OUTPUT ${EXECUTABLE_OUTPUT_PATH}/main_custom${CMAKE_EXECUTABLE_SUFFIX}
  COMMAND wrap_libs_to_tclkit_exe
)
ADD_CUSTOM_TARGET(main_custom ALL
  DEPENDS ${EXECUTABLE_OUTPUT_PATH}/main_custom${CMAKE_EXECUTABLE_SUFFIX}
)
ADD_DEPENDENCIES(main_custom targetA targetB)

Hope this helps others with the same problem.
Giampiero


More information about the CMake mailing list