Module Name:    src
Committed By:   rillig
Date:           Mon Apr 18 15:06:28 UTC 2022

Modified Files:
        src/distrib/sets/lists/tests: mi
        src/usr.bin/make: main.c make.1 make.h parse.c
        src/usr.bin/make/unit-tests: Makefile
Added Files:
        src/usr.bin/make/unit-tests: deptgt-posix.exp deptgt-posix.mk

Log Message:
make: only switch to POSIX mode if '.POSIX:' is the first line

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html
says that in order to make a makefile POSIX-conforming, its first
non-comment line must be the special dependency line '.POSIX:' without
any source dependencies.

Previously, make switched to POSIX mode even if such a line occurred
anywhere else, which was allowed by POSIX but was deep in the
"unspecified behavior" area.  For NetBSD make, there is no big
difference since it doesn't ship any <posix.mk> file, this change mainly
affects the bmake distribution.

Previously, makefiles that contain '.POSIX:' somewhere in the middle
could fail due to <posix.mk> resetting .SUFFIXES, among other things.

Suggested by Simon J. Gerraty, who also reviewed an earlier version of
this change.


To generate a diff of this commit:
cvs rdiff -u -r1.1192 -r1.1193 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.579 -r1.580 src/usr.bin/make/main.c
cvs rdiff -u -r1.307 -r1.308 src/usr.bin/make/make.1
cvs rdiff -u -r1.299 -r1.300 src/usr.bin/make/make.h
cvs rdiff -u -r1.668 -r1.669 src/usr.bin/make/parse.c
cvs rdiff -u -r1.311 -r1.312 src/usr.bin/make/unit-tests/Makefile
cvs rdiff -u -r0 -r1.1 src/usr.bin/make/unit-tests/deptgt-posix.exp \
    src/usr.bin/make/unit-tests/deptgt-posix.mk

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/tests/mi
diff -u src/distrib/sets/lists/tests/mi:1.1192 src/distrib/sets/lists/tests/mi:1.1193
--- src/distrib/sets/lists/tests/mi:1.1192	Fri Apr  8 23:35:52 2022
+++ src/distrib/sets/lists/tests/mi	Mon Apr 18 15:06:27 2022
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1192 2022/04/08 23:35:52 riastradh Exp $
+# $NetBSD: mi,v 1.1193 2022/04/18 15:06:27 rillig Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -5565,6 +5565,8 @@
 ./usr/tests/usr.bin/make/unit-tests/deptgt-path.mk				tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/make/unit-tests/deptgt-phony.exp				tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/make/unit-tests/deptgt-phony.mk				tests-usr.bin-tests	compattestfile,atf
+./usr/tests/usr.bin/make/unit-tests/deptgt-posix.exp				tests-usr.bin-tests	compattestfile,atf
+./usr/tests/usr.bin/make/unit-tests/deptgt-posix.mk				tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/make/unit-tests/deptgt-precious.exp				tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/make/unit-tests/deptgt-precious.mk				tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/make/unit-tests/deptgt-shell.exp				tests-usr.bin-tests	compattestfile,atf

Index: src/usr.bin/make/main.c
diff -u src/usr.bin/make/main.c:1.579 src/usr.bin/make/main.c:1.580
--- src/usr.bin/make/main.c:1.579	Tue Mar 22 23:37:09 2022
+++ src/usr.bin/make/main.c	Mon Apr 18 15:06:27 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: main.c,v 1.579 2022/03/22 23:37:09 rillig Exp $	*/
+/*	$NetBSD: main.c,v 1.580 2022/04/18 15:06:27 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -111,7 +111,7 @@
 #include "trace.h"
 
 /*	"@(#)main.c	8.3 (Berkeley) 3/19/94"	*/
-MAKE_RCSID("$NetBSD: main.c,v 1.579 2022/03/22 23:37:09 rillig Exp $");
+MAKE_RCSID("$NetBSD: main.c,v 1.580 2022/04/18 15:06:27 rillig Exp $");
 #if defined(MAKE_NATIVE) && !defined(lint)
 __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
 	    "The Regents of the University of California.  "
