rm -f fails for missing files when using "bash -e" as shell in GNU Make 4

Viewed 375

I have a Makefile that looks as follows:

.ONESHELL:
SHELL = /bin/bash
.SHELLFLAGS = -e

clean:
    rm -f foo

.PHONY: clean

foo doesn't exist. When I run this on Debian, GNU Make 4.1 I get this error:

rm -f foo
/bin/bash: rm -f foo: No such file or directory
Makefile:6: recipe for target 'clean' failed
make: *** [clean] Error 1

When I run it on macOS, GNU Make 3.81 it works as expected. It makes no difference if I write -rm -f instead of rm -f.

Why do I get the error? Running bash -e -c "rm -f foo" ; echo $? in a shell prints 0 on both systems.

Am I missing something?

2 Answers

The error message has to be read quite carefully:

/bin/bash: rm -f foo: No such file or directory

This isn't a message from rm saying it can't find foo, it's a message from Bash telling it can't find the file rm -f foo (with the spaces in the filename).

With .SHELLFLAGS = -e, the shell gets what would equal the command line:

bash -e "rm -f foo"

So it looks for a file rm -f foo to read commands from. You need to explicitly add the -c flag to tell it to take the argument itself as a command, i.e. .SHELLFLAGS = -ec, resulting in

bash -ec "rm -f foo"

Not surprisingly, the default value for .SHELLFLAGS contains -c:

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.

That is an invalid setting for .SHELLFLAGS. It will result in this being invoked:

/bin/sh -e 'rm -f foo'

which is not a valid command line; it's telling the shell to run a program named, literally, rm -f foo which is obviously wrong. You have to be sure you add the -c option as well, and since many shells only allow options in the first argument, you'll need:

.SHELLFLAGS = -ec

This is documented in the GNU make manual.

The reason it "works" in the older GNU make 3.81 is that this version doesn't support the .SHELLFLAGS option at all, so that line is just ignored.

Related