CMake add_custom_target в зависимости от строящегося проекта - PullRequest
8 голосов
/ 16 июня 2011

Я хочу добавить тестовую цель, которая зависит от всего успешно создаваемого проекта, без повторного указания зависимостей от всех библиотек или исполняемых файлов.

Я бы написал это в make как:

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
)

Однако это не работает, так как нет цели цели.

Есть ли способ указать это?Или есть переменная, которая распространяется на все цели, которые я пытаюсь построить?

Ответы [ 3 ]

9 голосов
/ 16 июня 2011

Начиная с версии 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.DEPENDS может ссылаться только на существующие файлы или файлы, созданные с помощью add_custom_command(...) в том же каталоге.Чтобы добавить целевую зависимость, используйте команду add_dependencies.

4 голосов
/ 19 июня 2013

У меня недостаточно репутации, чтобы комментировать ответ Сакры ...

Одна проблема, которую я вижу с этим решением, состоит в том, что если вы используете какой-либо подкаталог, изменения, которые вы вносите в переменную _allTargets внутри подкаталога, не будутраспространяется на родительскую область.

Копать больше, список (добавление ...) не может использоваться в этом случае:

Аналогично команде SET,команда LIST создает новые значения переменных в текущей области, даже если сам список фактически определен в родительской области.Чтобы распространить результаты этих операций вверх, используйте SET с PARENT_SCOPE, SET с CACHE INTERNAL, или некоторые другие средства распространения значения.

http://www.cmake.org/cmake/help/v2.8.11/cmake.html#command:set:

Если присутствует PARENT_SCOPE, переменная будет установлена ​​в области видимости над текущей областью видимости. Каждый новый каталог или функция создает новую область действия .Эта команда установит значение переменной в родительский каталог или вызывающую функцию (в зависимости от того, что применимо к данному случаю).

(примечание для меня: макрос не равен функция)

Я не вижу общего решения (например, независимого от использования add_subdirectory) при использовании PARENT_SCOPE.Однако здесь, похоже, есть решение с использованием CACHE INTERNAL.

Цитирование из: 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)
0 голосов
/ 18 июня 2011

Вы можете использовать CTest:

include(CTest)
if (BUILD_TESTING)
    add_test(MyTestName test.sh param1 param2)
endif(BUILD_TESTING)

Cmake сгенерирует Makefile с новой целью test , см. Также: Документация для add_test command .

Но вам нужно скомпилировать свой проект перед запуском тестов:

make
make test

Также вы можете использовать цель Experimental , Nightly или Непрерывный .Эти цели компилируют проект и запускают все тесты, но они также пытаются представить результаты тестов (вы можете настроить его с помощью CTestConfig.cmake ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...