Подстановка процессов в GNU Makefiles


11

В командной строке 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)'

Что это значит, и есть ли способ по-прежнему различать два вывода без использования временных файлов?

Ответы:


20

/bin/shможет быть bashв вашей системе, но при вызове как sh, bashбудет работать в режиме POSIX (как если бы он POSIXLY_CORRECTбыл определен, или он был запущен с --posix).

В этом режиме замены процесса не существуют.

Решения:

all:
    command1 >file1
    command2 >file2
    diff file1 file2
    rm -f file1 file2

Альтернатива:

all:
    bash -c "diff <(command1) <(command2)"

Или просто определите переменную Makefile SHELLкак /bin/bash:

SHELL=/bin/bash

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


Что касается настройки SHELL: Стандарт POSIX говорит , что исполняемые файлы в Makefiles должны вызываться с system()библиотечной функцией C помощи make. Эта функция не гарантирует использование SHELLпеременной окружения (на самом деле, это не рекомендуется стандартом). Стандарт также говорит о том, что установка переменной Makefile SHELLне должна влиять на переменную окружения SHELL . Однако в большинстве makeизвестных мне реализаций переменная Makefile SHELLбудет использоваться для выполнения команд.

Предложение в обосновании makeутилиты заключается в использовании bash -c:

Исторический MAKESHELLпризнак и связанные с ним функции, предоставляемые другими makeреализациями, были опущены. В некоторых реализациях он используется, чтобы позволить пользователю переопределить оболочку, которая будет использоваться для запуска makeкоманд. Это сбивало с толку; для портативного компьютера makeоболочка должна быть выбрана автором make-файла. Кроме того, средство записи make-файла не может требовать использования альтернативной оболочки и все же считает, что make-файл является переносимым. Хотя было бы возможно стандартизировать механизм указания альтернативной оболочки, существующие реализации не согласны с таким механизмом, и разработчики make-файлов уже могут вызывать альтернативную оболочку, указав имя оболочки в правиле для цели; например:

python -c "foo"


Есть ли способ вызвать bashв Makefile или любом другом решении проблемы diff без использования временных файлов?
— Йоханнес

Просто используйте два временных файла, это более или менее то, что метод подстановки процесса сделал бы в любом случае под капотом.
— Кусалананда

3
Кроме того, можно установить , SHELLчтобы /bin/bashв Makefile.
— Стивен Китт

1
@Johannes Kusalananda добавил информацию в свой ответ, и это здорово, поскольку в нем представлен ряд вариантов и обстоятельства, при которых они могут быть использованы. Я бы предпочел, чтобы вы приняли этот ответ ... (Но я ценю это чувство!)
— Стивен Китт

2
Информация о том, что использование переменной SHELL не соответствует POSIX, была очень полезной. Может быть, все еще лучше использовать bash -c.
— Йоханнес
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.