Makefile `echo -n 'не работает
Я пытаюсь получить текст эхо файла Makefile без завершающей новой строки, но не могу. Я испытываю поведение в OS X (в Linux все работает так, как ожидалось).
Makefile
a:
@echo -n "hello"
b:
@echo -n hello
c:
@/bin/echo -n "hello"
Вывод:
$make a
-n hello
$make b
hello$make c
hello$
Другими словами, make a
нарушается. Что именно происходит? Является ли использование встроенного эха? Очевидно, что наличие двойных кавычек меняет поведение, но почему?
Update
Как было обнаружено @chepner, использование полного пути к /bin/echo
в make файле правильно распознает флаг -n.
Ответы
Ответ 1
Что-то о цитатах смущает make
. Ваш код ведет себя одинаково для меня, но следующее работает как ожидалось:
help:
@echo -n Shouldn\'t print a newline
Hardcoding путь к исполняемому файлу также работает:
help:
@/bin/echo -n "Shouldn't print a newline"
В man-странице Mac OS X для echo
при обсуждении существования встроенной оболочки echo
s упоминается, что echo
sh(1)
не поддерживает параметр -n
, но это не работает объяснить (мне, во всяком случае), почему моя первая альтернатива работает.
Подтверждение, что make
использует sh
для выполнения команд по умолчанию. В
SHELL = bash
help:
@echo -n "Shouldn't print a newline"
@echo -n Shouldn\'t print a newline
оба выражения эха ведут себя одинаково (никаких строк печати не напечатано). Таким образом, без этой переменной мы имеем bash
, притворяясь sh
, но оценивая две строки по-разному. Вопрос 1: почему? Вопрос 2: вторая строка - это нативный bash
эхо или /bin/echo
, а не эмулируемый sh
echo
?
Ответ 2
Проблема возникает из-за неудачного взаимодействия двух фактов.
Во-первых, make
имеет два режима работы в зависимости от сложности рецепта, который нужно запустить:
- Если команда проста,
make
будет запускать рецепт с помощью встроенных команд. Это то, что происходит в вашем случае b
.
- Если команда сложная,
make
создаст оболочку для интерпретации и запуска рецепта. Это то, что происходит в вашем случае a
.
Во-вторых, make
использует /bin/sh
как оболочку, но функциональность /bin/sh
реализована по-разному в Mac OS X и Linux:
- В Mac OS X функциональность
/bin/sh
реализована bash
. Также в Mac OS X bash
скомпилируется с помощью --enable-strict-posix-default
. Одним из последствий этого флага является то, что команда echo
не понимает флаг -n
.
- В Linux функциональность
/bin/sh
реализована dash
, которая является менее строгой по отношению к спецификации POSIX. Поэтому флаг -n
реализуется в команде echo
.
BTW, команда makefile buitlin echo
понимает флаг -n
, который объясняет, почему всегда работает сценарий b
.
Чистый и переносимый способ решения проблемы заключается в замене рецептов @echo -n
на рецепты @printf
.
Ответ 3
echo - это встроенная оболочка bash, но когда вы запускаете ее из make файла, это версия программы