Date: Mon, 23 May 2005 15:51:16 +0200 (CEST) From: Harti Brandt <hartmut.brandt@dlr.de> To: arch@freebsd.org Subject: Handling of shell builtins in make(1) Message-ID: <20050523153118.C28521@beagle.kn.op.dlr.de>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050523153118.C28521>