
В командной строке bash можно выполнить diff, используя псевдофайлы:
diff <(echo test) <(echo test)
Добавление этого в Makefile в исходном виде не удается:
all:
diff <(echo test) <(echo test)
Ошибка (подсказка: /bin/sh указывает на /bin/bash в этой системе):
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `diff <(echo test) <(echo test)'
Что это значит, и есть ли способ сравнить два вывода без использования временных файлов?
решение1
/bin/sh
может быть bash
в вашей системе, но при вызове как sh
будет bash
работать в режиме POSIX (как если бы POSIXLY_CORRECT
был определен или запущен с помощью --posix
).
В этом режиме замены процессов не существует.
Решения:
Используйте явные временные файлы:
all: command1 >tmpfile command2 | diff tmpfile - rm -f tmpfile
Используйте
bash -c
встроенный скрипт:all: bash -c 'diff <(command1) <(command2)'
Определите переменную Makefile
SHELL
следующим образом/bin/bash
(или укажите путь к нейbash
в вашей системе):SHELL=/bin/bash
Если вам нужна переносимость, используйте первое решение. Если вас устраивает зависимость от bash
, выберите второе. Если вам, кроме того, не нужно беспокоиться о make
реализациях, отличных от GNU, используйте третье.
Относительно настройки SHELL
: Стандарт POSIX гласит, что исполняемые файлы в Makefiles должны вызываться с помощью system()
функции библиотеки C с помощью make
. Эта функция не гарантирует использование SHELL
переменной окружения (фактически, это не рекомендуется стандартом). Стандарт также идет на некоторые уступки, чтобы сказать, что настройка переменной Makefile SHELL
не должна влиять напеременная окружения SHELL
make
. Однако в большинстве известных мне реализаций SHELL
для выполнения команд будет использоваться переменная Makefile.
Предложение вОбоснование make
полезностизаключается в использовании bash -c
:
Историческая
MAKESHELL
функция и связанные с ней функции, предоставляемые другимиmake
реализациями, были опущены. В некоторых реализациях она используется для того, чтобы позволить пользователю переопределить оболочку, используемую для запускаmake
команд. Это сбивало с толку; для переносимогоmake
оболочка должна быть выбрана автором makefile. Кроме того, автор makefile не может требовать использования альтернативной оболочки и при этом считать makefile переносимым. Хотя можно было бы стандартизировать механизм указания альтернативной оболочки, существующие реализации не согласны с таким механизмом, и авторы makefile уже могут вызывать альтернативную оболочку, указывая имя оболочки в правиле для цели; например:
python -c "foo"