I want to add a test target that is dependant on the whole of a project being built successfully, without re-specifying dependencies on all the libraries or executables.
I would write this in make as:
all: foo bar
foo: ...
bar: ...
test: all
test.sh
test.sh implicitly uses foo and bar and wants them to be up to date.
This is how I would expect to specify this in cmake.
add_library(foo ...)
add_executable(bar ...)
add_custom_target(test test.sh
DEPENDS all
)
However this does not work as there is no all target.
Is there a way to specify this? Or is there a variable that expands to all the targets I am trying to build?
As of version 2.8 CMake does not provide a variable that holds a list of all targets. The best you can do is to override the built-in commands add_library
and add_executable
with custom macros that call the built-in ones and keep track of all defined targets in a variable.
You can even use the same names for your custom macros. That way you do not have to make changes to all the existing add_library
and add_executable
calls. The original built-in commands are prefixed with an underscore if you override any of them:
set (_allTargets "")
macro(add_library _target)
_add_library (${_target} ${ARGN})
list (APPEND _allTargets ${_target})
endmacro()
macro(add_executable _target)
_add_executable (${_target} ${ARGN})
list (APPEND _allTargets ${_target})
endmacro()
add_library(liba STATIC liba.cpp)
add_executable(main liba main.cpp)
add_custom_target(test "${CMAKE_CURRENT_SOURCE_DIR}/test.sh")
add_dependencies(test ${_allTargets})
Also note that you cannot add a target dependency to a custom target with the DEPENDS
option. DEPENDS
may only reference existing files or files generated with add_custom_command(...)
in the same directory. To add a target dependency use the add_dependencies
command instead.
I have not enough reputation to comment on Sakra answer...
One problem I see with that solution is that if you use any subdirectory the changes you do to the variable _allTargets inside the subdirectory will not be propagated to the parent scope.
Digging more, list(append ...) cannot be used in this case:
Similar to the SET command, the LIST command creates new variable values in the current scope, even if the list itself is actually defined in a parent scope. To propagate the results of these operations upwards, use SET with PARENT_SCOPE, SET with CACHE INTERNAL, or some other means of value propagation.
http://www.cmake.org/cmake/help/v2.8.11/cmake.html#command:set :
If PARENT_SCOPE is present, the variable will be set in the scope above the current scope. Each new directory or function creates a new scope. This command will set the value of a variable into the parent directory or calling function (whichever is applicable to the case at hand).
(note for myself: a macro is not a function)
I don't see a general solution (e.g. independent from using add_subdirectory) when using PARENT_SCOPE. However, here there seem to be a solution using CACHE INTERNAL.
Quoting from: http://www.cmake.org/pipermail/cmake/2007-November/018109.html
# A macro for passing lists between different directories
# through an internal cache variable.
MACRO (APPEND_INTERNAL_LIST LIST_NAME VALUE)
# If the list in not in the cache, create it.
IF (${LIST_NAME})
SET (${LIST_NAME} "${${LIST_NAME}};${VALUE}" CACHE INTERNAL "Internal
variable")
ELSE (${LIST_NAME})
SET (${LIST_NAME} "${VALUE}" CACHE INTERNAL "Internal variable")
ENDIF (${LIST_NAME})
ENDMACRO (APPEND_INTERNAL_LIST)
# A macro for passing lists between different directories
# through an internal cache variable.
# This function empties the variable (usually because of older runs)
MACRO (INITIALIZE_INTERNAL_LIST LIST_NAME)
SET (${LIST_NAME} "" CACHE INTERNAL "Internal variable")
ENDMACRO (INITIALIZE_INTERNAL_LIST)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With