Customize SHELL in Makefile (set SHELL=my_shel

2019-07-29 10:36发布

问题:

I would like to customize the shell for a Makefile, but I am running into trouble. Here is a MWE. I have a Makefile,

SHELL=./my_shell.sh

all: abc def

abc:
        touch abc

def:
        touch def

clean:
        rm -f abc def

and a simple custom script, my_shell.sh.

#!/bin/bash
eval $*

I made sure to run chmod +x my_shell.sh beforehand. Then, when I typed make, I got an error.

make[3]: Entering directory `<CONFIDENTIAL>'
touch abc
./my_shell.sh: line 2: eval: -c: invalid option
eval: usage: eval [arg ...]
make[3]: *** [abc] Error 2
make[3]: Leaving directory `<CONFIDENTIAL>`

I have been struggling to get rid of the -c option. Setting .SHELLFLAGS='' doesn't seem to work.

回答1:

First, if you want to set a make variable to empty use

.SHELLFLAGS =

By adding the quotes you've actually set the variable to the literal string '' (make is not the shell and does not do shell quote stripping).

Second, the .SHELLFLAGS variable was added in GNU make 3.82 so if your version is older than that, it won't work. If you have 3.82 or newer then it does work (I just tried it).

Lastly, as Jean-François points out you will problems if your command has escaped spaces. However, his solution of using "$@" cannot work as-is, because then the entire command is seen as a single string.

A more reliable implementation of the script would be:

#!/bin/bash
exec /bin/bash "$@"

And then do not modify .SHELLFLAGS. Or else, do set .SHELLFLAGS to empty and make your script:

#!/bin/bash
exec /bin/bash -c "$@"


回答2:

SHELL expects a shell command like bash or csh. make invokes the shell command using -c as first argument (command option).

Since you pass all arguments directly to the eval commands you get that error.

Use shift to skip the first -c argument that you are not using.

#!/bin/bash
shift
eval $*

And maybe you'll need "$@" instead of $* if the arguments have spaces.