Подтвердить что ты не робот

Тестирование, если файл существует в целевом файле makefile, и завершение, если нет

Есть ли способ выйти с условием ошибки, если файл не существует? В настоящее время я делаю что-то вроде этого:

all: foo

foo:
    test -s /opt/local/bin/gsort || echo "GNU sort does not exist! Exiting..." && exit

Запуск make запускает цель all, которая запускает foo.

Ожидается, что если условие test -s не выполнено, то выполняются операторы echo/exit.

Однако, даже если /usr/bin/gsort существует, я получаю результат оператора echo, но команда exit не запускается. Это противоположность тому, что я надеюсь выполнить.

Каков правильный способ сделать что-то вроде выше?

4b9b3361

Ответ 1

exit возвращает статус последней выполненной команды. В этом случае он возвращает ноль, что означает, что все в порядке.

Это потому, что || и && имеют равный приоритет, и оболочка интерпретирует команду так, как если бы она была написана

( test ... || echo ... ) && exit

Если вы хотите подать сигнал об ошибке, вы должны выйти с ненулевым значением, например. exit 1. И если вы хотите эхо и выйти, просто поместите команды в последовательности, разделенные ;

all: foo

foo:
    test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; exit 1; }

Ответ 2

Я понимаю, что это немного устарело на данный момент, но вам не нужно даже использовать подоболочку, чтобы проверить, существует ли файл в Make.

Это также зависит от того, как вы хотите/ожидаете его запуска.

Использование подстановочной функции, например:

all: foo
foo:
ifeq (,$(wildcard /opt/local/bin/gsort))
    $(error GNU Sort does not exist!)
endif

- один из лучших способов сделать это. Обратите внимание, что предложение ifeq не имеет отступ, потому что оно оценивается до самой цели.

Если вы хотите, чтобы это произошло безоговорочно для каждой цели, вы можете просто переместить его за пределы цели:

ifeq (,$(wildcard /opt/local/bin/gsort))
$(error GNU Sort does not exist!)
endif

Ответ 3

Каждая командная строка в make работает в своей собственной суб-оболочке. Таким образом, запуск exit просто завершает эту под-оболочку, а не make файл в целом. По умолчанию выполнение make прекратится, если какая-либо суб-оболочка вернет неудачный статус выхода (по соглашению 0 означает успех, так что все остальное остановит выполнение). Простейшим методом было бы просто использовать статус выхода команды test:

all: foo

foo:
    test -s /opt/local/bin/gsort

Печать диагностического сообщения немного усложняет ситуацию, потому что команды типа echo возвращают статус выхода 0, заставляя make думать, что все в порядке. Чтобы обойти это, вам нужно запустить команду после нее, которая предоставит суб-оболочке ненулевой статус выхода:

all: foo

foo:
    test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; exit 1; }

или даже просто

all: foo

foo:
    test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; false; }

Ответ 4

Просто выполните:

all: /opt/local/bin/gsort

и если /opt/local/bin/gsort отсутствует, вы получите сообщение об ошибке "no rule to target target//local/bin/gsort".

Но если вы также хотите, чтобы с ним было приятное объяснение:

/opt/local/bin/gsort:
    echo "GNU sort does not exist! Exiting..."
    false

В GNU/Make, если цель не объявлена ​​ .PHONEY и не имеет каких-либо зависимостей, правило будет вызываться, если файл, соответствующий этой цели, не существует.

Приведенный выше код запускает команду false только тогда, когда /opt/local/bin/gsort не существует, будет возвращать значение не 0, и make будет терпеть неудачу.

Ответ 5

Поскольку вы проверяете, существует ли исполняемый файл gsort, вы можете использовать команду оболочки which или type для этого, например:

all: foo
  :

foo:
  which gsort || exit 1
  # or
  type gsort || exit 1

Вам не требуется сообщение об ошибке, так как оно автоматически распечатает:

/bin/sh: строка 0: type: gsort: не найден

что очевидно.


В качестве альтернативы используйте test или [ (см. help test/help [ для синтаксиса), например

test -x /opt/local/bin/gsort || { echo Error msg; exit 1; }

который проверяет, существует ли данный файл и его исполняемый файл, в противном случае отобразите сообщение и выйдите из него. Скобки важны для переопределения обычного приоритета операторов (слева направо) путем группировки команд (см. Раздел Compound Commands в man bash для дополнительной информации).


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

all: /opt/local/bin/gsort
  @echo Success.

/opt/local/bin/gsort:
  @echo "GNU sort does not exist! Exiting..."
  exit 1

Результат:

$ make
GNU sort does not exist! Exiting...
exit 1
make: *** [/opt/local/bin/gsort] Error 1