[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

make POSIX conformance problem ('sh -e' & .POSIX: rule)



>Category:	user
>Submitter-Id:	net
>Originator:	Mark Baushke
>Organization:	Juniper Networks, Inc.
>Confidential:	no
>Synopsis:	make POSIX conformance problem ('sh -e' & .POSIX: rule)
>Severity:	non-critical
>Priority:	low
>Class:		sw-bug
>Release:	3.4
>Environment:
	System      : OpenBSD 3.4
	Architecture: OpenBSD.i386
	Machine     : i386
>Description:
Background:

POSIX 1003.2-1997 states that each makefile command line is processed
as if given to system(3) (see URL
http://www.opengroup.org/onlinepubs/009695399/utilities/make.html)

POSIX 1003.1-2004 (as well as older versions of the standard) states
that system() does not use the "sh -e" command to exit immediately if
any untested command fails in non-interactive mode. (see URL
http://www.opengroup.org/onlinepubs/009695399/functions/system.html)

The Problem (tested on OpenBSD 3.4, the problem seems to still be
present in the cvs versions of make visible on the web for OpenBSD 3.5):

The OpenBSD /usr/bin/make program incorrectly selects the .POSIX: rule
as the default. It also incorrectly generates an error when an
intermediate command in the shell script generates an error.

It is my understanding that OpenBSD is interested in conforming to the
POSIX standards where reasonable. I hope you will consider adapting your
version of /usr/bin/make to handle this particular case.

http://www.openbsd.org/cgi-bin/cvsweb/~checkout~/src/usr.bin/make/compat.c?rev=HEAD

	/* If *cp isn't the null character, we hit a "meta" character and
	 * need to pass the command off to the shell. We give the shell the
	 * -e flag as well as -c if it's supposed to exit when it hits an
	 * error.  */

	shargv[1] = errCheck ? "-ec" : "-c";
...
	case 1:
		shargv[1] = errCheck ? "-ec" : "-c";

In both of the above cases, I believe that 'sharg[1] = "-c";' is the
correct replacment line.

My guess is that the .POSIX: directive in the test case would not have
much impact as the sys.mk file seems to be read before the first
Makefile is opened, but I have added that rule to underline that this
change is really only required in order to be POSIX compliant. 

It would be useful if .POSIX: were not being used as the default rule
and instead treated as a special case as required by the POSIX
specifications.

Should you wish to retain your existing behavior, that would be fine as
long as the behavior is modified as expected when the .POSIX: directive
is given.

I have consulted with Simon J. Gerraty who commits changes to the NetBSD
version of make as well as providing portable versions of bmake for
other platforms (see URL http://www.crufty.net/help/sjg/bmake.html). He
says he has committed a patch to the NetBSD -current version of the make
program.

Part of the e-mail exchange focused on this problem is found here:

http://mail-index.netbsd.org/tech-toolchain/2004/05/05/0008.html

After my .signature are the log message and URLs for the changes made to
the NetBSD.

>How-To-Repeat:
How to reproduce the problem:

The following Makefile

 --------------- start Makefile ---------------
.POSIX:
all: x plus sub err
x:
	@echo "Hello,"; false; echo "World"
plus:
	@echo a command
	+_(_at_)_echo "a command prefixed by '+' executes even with -n"
	@echo another command
subs:
	@echo make -n
	@${.MAKE} -f ${MAKEFILE} -n plus
	@echo make -n -j1
	@${.MAKE} -f ${MAKEFILE} -n -j1 plus

err:
	@(echo Now we expect an error...; exit 1)
	@echo "Oops! you shouldn't see this!"
	
 --------------- end Makefile ---------------

The
	make x

command should therefore generate two lines:

	Hello,
	World

with no error on a 'make' command that is POSIX-compliant. 

The
	make -n plus

command should print

	echo a command
	echo "a command prefixed by '+' executes even with -n"
	a command prefixed by '+' executes even with -n
	echo another command

to show that it is not executing the first and last echo command, but
is executing the middle one.

The
	make err

command should print 

	Now we expect an error...

and exit with an error code 1.

Running all of the tests may require adding a few command-line
arguments if the paricular version of make does not support setting
the .MAKE or MAKEFILE macros such as this:

	make .MAKE=/usr/bin/make MAKEFILE=Makefile

However, as those macros are not required by the POSIX standard, you
don't need to worry if they are not being set by default.

 --------------- begin test results for OpenBSD 3.4 ---------------
66-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile
67-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile plus
a command
a command prefixed by '+' executes even with -n
another command
68-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile -n plus
echo a command
echo "a command prefixed by '+' executes even with -n"
a command prefixed by '+' executes even with -n
echo another command
69-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile -n -j1 plus
echo a command
echo "a command prefixed by '+' executes even with -n"
echo another command
70-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile subs
make -n
echo a command
echo "a command prefixed by '+' executes even with -n"
a command prefixed by '+' executes even with -n
echo another command
make -n -j1
echo a command
echo "a command prefixed by '+' executes even with -n"
a command prefixed by '+' executes even with -n
echo another command
71-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile -n subs
echo make -n
/usr/bin/make -f Makefile -n plus
echo make -n -j1
/usr/bin/make -f Makefile -n -j1 plus
72-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile err
Now we expect an error...
*** Error code 1

Stop in /tmp_mnt/192.54.239.17/export/ford/home/eggert/junk/d (line 16 of Makefile).
73-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile -n err
(echo Now we expect an error...; exit 1)
echo "Oops! you shouldn't see this!"
74-alkaid $ uname -a
OpenBSD alkaid.twinsun.com 3.4 GENERIC#1 i386
76-alkaid $ /usr/bin/make x
Hello,
*** Error code 1

Stop in /tmp_mnt/192.54.239.17/export/ford/home/eggert/junk/d (line 4 of Makefile).
77-alkaid $ /usr/bin/make -n x
echo "Hello,"; false; echo "World"
... if the .POSIX: line is moved after the all: line
80-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile
Hello,
*** Error code 1

Stop in /tmp_mnt/192.54.239.17/export/ford/home/eggert/junk/d (line 4 of Makefile).
81-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile plus
a command
a command prefixed by '+' executes even with -n
another command
82-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile -n plus
echo a command
echo "a command prefixed by '+' executes even with -n"
a command prefixed by '+' executes even with -n
echo another command
83-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile -n -j1 plus
echo a command
echo "a command prefixed by '+' executes even with -n"
echo another command
84-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile subs
make -n
echo a command
echo "a command prefixed by '+' executes even with -n"
a command prefixed by '+' executes even with -n
echo another command
make -n -j1
echo a command
echo "a command prefixed by '+' executes even with -n"
a command prefixed by '+' executes even with -n
echo another command
85-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile -n subs
echo make -n
/usr/bin/make -f Makefile -n plus
echo make -n -j1
/usr/bin/make -f Makefile -n -j1 plus
86-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile err
Now we expect an error...
*** Error code 1

Stop in /tmp_mnt/192.54.239.17/export/ford/home/eggert/junk/d (line 16 of Makefile).
87-alkaid $ /usr/bin/make .MAKE=/usr/bin/make MAKEFILE=Makefile -n err
(echo Now we expect an error...; exit 1)
echo "Oops! you shouldn't see this!"
88-alkaid $
 --------------- end test results for OpenBSD 3.4 ---------------

>Fix:
Committed to the NetBSD cvs repository on Fri May 7 08:12:15 2004 UTC by sjg

Log message:

Remove use of sh -e when running in compat mode.
Its not posix compliant and serves very little purpose.
With this change compat and jobs modes are consistent wrt how
they treat each line of a script.

Add support for the '+' command line prefix as required by posix.
Lines prefixed with '+' are executed even when -n is given.
[Actually posix says they should also be done for -q and -t]

PR:
Reviewed by: jmc

http://cvsweb.netbsd.org/bsdweb.cgi/src/usr.bin/make/compat.c.diff?r1=1.53&r2=1.54

http://cvsweb.netbsd.org/bsdweb.cgi/src/usr.bin/make/nonints.h.diff?r1=1.31&r2=1.32
http://cvsweb.netbsd.org/bsdweb.cgi/src/usr.bin/make/job.c.diff?r1=1.84&r2=1.85
http://cvsweb.netbsd.org/bsdweb.cgi/src/usr.bin/make/unit-tests/Makefile.diff?r1=1.12&r2=1.13
http://cvsweb.netbsd.org/bsdweb.cgi/src/usr.bin/make/unit-tests/test.exp.diff?r1=1.11&r2=1.12
http://cvsweb.netbsd.org/bsdweb.cgi/src/usr.bin/make/unit-tests/posix



Visit your host, monkey.org