CMake добавляет пользовательскую цель в зависимости от всего строящегося проекта
Я хочу добавить тестовую цель, которая зависит от всего успешно строящегося проекта, без повторного указания зависимостей от всех библиотек или исполняемых файлов.
Я бы написал это в Сделать:
all: foo bar
foo: ...
bar: ...
test: all
test.sh
test.sh неявно использует foo и bar и хочет, чтобы они были в курсе.
вот как я ожидал бы указать это в cmake.
add_library(foo ...)
add_executable(bar ...)
add_custom_target(test test.sh
DEPENDS all
)
однако это не работает, поскольку нет цели all.
Is есть способ уточнить это? Или есть переменная, которая расширяется до всех целей, которые я пытаюсь построить?
3 ответов
начиная с версии 2.8 CMake не предоставляет переменную, которая содержит список всех целей. Лучшее, что вы можете сделать, это переопределить встроенные команды add_library
и add_executable
с пользовательскими макросами, которые вызывают встроенные и отслеживают все определенные цели в переменной.
вы даже можете использовать те же имена для пользовательских макросов. Таким образом, вам не нужно вносить изменения во все существующие add_library
и add_executable
звонки. Исходные встроенные команды имеют префикс подчеркивание при переопределении любого из них:
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})
также обратите внимание, что вы не можете добавить целевую зависимость к пользовательской цели с помощью . DEPENDS
может ссылаться только на существующие файлы или файлы, созданные с помощью add_custom_command(...)
в том же каталоге. Чтобы добавить целевую зависимость, используйте .
У меня недостаточно репутации, чтобы прокомментировать ответ Сакры...
одна проблема, которую я вижу с этим решением, заключается в том, что если вы используете любой подкаталог, изменения, которые вы делаете с переменной _allTargets внутри подкаталога, не будут распространяться на родительскую область.
глубже список(добавить ...) нельзя использовать в этом случае:
подобно команде SET, команда LIST создает новую переменную значения в текущей области, даже если сам список на самом деле определяется в родительской области. Для распространения результатов этих операции вверх, использовать SET с PARENT_SCOPE, SET с кэшем Внутренний, или некоторые другие средства распространения значений.
http://www.cmake.org/cmake/help/v2.8.11/cmake.html#command:set:
если PARENT_SCOPE присутствует, переменная будет установлена в области выше текущего объема. каждый новый каталог или функция создает новая область. Эта команда установит значение переменной в родительский каталог или вызывающая функция (в зависимости от того, что применимо к дело под рукой).
(примечание для себя: макрос не функция)
Я не вижу общего решения (например, независимого от использования add_subdirectory) при использовании PARENT_SCOPE. Однако здесь, похоже,есть решение с использованием внутреннего кэша.
цитирование: 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)
Вы можете использовать CTest:
include(CTest)
if (BUILD_TESTING)
add_test(MyTestName test.sh param1 param2)
endif(BUILD_TESTING)
Cmake будет генерировать Makefile с новой целью тест Смотрите также: документация add_test команда.
но вам нужно скомпилировать свой проект перед запуском тестов:
make
make test
кроме того, вы можете использовать элемент экспериментальные, ночной или постоянный. Эти цели будут компилировать проект и запускать все тесты, но они также пытаются отправить результаты теста (вы можете настроить его с помощью CTestConfig.с CMake).