Handling of shell builtins in make(1)

Scott Long scottl at samsco.org
Mon May 23 19:52:03 PDT 2005


Harti Brandt wrote:

> 
> Hi all,
> 
> I think I found a problem in the shell code in make(1), but I'm not sure 
> whether to fix it or not and how. The problem is as follows: in compat 
> mode (this is the default mode when make(1) is not called with -j) the 
> command lines of a target are executed by one shell per line (this is 
> also how Posix wants it). To reduce the number of shells make does an 
> optimisation: when the command line does not contain one of a 
> pre-defined set of meta characters and does not start with one of a 
> predefined set of shell builtins, make directly exec's the command 
> instead of using an intermediate shell. The problem is that the current 
> list of builtins is limited to:
> 
>   alias cd eval exec exit read set ulimit unalias umask unset wait
> 
> Obviously this is not the full set of shell builtins and does also not 
> contain the shell reserved words.
> 
> The result of this is that for one and the same command you can get 
> different behaviour whether you execute it via make(1) or via sh -c '...'.
> As an example take echo(1). When called via the sh -c you get the builtin
> echo which supports the -e option, when executed by make(1) you get 
> /bin/echo which doesn't. If you suddenly include a shell meta character 
> in the command line:
> 
> foo:
>     echo "MAKEFLAGS: ${MAKEFLAGS}"
> 
> you suddenly get also the builtin (':' is a meta character).
> 
> For the reserved words the situation is almost the same. With the 
> following makefile:
> 
> foo:
>     if
> 
> one gets:
> 
> if:No such file or directory, while
> 
> foo:
>     if [ -x /bin/sh ] ; then echo hey ; fi
> 
> you get what you expect.
> 
> I think all this may be very confusing. The question is what to do. I 
> see the following options:
> 
> 1. leave it as it is.
> 
> 2. include the Posix reserved words and builtins into the list.
> 
> 3. include all reserved words and builtins of our shell into the list.
> 
> Option (3) is probably best. With (2) you still get different behaviour 
> for the two command lines in:
> 
> foo:
>     bind -h
>     bind -h *
> 
> (the first line will try to find bind in the path while the second will 
> execute the shell builtin).
> 
> Opinions?
> 
> harti

4. Separate /bin/sh into a front end and back end (libsh) and include 
libsh into make.

(running and hiding as I hit the 'send' key)

Scott


More information about the freebsd-arch mailing list