I am trying to have my Makefile echo text without the trailing new line, but am unable to. I am experiencing the behavior on OS X (on Linux everything works as expected).
Makefile
a:
@echo -n "hello"
b:
@echo -n hello
c:
@/bin/echo -n "hello"
Output:
$make a
-n hello
$make b
hello$make c
hello$
In other words, the make a
is broken. What exactly is happening? Is make using a built-in echo? Clearly the presence of the double quotes changes the behavior, but why?
Update
As discovered by @chepner, using the full path to /bin/echo
in the makefile understands the -n flag correctly.
echo is a bash shell builtin, but when you run it from makefile, it is the program version
The problem comes from the unfortunate interaction of two facts.
First,
make
has two modes of operations depending on the complexity of the recipe to be run:make
will directly run the recipe with its builtin commands. This is what happens in yourb
case.make
will spawn a shell to interpret and run the recipe. This is what happens in youra
case.Second,
make
uses/bin/sh
as a shell but the functionality of/bin/sh
is implemented differently on Mac OS X and Linux:/bin/sh
is implemented bybash
. Also on Mac OS X,bash
is compiled with--enable-strict-posix-default
. One consequence of this flag is that theecho
command does not understand the-n
flag./bin/sh
is implemented bydash
which is less strict with respect to POSIX specification. Therefore the flag-n
is implemented in theecho
command.BTW, the Makefile buitlin
echo
command understands the-n
flag which explains why theb
case always works.The clean and portable way of fixing your problem is to replace your
@echo -n
recipes with@printf
recipes.Something about the quotes confuses
make
. Your code behaves the same for me, but the following works as expected:Hardcoding the path to the executable also works:
The Mac OS X man page for
echo
, while discussing the existence of shell built-inecho
s, mentions that theecho
ofsh(1)
does not support the-n
option, but that fails to explain (to me, anyway) why my first alternative works.Confirmation that
make
is usingsh
to execute the commands by default. Inboth echo statements behave the same (no newlines printed). So without that variable, we have
bash
pretending to besh
, but evaluating the two lines differently. Question 1: why? Question 2: is the second line the nativebash
echo or/bin/echo
, rather than the emulatedsh
echo
?