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

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.

4b9b3361

Ответ 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 файла, это версия программы