add_custom_command не перезапускается при сбое
В CMake я бы хотел использовать add_custom_command(... POST_BUILD ...)
с COMMAND
это может потерпеть неудачу.
наблюдение
- Бег
make
не удастся в первый раз, потому что код выходаadd_custom_command( ... COMMAND exit 1)
не является0
, -> Это то, что я ожидал. - Бег
make
пройдет второй раз, потому что команда, указанная вadd_custom_command
больше не будет -> Это не то, что я хочу. я бы хотелmake
потерпеть неудачу, пока пользовательская команда не работает.
Minimium Failing Пример
project(Foo)
cmake_minimum_required(VERSION 3.2)
# Create main.cc
##include <iostream>
#
#int main() {
# std::cout << "Hello, World!" << std::endl;
#}
add_executable(main main.cc)
add_custom_command(TARGET main POST_BUILD
COMMAND exit 1 # In the real example, I am changing capabilities of the resulting binary with /sbin/setcap, which might fail.
COMMENT "Doing stuff."
)
Вопрос
- Как я могу решить эту проблему?
- Это предполагаемое поведение CMake?
Одно решение
Я знаю, что могу создать собственную команду, которая не POST_BUILD
но вместо этого выводит файл TARGET.passed
на успех. Однако я бы хотел этого избежать. Потому что POST_BUILD кажется наиболее подходящим для использования здесь. (Я изменяю возможности полученного файла.)
1 ответ
Решение
Раньше это была ошибка в CMake.
Это было исправлено в следующем коммите:
commit 4adf1dad2a6e462364bae81030c928599d11c24f
Author: Brad King <brad.king@kitware.com>
Date: Mon Mar 30 16:32:26 2015 -0400
Makefile: Tell GNU make to delete rule outputs on error (#15474)
Add .DELETE_ON_ERROR to the "build.make" files that contain the actual
build rules that generate files. This tells GNU make to delete the
output of a rule if the recipe modifies the output but returns failure.
This is particularly useful for custom commands that use shell
redirection to produce a file.
Do not add .DELETE_ON_ERROR for Borland or Watcom make tools because
they may not tolerate it and would not honor it anyway. Other make
tools that do not understand .DELETE_ON_ERROR will not be hurt.
Suggested-by: Andrey Vihrov <andrey.vihrov@gmail.com>
Самым ранним выпуском с этим исправлением был CMake 3.3.0.
Временное решение
- Создайте дополнительную выходную цель, которая зависит от успешной работы пользовательской команды. (Ниже это называется
main.done
) - Переключить пользовательскую команду из
POST_BUILD
наTARGET
, чтобы быть отдельной командой. Таким образом, сделать этоOUTPUT
файл (main.intermediate_step
ниже). - Используйте опцию для запуска второго
COMMAND
создать указанный файл, используяtouch
,
Код:
project(Foo)
cmake_minimum_required(VERSION 3.2)
# Create main.cc
##include <iostream>
#
#int main() {
# std::cout << "Hello, World!" << std::endl;
#}
add_executable(main main.cc)
add_custom_command(TARGET main POST_BUILD
COMMAND exit 1 # In the real example, I am changing capabilities of the resulting binary with /sbin/setcap, which might fail.
COMMENT "Doing stuff."
)
add_custom_command(OUTPUT main.intermediate_step
COMMAND exit 1 # In the real example, I am changing capabilities of the resulting binary with /sbin/setcap, which might fail.
COMMAND touch main_setcap.passed
DEPENDS main
COMMENT "Doing stuff."
)
add_custom_target(main.done ALL DEPENDS main.intermediate_step)
Замечания: make main
не будет запускать пользовательскую команду. использование make main.done
для этого. make
а также make all
будет работать как задумано.