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:'