Search code examples
bashmakefileecho

Makefile `echo -n' not working


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.


Solution

  • Something about the quotes confuses make. Your code behaves the same for me, but the following works as expected:

    help:
            @echo -n Shouldn\'t print a newline
    

    Hardcoding the path to the executable also works:

    help:
            @/bin/echo -n "Shouldn't print a newline"
    

    The Mac OS X man page for echo, while discussing the existence of shell built-in echos, mentions that the echo of sh(1) does not support the -n option, but that fails to explain (to me, anyway) why my first alternative works.


    Confirmation that make is using sh to execute the commands by default. Make manual 5.3.2 Choosing the Shell specifies this hehavrior:

    The program used as the shell is taken from the variable SHELL. If this variable is not set in your makefile, the program /bin/sh is used as the shell. The argument(s) passed to the shell are taken from the variable .SHELLFLAGS. The default value of .SHELLFLAGS is -c normally, or -ec in POSIX-conforming mode.

    In

    SHELL = bash
    help:
            @echo -n "Shouldn't print a newline"
            @echo -n Shouldn\'t print a newline
    

    both echo statements behave the same (no newlines printed). So without that variable, we have bash pretending to be sh, but evaluating the two lines differently. Question 1: why? Question 2: is the second line the native bash echo or /bin/echo, rather than the emulated sh echo?