@@ -1480,6 +1480,7 @@ main_ReadFiles(void)
 	if (!opts.noBuiltins)
 		ReadBuiltinRules();
 
+	posix_state = PS_MAYBE_NEXT_LINE;
 	if (!Lst_IsEmpty(&opts.makefiles))
 		ReadAllMakefiles(&opts.makefiles);
 	else

Index: src/usr.bin/make/make.1
diff -u src/usr.bin/make/make.1:1.307 src/usr.bin/make/make.1:1.308
--- src/usr.bin/make/make.1:1.307	Sat Mar 26 15:39:58 2022
+++ src/usr.bin/make/make.1	Mon Apr 18 15:06:27 2022
@@ -1,4 +1,4 @@
-.\"	$NetBSD: make.1,v 1.307 2022/03/26 15:39:58 sjg Exp $
+.\"	$NetBSD: make.1,v 1.308 2022/04/18 15:06:27 rillig Exp $
 .\"
 .\" Copyright (c) 1990, 1993
 .\"	The Regents of the University of California.  All rights reserved.
@@ -29,7 +29,7 @@
 .\"
 .\"	from: @(#)make.1	8.4 (Berkeley) 3/19/94
 .\"
-.Dd March 24, 2022
+.Dd April 18, 2022
 .Dt MAKE 1
 .Os
 .Sh NAME
@@ -2290,17 +2290,15 @@ Apply the
 .Ic .PHONY
 attribute to any specified sources.
 .It Ic .POSIX
-This should be the first non-comment line in a Makefile.
-It results in the variable
+If this is the first non-comment line in the main makefile,
+the variable
 .Va %POSIX
-being defined with the value
-.Ql 1003.2 .
-The first time
-.Ic .POSIX
-is encountered, the makefile
-.Ql posix.mk
-will be included if possible,
-to provide POSIX compatible default rules.
+is set to the value
+.Ql 1003.2
+and the makefile
+.Ql <posix.mk>
+is included if it exists,
+to provide POSIX-compatible default rules.
 If
 .Nm
 is run with the

