CMake add_custom_command не запускается - PullRequest
46 голосов
/ 30 мая 2010

Я пытаюсь использовать add_custom_command для создания файла во время сборки. Команда никогда не выполнялась, поэтому я создал этот тестовый файл.

cmake_minimum_required( VERSION 2.6 )

add_custom_command(
  OUTPUT hello.txt
  COMMAND touch hello.txt
  DEPENDS hello.txt
)

Я попытался запустить:

cmake .  
make

И hello.txt не был сгенерирован. Что я сделал не так?

Ответы [ 3 ]

52 голосов
/ 22 июля 2011

Решение add_custom_target(run ALL ... будет работать для простых случаев, когда у вас есть только одна цель, которую вы строите, но не работает, если у вас есть несколько целей верхнего уровня, например, приложение и тесты.

Я столкнулся с той же проблемой, когда пытался упаковать некоторые файлы тестовых данных в объектный файл, чтобы мои модульные тесты не зависели от чего-либо внешнего. Я решил это с помощью add_custom_command и некоторой дополнительной магии зависимостей с set_property.

add_custom_command(
  OUTPUT testData.cpp
  COMMAND reswrap 
  ARGS    testData.src > testData.cpp
  DEPENDS testData.src 
)
set_property(SOURCE unit-tests.cpp APPEND PROPERTY OBJECT_DEPENDS testData.cpp)

add_executable(app main.cpp)
add_executable(tests unit-tests.cpp)

Так что теперь testData.cpp будет сгенерирован до компиляции unit-tests.cpp, и каждый раз, когда testData.src изменяется. Если команда, которую вы вызываете, очень медленная, вы получаете дополнительный бонус, заключающийся в том, что при создании только цели приложения вам не придется ждать, пока эта команда (которая нужна только исполняемому файлу тестов) завершится.

Это не показано выше, но осторожное применение ${PROJECT_BINARY_DIR}, ${PROJECT_SOURCE_DIR} and include_directories() сохранит ваше исходное дерево чистым от сгенерированных файлов.

31 голосов
/ 31 мая 2010

Добавить следующее:

add_custom_target(run ALL
    DEPENDS hello.txt)

Если вы знакомы с make-файлами, это означает:

all: run
run: hello.txt
9 голосов
/ 16 августа 2018

Проблема с двумя существующими ответами заключается в том, что они либо делают зависимость глобальной (add_custom_target(name ALL ...)), либо присваивают ее определенному отдельному файлу (set_property(...)), который становится неприятным, если у вас есть много файлов, которые нуждаются в этом как зависимость. Вместо этого нам нужна цель, которую мы можем сделать зависимой от другой цели.

Способ сделать это - использовать add_custom_command для определения правила, а затем add_custom_target для определения новой цели на основе этого правила. Затем вы можете добавить эту цель как зависимость от другой цели через add_dependencies.

# this defines the build rule for some_file
add_custom_command(
  OUTPUT some_file
  COMMAND ...
)
# create a target that includes some_file, this gives us a name that we can use later
add_custom_target(
  some_target
  DEPENDS some_file
)
# then let's suppose we're creating a library
add_library(some_library some_other_file.c)
# we can add the target as a dependency, and it will affect only this library
add_dependencies(some_library some_target)

Преимущества этого подхода:

  • some_target не является зависимостью для ALL, что означает, что вы строите его только тогда, когда этого требует конкретная цель. (Принимая во внимание, что add_custom_target(name ALL ...) построит его безоговорочно для всех целей.)
  • Поскольку some_target является зависимостью для библиотеки в целом, она будет построена раньше, чем все файлы в этой библиотеке. Это означает, что если в библиотеке много файлов, нам не нужно делать set_property для каждого из них.
  • Если мы добавим DEPENDS к add_custom_command, то он будет восстановлен только при изменении входных данных. (Сравните это с подходом, использующим add_custom_target(name ALL ...), когда команда запускается при каждой сборке независимо от того, нужна она или нет.)

Дополнительную информацию о том, почему все так работает, смотрите в этом блоге: https://samthursfield.wordpress.com/2015/11/21/cmake-dependencies-between-targets-and-files-and-custom-commands/

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