Как я могу перехватывать ошибки и прерывания в GNU make?

StackOverflow https://stackoverflow.com/questions/974077

Вопрос

Мне интересно, есть ли способ реализовать trap в GNU make, аналогичный тому , что встроен в BASH?

Если пользователь нажимает CTRL-C, или если make сам сбой (ненулевой выход), я бы хотел вызвать конкретную цель или макрос.

Это было полезно?

Решение

Нет.Обработка сигналов GNU make уже оставляет желать лучшего.Из своего обработчика сигналов он вызывает такие функции, как printf которые небезопасны для вызова из обработчика сигнала.Я видел, как это вызывало проблемы, например .DELETE_ON_ERROR правила не всегда выполняются, если stderr перенаправляется на stdout.

Например, на коробке CentOS 7.4:

  1. Создайте следующее Makefile:

    .DELETE_ON_ERROR:
    
    foo:
            touch $@
            sleep 10
    
  2. Откройте его в vim и бежать :make,

  3. Пока он спит, нажмите Ctrl-C

Vim/ создавать отпечатки

Press ENTER or type command to continue
touch foo
sleep 10
^C
shell returned 130

Interrupt: Press ENTER or type command to continue

Make был отправлен сигнал прерывания, но foo все еще существует.

Другие советы

На данный момент GNU make не имеет встроенной поддержки.

Однако существует надежный обходной путь:

.PHONY: internal-target external-target

external-target:
  bash -c "trap 'trap - SIGINT SIGTERM ERR; <DO CLEANUP HERE>; exit 1' SIGINT SIGTERM ERR; $(MAKE) internal-target"

internal-target:
  echo "doing stuff here"

Это улавливает прерывания, завершения И любые ненулевые коды выхода.

Обратите внимание на $(MAKE) таким образом, переопределения cmdline и параметры make передаются в submake.

В ловушке:

  • очистить обработчик ловушек (с помощью -)
  • сделайте уборку
  • завершите работу с ненулевым статусом завершения, поэтому средства автоматизации сборки сообщают о неудачной сборке.

DELETE_ON_ERROR НЕ работает для каталогов, поэтому это ключ к очистке после mktemp -d, например

Заменить <DO CLEANUP HERE> с действительным CMD.

Упрощенная версия ответа @kevinf, которая кажется достаточно хорошей для базовых случаев:

run:
    bash -c "trap 'docker-compose down' EXIT; docker-compose up --build"

(Этот пример приведен не просто так: docker-compose up действительно говорит

Когда завершается выполнение команды, все контейнеры останавливаются.

но это не так rm остановленные контейнеры, такие как docker run --rm бы, так что вы все еще можете видеть их с docker ps -a.)

Make это не поддерживает, но с помощью BASH-трюков вы можете добиться чего-то подобного.

default: complete

complete: do_mount
        echo "Do something here..."

do_mount:
        mkdir -p "$(MOUNTPOINT)"
        ( while ps -p $$PPID >/dev/null ; do \
                sleep 1 ; \
        done ; \
        unmount "$(MOUNTPOINT)" \
        ) &
        mount "$(MOUNTSOURCE)" "$(MOUNTPOINT)" -o bind

"Размонтировать" будет запущено после завершения "make".Обычно это удовлетворительное решение, если вы пытаетесь выполнить операции очистки, которые могут возникнуть во время сборки, но обычно не очищаются при выходе "make".

Нет.Насколько я знаю, такой функциональности не существует.

make выдает коды возврата.Насколько я могу вспомнить прямо сейчас, он возвращает 0 для успеха, 2 для сбоя (пожалуйста, ознакомьтесь с документацией).Следовательно, будет ли вам достаточно, например, обернуть make внутри сценария оболочки?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top