Index: src/usr.bin/make/make.h
diff -u src/usr.bin/make/make.h:1.299 src/usr.bin/make/make.h:1.300
--- src/usr.bin/make/make.h:1.299	Sat Mar 26 14:02:40 2022
+++ src/usr.bin/make/make.h	Mon Apr 18 15:06:27 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: make.h,v 1.299 2022/03/26 14:02:40 rillig Exp $	*/
+/*	$NetBSD: make.h,v 1.300 2022/04/18 15:06:27 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -506,6 +506,17 @@ typedef struct GNode {
 	unsigned lineno;
 } GNode;
 
+/*
+ * Keep track of whether to include <posix.mk> when parsing the line
+ * '.POSIX:'.
+ */
+extern enum PosixState {
+	PS_NOT_YET,
+	PS_MAYBE_NEXT_LINE,
+	PS_NOW_OR_NEVER,
+	PS_TOO_LATE
+} posix_state;
+
 /* Error levels for diagnostics during parsing. */
 typedef enum ParseErrorLevel {
 	/*

Index: src/usr.bin/make/parse.c
diff -u src/usr.bin/make/parse.c:1.668 src/usr.bin/make/parse.c:1.669
--- src/usr.bin/make/parse.c:1.668	Fri Mar 25 21:16:04 2022
+++ src/usr.bin/make/parse.c	Mon Apr 18 15:06:27 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: parse.c,v 1.668 2022/03/25 21:16:04 sjg Exp $	*/
+/*	$NetBSD: parse.c,v 1.669 2022/04/18 15:06:27 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -106,7 +106,7 @@
 #include "pathnames.h"
 
 /*	"@(#)parse.c	8.3 (Berkeley) 3/19/94"	*/
-MAKE_RCSID("$NetBSD: parse.c,v 1.668 2022/03/25 21:16:04 sjg Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.669 2022/04/18 15:06:27 rillig Exp $");
 
 /*
  * A file being read.
@@ -294,6 +294,7 @@ static const struct {
     { ".WAIT",		SP_WAIT,	OP_NONE },
 };
 
+enum PosixState posix_state = PS_NOT_YET;
 
 static IncludedFile *
 GetInclude(size_t i)
@@ -1252,23 +1253,9 @@ HandleDependencySourcesEmpty(ParseSpecia
 		break;
 #ifdef POSIX
 	case SP_POSIX:
-		Global_Set("%POSIX", "1003.2");
-		{
-			static bool first_posix = true;
-
-			/*
-			 * Since .POSIX: should be the first
-			 * operative line in a makefile,
-			 * if '-r' flag is used, no default rules have
-			 * been read yet, in which case 'posix.mk' can
-			 * be a substiute for 'sys.mk'.
-			 * If '-r' is not used, then 'posix.mk' acts
-			 * as an extension of 'sys.mk'.
-			 */
-			if (first_posix) {
-				first_posix = false;
-				IncludeFile("posix.mk", true, false, true);
-			}
+		if (posix_state == PS_NOW_OR_NEVER) {
+			Global_Set("%POSIX", "1003.2");
+			IncludeFile("posix.mk", true, false, true);
 		}
 		break;
 #endif
@@ -2590,6 +2577,10 @@ ReadHighLevelLine(void)
 
 	for (;;) {
 		line = ReadLowLevelLine(LK_NONEMPTY);
+		if (posix_state == PS_MAYBE_NEXT_LINE)
+			posix_state = PS_NOW_OR_NEVER;
+		else
+			posix_state = PS_TOO_LATE;
 		if (line == NULL)
 			return NULL;
 

Index: src/usr.bin/make/unit-tests/Makefile
diff -u src/usr.bin/make/unit-tests/Makefile:1.311 src/usr.bin/make/unit-tests/Makefile:1.312
--- src/usr.bin/make/unit-tests/Makefile:1.311	Sat Mar 26 12:44:57 2022
+++ src/usr.bin/make/unit-tests/Makefile	Mon Apr 18 15:06:28 2022
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.311 2022/03/26 12:44:57 rillig Exp $
+# $NetBSD: Makefile,v 1.312 2022/04/18 15:06:28 rillig Exp $
 #
 # Unit tests for make(1)
 #
@@ -143,6 +143,7 @@ TESTS+=		deptgt-order
 TESTS+=		deptgt-path
 TESTS+=		deptgt-path-suffix
 TESTS+=		deptgt-phony
+TESTS+=		deptgt-posix
 TESTS+=		deptgt-precious
 TESTS+=		deptgt-shell
 TESTS+=		deptgt-silent

Added files:

Index: src/usr.bin/make/unit-tests/deptgt-posix.exp
diff -u /dev/null src/usr.bin/make/unit-tests/deptgt-posix.exp:1.1
--- /dev/null	Mon Apr 18 15:06:28 2022
+++ src/usr.bin/make/unit-tests/deptgt-posix.exp	Mon Apr 18 15:06:28 2022
@@ -0,0 +1 @@
+exit status 0
Index: src/usr.bin/make/unit-tests/deptgt-posix.mk
diff -u /dev/null src/usr.bin/make/unit-tests/deptgt-posix.mk:1.1
--- /dev/null	Mon Apr 18 15:06:28 2022
+++ src/usr.bin/make/unit-tests/deptgt-posix.mk	Mon Apr 18 15:06:28 2022
@@ -0,0 +1,116 @@
+# $NetBSD: deptgt-posix.mk,v 1.1 2022/04/18 15:06:28 rillig Exp $
+#
+# Tests for the special target '.POSIX', which enables POSIX mode.
+#
+# As of 2022-04-18, this only means that the variable '%POSIX' is defined and
+# that the variables and rules specified by POSIX replace the default ones.
+# This is done by loading <posix.mk>, if available.  That file is not included
+# in NetBSD, but only in the bmake distribution.  As of 2022-04-18, POSIX
+# support is not complete.
+#
+# Implementation node: this test needs to be isolated from the usual test
+# to prevent unit-tests/posix.mk from interfering with the posix.mk from the
+# system directory that this test uses.
+#
+# See also:
+#	https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html
+
+TMPDIR?=	/tmp/make.test.deptgt-posix
+SYSDIR=		${TMPDIR}/sysdir
+MAIN_MK=	${TMPDIR}/main.mk
+INCLUDED_MK=	${TMPDIR}/included.mk
+
+all: .PHONY
+.SILENT:
+
+set-up-sysdir: .USEBEFORE
+	mkdir -p ${SYSDIR}
+	printf '%s\n' > ${SYSDIR}/sys.mk \
+	    'CC=sys-cc' \
+	    'SEEN_SYS_MK=yes'
+	printf '%s\n' > ${SYSDIR}/posix.mk \
+	    'CC=posix-cc'
+
+check-is-posix: .USE
+	printf '%s\n' >> ${MAIN_MK} \
+		'.if $${CC} != "posix-cc"' \
+		'.  error' \
+		'.endif' \
+		'.if $${%POSIX} != "1003.2"' \
+		'.  error' \
+		'.endif' \
+		'all: .PHONY'
+
+check-not-posix: .USE
+	printf '%s\n' >> ${MAIN_MK} \
+		'.if $${CC} != "sys-cc"' \
+		'.  error' \
+		'.endif' \
+		'.if defined(%POSIX)' \
+		'.  error' \
+		'.endif' \
+		'all: .PHONY'
+
+check-not-seen-sys-mk: .USE
+	printf '%s\n' >> ${MAIN_MK} \
+	    '.if defined(SEEN_SYS_MK)' \
+	    '.  error' \
+	    '.endif'
+
+run: .USE
+	(cd "${TMPDIR}" && MAKEFLAGS=${MAKEFLAGS.${.TARGET}:Q} ${MAKE} \
+	    -m "${SYSDIR}" -f ${MAIN_MK:T})
+	rm -rf ${TMPDIR}
+
+# If the main makefile has a '.for' loop as its first non-comment line, a
+# strict reading of POSIX 2018 makes the makefile non-conforming.
+all: after-for
+after-for: .PHONY set-up-sysdir check-not-posix run
+	printf '%s\n' > ${MAIN_MK} \
+	    '# comment' \
+	    '' \
+	    '.for i in once' \
+	    '.POSIX:' \
+	    '.endfor'
+
+# If the main makefile has an '.if' conditional as its first non-comment line,
+# a strict reading of POSIX 2018 makes the makefile non-conforming.
+all: after-if
+after-if: .PHONY set-up-sysdir check-not-posix run
+	printf '%s\n' > ${MAIN_MK} \
+	    '# comment' \
+	    '' \
+	    '.if 1' \
+	    '.POSIX:' \
+	    '.endif'
+
+# If the main makefile first includes another makefile and that included
+# makefile tries to switch to POSIX mode, that's too late.
+all: in-included-file
+in-included-file: .PHONY set-up-sysdir check-not-posix run
+	printf 'include included.mk\n' > ${MAIN_MK}
+	printf '.POSIX:\n' > ${INCLUDED_MK}
+
+# If the main makefile switches to POSIX mode in its very first line, before
+# and comment lines or empty lines, that works.
+all: in-first-line
+in-first-line: .PHONY set-up-sysdir check-is-posix run
+	printf '%s\n' > ${MAIN_MK} \
+	    '.POSIX:'
+
+# The only allowed lines before switching to POSIX mode are comment lines.
+# POSIX defines that empty and blank lines are called comment lines as well.
+all: after-comment-lines
+after-comment-lines: .PHONY set-up-sysdir check-is-posix run
+	printf '%s\n' > ${MAIN_MK} \
+	    '# comment' \
+	    '' \
+	    '.POSIX:'
+
+# Running make with the option '-r' skips the builtin rules from <sys.mk>.
+# In that mode, '.POSIX:' just loads <posix.mk>, which works as well.
+MAKEFLAGS.no-builtins=	-r
+all: no-builtins
+no-builtins: .PHONY set-up-sysdir check-is-posix check-not-seen-sys-mk run
+	printf '%s\n' > ${MAIN_MK} \
+	    '.POSIX:'

Reply via email to