add_custom_command не перезапускается при сбое

В CMake я бы хотел использовать add_custom_command(... POST_BUILD ...) с COMMAND это может потерпеть неудачу.

наблюдение

  1. Бег make не удастся в первый раз, потому что код выхода add_custom_command( ... COMMAND exit 1) не является 0, -> Это то, что я ожидал.
  2. Бег 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."
          )

Вопрос

  1. Как я могу решить эту проблему?
  2. Это предполагаемое поведение 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 будет работать как задумано.

Другие вопросы по тегам