Процес заміни в 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, оболонку повинен вибирати автор, що працює з файлами. Крім того, автори makefile не можуть вимагати використання альтернативної оболонки, і все ще вважають makefile переносним. Хоча можна було б стандартизувати механізм визначення альтернативної оболонки, існуючі реалізації не погоджуються на такий механізм, і автори makefile вже можуть викликати альтернативну оболонку, вказавши ім'я оболонки в правилі для цілі; наприклад:

python -c "foo"


Чи є спосіб викликати bashв Makefile або будь-якому іншому вирішенні проблеми diff без використання тимчасових файлів?
Йоганнес

Просто використовуйте два тимчасові файли, це більш-менш те, що метод заміщення процесу все-таки робив би під капотом.
Кусалаланда

3
Крім того, можна встановити , SHELLщоб /bin/bashв Makefile.
Стівен Кітт

1
@Johannes Kusalananda's додав інформацію до своєї відповіді, що чудово, оскільки вона містить ряд варіантів та обставин, за яких їх можна використовувати. Я вважаю за краще прийняти цю відповідь ... (Але я ціную почуття!)
Стівен Кітт

2
Інформація про те, що використання змінної SHELL не відповідає POSIX, була дуже корисною. Можливо, це все-таки краще використовувати bash -c.
Йоганнес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.