aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon J. Gerraty <sjg@FreeBSD.org>2022-07-26 15:52:53 +0000
committerSimon J. Gerraty <sjg@FreeBSD.org>2022-07-26 15:52:53 +0000
commit308a28d6cd2e87028e535eabccb89a9dc2fd9515 (patch)
treeba6d8167e442ce861503a2bd8233d0e2e1545a8e
parent92bfae0e6bd53a7a0d6fe55e70a916d86cf26e8b (diff)
downloadsrc-308a28d6cd2e87028e535eabccb89a9dc2fd9515.tar.gz
src-308a28d6cd2e87028e535eabccb89a9dc2fd9515.zip
Import bmake-20220724vendor/NetBSD/bmake/20220724
Relevant/interesting changes: o parse.c: fix out-of-bounds read when parsing an invalid line https://bugs.freebsd.org/265119 fix memory leak in wildcard targets and sources fix off-by-one error in buffer for .WAIT nodes o allow to randomize build order of targets .MAKE.MODE += randomize-targets can help uncover dependency bugs
-rw-r--r--ChangeLog29
-rw-r--r--FILES6
-rw-r--r--VERSION2
-rw-r--r--bmake.1381
-rw-r--r--bmake.cat1707
-rw-r--r--compat.c79
-rw-r--r--dir.c6
-rw-r--r--for.c13
-rw-r--r--job.c6
-rw-r--r--main.c12
-rw-r--r--make.1381
-rw-r--r--make.c78
-rw-r--r--make.h11
-rw-r--r--mk/ChangeLog20
-rw-r--r--mk/gendirdeps.mk5
-rw-r--r--mk/install-mk4
-rw-r--r--mk/mkopt.sh31
-rw-r--r--mk/prog.mk16
-rw-r--r--mk/yacc.mk26
-rw-r--r--parse.c232
-rw-r--r--str.c97
-rw-r--r--unit-tests/Makefile13
-rw-r--r--unit-tests/cmdline.exp3
-rw-r--r--unit-tests/cmdline.mk24
-rw-r--r--unit-tests/comment.mk4
-rw-r--r--unit-tests/compat-error.mk27
-rw-r--r--unit-tests/cond-cmp-string.mk10
-rw-r--r--unit-tests/cond-func-defined.mk11
-rw-r--r--unit-tests/cond-token-string.exp3
-rw-r--r--unit-tests/cond-token-string.mk23
-rw-r--r--unit-tests/cond1.exp23
-rw-r--r--unit-tests/cond1.mk114
-rw-r--r--unit-tests/depsrc-wait.exp13
-rw-r--r--unit-tests/depsrc-wait.mk22
-rw-r--r--unit-tests/deptgt-begin.mk10
-rw-r--r--unit-tests/deptgt-end-fail-indirect.mk4
-rw-r--r--unit-tests/deptgt-end-fail.mk4
-rw-r--r--unit-tests/deptgt-posix.mk27
-rw-r--r--unit-tests/directive-for-empty.exp27
-rw-r--r--unit-tests/directive-for-empty.mk120
-rw-r--r--unit-tests/directive-for-escape.exp67
-rw-r--r--unit-tests/directive-for-escape.mk59
-rw-r--r--unit-tests/directive-for-lines.mk6
-rw-r--r--unit-tests/directive-for-null.mk10
-rw-r--r--unit-tests/directive-info.mk4
-rw-r--r--unit-tests/hanoi-include.mk25
-rw-r--r--unit-tests/opt-define.mk16
-rw-r--r--unit-tests/opt-jobs-no-action.mk4
-rw-r--r--unit-tests/opt-version.mk8
-rw-r--r--unit-tests/opt-x-reduce-exported.exp4
-rw-r--r--unit-tests/opt-x-reduce-exported.mk22
-rw-r--r--unit-tests/parse.exp1
-rw-r--r--unit-tests/parse.mk12
-rw-r--r--unit-tests/varmod-head.exp10
-rw-r--r--unit-tests/varmod-head.mk65
-rw-r--r--unit-tests/varmod-ifelse.mk17
-rw-r--r--unit-tests/varmod-match.exp5
-rw-r--r--unit-tests/varmod-match.mk132
-rw-r--r--unit-tests/varmod-quote-dollar.exp2
-rw-r--r--unit-tests/varmod-quote-dollar.mk11
-rw-r--r--unit-tests/varname-dot-make-mode.exp30
-rw-r--r--unit-tests/varname-dot-make-mode.mk41
-rw-r--r--unit-tests/varquote.exp3
-rw-r--r--unit-tests/varquote.mk14
-rw-r--r--var.c112
65 files changed, 1934 insertions, 1370 deletions
diff --git a/ChangeLog b/ChangeLog
index c4d43ef82e62..b9b5711e6e09 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2022-07-24 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20220724
+ Merge with NetBSD make, pick up
+ o make.1: describe variable assignment and evaluation more precisely
+ o parse.c: fix out-of-bounds read when parsing an invalid line
+ o var.c: simplify return type of IsShortVarnameValid
+
+2022-06-12 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20220612
+ Merge with NetBSD make, pick up
+ o allow to randomize build order of targets
+ .MAKE.MODE += randomize-targets can help uncover dependency bugs
+ within a makefile.
+ o compat.c: rename Compat_Run to Compat_MakeAll
+ o make.c: inline MakeBuildParent
+ inline make_abort, improve error details
+ o parse.c: reorganize Parse_Error
+ fix memory leak in wildcard targets and sources
+ separate cases in HandleDependencyTargetMundane
+ extract HandleSingleDependencyTargetMundane
+ rename loadfile to LoadFile
+ split IncludeFile into separate functions
+ condense code for searching a file in the paths
+ fix off-by-one error in buffer for .WAIT nodes
+ o str.c: condense Str_Match
+ make code for string matching syntactically more consistent
+
2022-04-18 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20220418
diff --git a/FILES b/FILES
index ecdd3327a9de..7a6ca8ad6212 100644
--- a/FILES
+++ b/FILES
@@ -158,8 +158,6 @@ unit-tests/cond-token-var.exp
unit-tests/cond-token-var.mk
unit-tests/cond-undef-lint.exp
unit-tests/cond-undef-lint.mk
-unit-tests/cond1.exp
-unit-tests/cond1.mk
unit-tests/counter-append.exp
unit-tests/counter-append.mk
unit-tests/counter.exp
@@ -324,6 +322,8 @@ unit-tests/directive-export-literal.exp
unit-tests/directive-export-literal.mk
unit-tests/directive-export.exp
unit-tests/directive-export.mk
+unit-tests/directive-for-empty.exp
+unit-tests/directive-for-empty.mk
unit-tests/directive-for-errors.exp
unit-tests/directive-for-errors.mk
unit-tests/directive-for-escape.exp
@@ -864,8 +864,6 @@ unit-tests/varparse-mod.exp
unit-tests/varparse-mod.mk
unit-tests/varparse-undef-partial.exp
unit-tests/varparse-undef-partial.mk
-unit-tests/varquote.exp
-unit-tests/varquote.mk
util.c
var.c
wait.h
diff --git a/VERSION b/VERSION
index ed97681843b1..34b791ec9d8f 100644
--- a/VERSION
+++ b/VERSION
@@ -1,2 +1,2 @@
# keep this compatible with sh and make
-_MAKE_VERSION=20220418
+_MAKE_VERSION=20220724
diff --git a/bmake.1 b/bmake.1
index 8ebd54ed6e31..9e7889a03923 100644
--- a/bmake.1
+++ b/bmake.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: make.1,v 1.308 2022/04/18 15:06:27 rillig Exp $
+.\" $NetBSD: make.1,v 1.315 2022/07/12 23:47:00 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 April 18, 2022
+.Dd July 12, 2022
.Dt BMAKE 1
.Os
.Sh NAME
@@ -61,12 +61,12 @@ If no
makefile option is given,
.Nm
will try to open
-.Ql Pa makefile
+.Sq Pa makefile
then
-.Ql Pa Makefile
+.Sq Pa Makefile
in order to find the specifications.
If the file
-.Ql Pa .depend
+.Sq Pa .depend
exists, it is read (see
.Xr mkdep 1 ) .
.Pp
@@ -229,11 +229,11 @@ Specify that environment variables override macro assignments within
makefiles.
.It Fl f Ar makefile
Specify a makefile to read instead of the default
-.Ql Pa makefile .
+.Sq Pa makefile .
If
.Ar makefile
is
-.Ql Fl ,
+.Sq Fl ,
standard input is read.
Multiple makefiles may be specified, and are read in the order specified.
.It Fl I Ar directory
@@ -244,7 +244,7 @@ option) is automatically included as part of this list.
.It Fl i
Ignore non-zero exit of shell commands in the makefile.
Equivalent to specifying
-.Ql Fl
+.Sq Fl
before each command line in the makefile.
.It Fl J Ar private
This option should
@@ -252,7 +252,7 @@ This option should
be specified by the user.
.Pp
When the
-.Ar j
+.Fl j
option is in use in a recursive build, this option is passed by a make
to child makes to allow all the make processes in the build to
cooperate to avoid overloading the system.
@@ -263,8 +263,8 @@ may have running at any one time.
The value is saved in
.Va .MAKE.JOBS .
Turns compatibility mode off, unless the
-.Ar B
-flag is also specified.
+.Fl B
+option is also specified.
When compatibility mode is off, all commands associated with a
target are executed in a single shell invocation as opposed to the
traditional one shell invocation per line.
@@ -319,7 +319,7 @@ as an argument).
Display the commands that would have been executed, but do not
actually execute them unless the target depends on the .MAKE special
source (see below) or the command is prefixed with
-.Ql Ic + .
+.Sq Ic + .
.It Fl N
Display the commands which would have been executed, but do not
actually execute any of them; useful for debugging top-level makefiles
@@ -336,7 +336,7 @@ This is the default behavior and the opposite of
.It Fl s
Do not echo any commands as they are executed.
Equivalent to specifying
-.Ql Ic @
+.Sq Ic @
before each command line in the makefile.
.It Fl T Ar tracefile
When used with the
@@ -493,7 +493,7 @@ While targets can appear in many dependency lines if desired, by
default only one of these rules may be followed by a creation
script.
If the
-.Ql Ic \&::
+.Sq Ic \&::
operator is used, however, all rules may include scripts and the
scripts are executed in the order found.
.Pp
@@ -505,23 +505,23 @@ in which case that line and the next are combined.
.\" normally ignores it.
.\" However, the tab at the beginning of the following line is removed.
If the first characters of the command are any combination of
-.Ql Ic @ ,
-.Ql Ic + ,
+.Sq Ic @ ,
+.Sq Ic + ,
or
-.Ql Ic \- ,
+.Sq Ic \- ,
the command is treated specially.
A
-.Ql Ic @
+.Sq Ic @
causes the command not to be echoed before it is executed.
A
-.Ql Ic +
+.Sq Ic +
causes the command to be executed even when
.Fl n
is given.
This is similar to the effect of the .MAKE special source,
except that the effect can be limited to a single line of a script.
A
-.Ql Ic \-
+.Sq Ic \-
in compatibility mode
causes any non-zero exit status of the command line to be ignored.
.Pp
@@ -538,11 +538,11 @@ it will be passed to the shell; otherwise
.Nm
will attempt direct execution.
If a line starts with
-.Ql Ic \-
+.Sq Ic \-
and the shell has ErrCtl enabled then failure of the command line
will be ignored as in compatibility mode.
Otherwise
-.Ql Ic \-
+.Sq Ic \-
affects the entire job;
the script will stop at the first command line that fails,
but the target will not be deemed to have failed.
@@ -576,27 +576,47 @@ Since
will
.Xr chdir 2
to
-.Ql Va .OBJDIR
+.Sq Va .OBJDIR
before executing any targets, each child process
starts with that as its current working directory.
.Sh VARIABLE ASSIGNMENTS
-Variables in make are much like variables in the shell, and, by tradition,
-consist of all upper-case letters.
-.Ss Variable assignment modifiers
-The five operators that can be used to assign values to variables are as
-follows:
+Variables in make behave much like macros in the C preprocessor.
+.Pp
+Variable assignments have the form
+.Sq Ar NAME Ar op Ar value ,
+where:
+.Bl -tag -width Ds
+.It Ar NAME
+is a single-word variable name,
+consisting, by tradition, of all upper-case letters,
+.It Ar op
+is one of the five variable assignment operators described below, and
+.It Ar value
+is interpreted according to the variable assignment operator.
+.El
+.Pp
+Whitespace around
+.Ar NAME ,
+.Ar op
+and
+.Ar value
+is discarded.
+.Ss Variable assignment operators
+The five operators that can be used to assign values to variables are:
.Bl -tag -width Ds
.It Ic \&=
Assign the value to the variable.
-Any previous value is overridden.
+Any previous value is overwritten.
.It Ic \&+=
-Append the value to the current value of the variable.
+Append the value to the current value of the variable,
+separating them by a single space.
.It Ic \&?=
Assign the value to the variable if it is not already defined.
.It Ic \&:=
Assign with expansion, i.e. expand the value before assigning it
to the variable.
Normally, expansion is not done until the variable is referenced.
+.Pp
.Em NOTE :
References to undefined variables are
.Em not
@@ -607,45 +627,42 @@ Expand the value and pass it to the shell for execution and assign
the result to the variable.
Any newlines in the result are replaced with spaces.
.El
-.Pp
-Any white-space before the assigned
-.Ar value
-is removed; if the value is being appended, a single space is inserted
-between the previous contents of the variable and the appended value.
-.Pp
-Variables are expanded by surrounding the variable name with either
-curly braces
-.Pq Ql {}
-or parentheses
-.Pq Ql ()
-and preceding it with
-a dollar sign
-.Pq Ql \&$ .
-If the variable name contains only a single letter, the surrounding
-braces or parentheses are not required.
+.Ss Expansion of variables
+In contexts where variables are expanded,
+.Ql \&$$
+expands to a single dollar sign.
+References to variables have the form
+.Ql \&${ Ns Ar name Ns Oo \&: Ns Ar modifiers Oc Ns }
+or
+.Ql \&$( Ns Ar name Ns Oo \&: Ns Ar modifiers Oc Ns ) .
+If the variable name contains only a single character,
+the surrounding curly braces or parentheses are not required.
This shorter form is not recommended.
.Pp
If the variable name contains a dollar, then the name itself is expanded first.
This allows almost arbitrary variable names, however names containing dollar,
-braces, parentheses, or whitespace are really best avoided!
+braces, parentheses, or whitespace are really best avoided.
.Pp
If the result of expanding a variable contains a dollar sign
-.Pq Ql \&$
+.Pq Ql \&$ ,
the string is expanded again.
.Pp
-Variable substitution occurs at three distinct times, depending on where
+Variable substitution occurs at four distinct times, depending on where
the variable is being used.
.Bl -enum
.It
Variables in dependency lines are expanded as the line is read.
.It
+Variables in conditionals are expanded individually,
+but only as far as necessary to determine the result of the conditional.
+.It
Variables in shell commands are expanded when the shell command is
executed.
.It
.Dq .for
loop index variables are expanded on each loop iteration.
-Note that other variables are not expanded inside loops so
-the following example code:
+Note that other variables are not expanded when composing the body of a loop,
+so the following example code:
.Bd -literal -offset indent
.Dv .for i in 1 2 3
@@ -726,34 +743,34 @@ The seven built-in local variables are as follows:
.Bl -tag -width ".ARCHIVE" -offset indent
.It Va .ALLSRC
The list of all sources for this target; also known as
-.Ql Va \&> .
+.Sq Va \&> .
.It Va .ARCHIVE
The name of the archive file; also known as
-.Ql Va \&! .
+.Sq Va \&! .
.It Va .IMPSRC
In suffix-transformation rules, the name/path of the source from which the
target is to be transformed (the
.Dq implied
source); also known as
-.Ql Va \&< .
+.Sq Va \&< .
It is not defined in explicit rules.
.It Va .MEMBER
The name of the archive member; also known as
-.Ql Va % .
+.Sq Va % .
.It Va .OODATE
The list of sources for this target that were deemed out-of-date; also
known as
-.Ql Va \&? .
+.Sq Va \&? .
.It Va .PREFIX
The file prefix of the target, containing only the file portion, no suffix
or preceding directory components; also known as
-.Ql Va * .
+.Sq Va * .
The suffix must be one of the known suffixes declared with
.Ic .SUFFIXES
or it will not be recognized.
.It Va .TARGET
The name of the target; also known as
-.Ql Va @ .
+.Sq Va @ .
For compatibility with other makes this is an alias for
.Ic .ARCHIVE
in archive member rules.
@@ -761,13 +778,13 @@ in archive member rules.
.Pp
The shorter forms
.Ql ( Va > ,
-.Ql Va \&! ,
-.Ql Va < ,
-.Ql Va % ,
-.Ql Va \&? ,
-.Ql Va * ,
+.Sq Va \&! ,
+.Sq Va < ,
+.Sq Va % ,
+.Sq Va \&? ,
+.Sq Va * ,
and
-.Ql Va @ )
+.Sq Va @ )
are permitted for backward
compatibility with historical makefiles and legacy POSIX make and are
not recommended.
@@ -776,8 +793,8 @@ Variants of these variables with the punctuation followed immediately by
.Ql D
or
.Ql F ,
-e.g.
-.Ql Va $(@D) ,
+e.g.\&
+.Sq Va $(@D) ,
are legacy forms equivalent to using the
.Ql :H
and
@@ -790,23 +807,16 @@ makefiles and POSIX but are not recommended.
Four of the local variables may be used in sources on dependency lines
because they expand to the proper value for each target on the line.
These variables are
-.Ql Va .TARGET ,
-.Ql Va .PREFIX ,
-.Ql Va .ARCHIVE ,
+.Sq Va .TARGET ,
+.Sq Va .PREFIX ,
+.Sq Va .ARCHIVE ,
and
-.Ql Va .MEMBER .
+.Sq Va .MEMBER .
.Ss Additional built-in variables
In addition,
.Nm
sets or knows about the following variables:
.Bl -tag -width .MAKEOVERRIDES
-.It Va \&$
-A single dollar sign
-.Ql \&$ ,
-i.e.
-.Ql \&$$
-expands to a single dollar
-sign.
.It Va .ALLTARGETS
The list of all targets encountered in the Makefile.
If evaluated during
@@ -816,7 +826,7 @@ A path to the directory where
.Nm
was executed.
Refer to the description of
-.Ql Ev PWD
+.Sq Ev PWD
for more details.
.It Va .INCLUDEDFROMDIR
The directory of the file this Makefile was included from.
@@ -839,7 +849,7 @@ because it is more compatible with other versions of
and cannot be confused with the special target with the same name.
.It Va .MAKE.DEPENDFILE
Names the makefile (default
-.Ql Pa .depend )
+.Sq Pa .depend )
from which generated dependencies are read.
.It Va .MAKE.EXPAND_VARIABLES
A boolean that controls the default behavior of the
@@ -860,17 +870,18 @@ option.
If
.Nm
is run with
-.Ar j
-then output for each target is prefixed with a token
+.Fl j ,
+the output for each target is prefixed with a token
.Ql --- target ---
the first part of which can be controlled via
.Va .MAKE.JOB.PREFIX .
If
.Va .MAKE.JOB.PREFIX
is empty, no token is printed.
-.br
-For example:
-.Li .MAKE.JOB.PREFIX=${.newline}---${.MAKE:T}[${.MAKE.PID}]
+For example, setting
+.Va .MAKE.JOB.PREFIX
+to
+.Li ${.newline}---${.MAKE:T}[${.MAKE.PID}]
would produce tokens like
.Ql ---make[1234] target ---
making it easier to track the degree of parallelism being achieved.
@@ -881,7 +892,7 @@ apparent variable assignments in dependency lines are
treated as normal sources.
.It Ev MAKEFLAGS
The environment variable
-.Ql Ev MAKEFLAGS
+.Sq Ev MAKEFLAGS
may contain anything that
may be specified on
.Nm Ns 's
@@ -889,7 +900,7 @@ command line.
Anything specified on
.Nm Ns 's
command line is appended to the
-.Ql Ev MAKEFLAGS
+.Sq Ev MAKEFLAGS
variable which is then
entered into the environment for all programs which
.Nm
@@ -908,8 +919,8 @@ to protect things which should only be evaluated in the initial instance of
.It Va .MAKE.MAKEFILE_PREFERENCE
The ordered list of makefile names
(default
-.Ql Pa makefile ,
-.Ql Pa Makefile )
+.Sq Pa makefile ,
+.Sq Pa Makefile )
that
.Nm
will look for.
@@ -944,7 +955,7 @@ The captured output can be very useful when diagnosing errors.
Normally
.Nm
will not create .meta files in
-.Ql Va .CURDIR .
+.Sq Va .CURDIR .
This can be overridden by setting
.Va bf
to a value which represents True.
@@ -978,6 +989,10 @@ If
.Va bf
is True, when a .meta file is created, mark the target
.Ic .SILENT .
+.It Pa randomize-targets
+In both compat and parallel mode, do not make the targets in the usual order,
+but instead randomize their order.
+This mode can be used to detect undeclared dependencies between files.
.El
.It Va .MAKE.META.BAILIWICK
In "meta" mode, provides a list of prefixes which
@@ -1007,7 +1022,7 @@ information.
Provides a list of path prefixes that should be ignored;
because the contents are expected to change over time.
The default list includes:
-.Ql Pa /dev /etc /proc /tmp /var/run /var/tmp
+.Sq Pa /dev /etc /proc /tmp /var/run /var/tmp
.It Va .MAKE.META.IGNORE_PATTERNS
Provides a list of patterns to match against pathnames.
Ignore any that match.
@@ -1021,16 +1036,16 @@ The default value is:
.It Va .MAKEOVERRIDES
This variable is used to record the names of variables assigned to
on the command line, so that they may be exported as part of
-.Ql Ev MAKEFLAGS .
+.Sq Ev MAKEFLAGS .
This behavior can be disabled by assigning an empty value to
-.Ql Va .MAKEOVERRIDES
+.Sq Va .MAKEOVERRIDES
within a makefile.
Extra variables can be exported from a makefile
by appending their names to
-.Ql Va .MAKEOVERRIDES .
-.Ql Ev MAKEFLAGS
+.Sq Va .MAKEOVERRIDES .
+.Sq Ev MAKEFLAGS
is re-exported whenever
-.Ql Va .MAKEOVERRIDES
+.Sq Va .MAKEOVERRIDES
is modified.
.It Va .MAKE.PATH_FILEMON
If
@@ -1068,21 +1083,21 @@ The group-id running
When
.Nm
stops due to an error, it sets
-.Ql Va .ERROR_TARGET
+.Sq Va .ERROR_TARGET
to the name of the target that failed,
-.Ql Va .ERROR_CMD
+.Sq Va .ERROR_CMD
to the commands of the failed target,
and in "meta" mode, it also sets
-.Ql Va .ERROR_CWD
+.Sq Va .ERROR_CWD
to the
.Xr getcwd 3 ,
and
-.Ql Va .ERROR_META_FILE
+.Sq Va .ERROR_META_FILE
to the path of the meta file (if any) describing the failed target.
It then prints its name and the value of
-.Ql Va .CURDIR
+.Sq Va .CURDIR
as well as the value of any variables named in
-.Ql Va MAKE_PRINT_VAR_ON_ERROR .
+.Sq Va MAKE_PRINT_VAR_ON_ERROR .
.It Va .newline
This variable is simply assigned a newline character as its value.
This allows expansions using the
@@ -1090,7 +1105,7 @@ This allows expansions using the
modifier to put a newline between
iterations of the loop rather than a space.
For example, the printing of
-.Ql Va MAKE_PRINT_VAR_ON_ERROR
+.Sq Va MAKE_PRINT_VAR_ON_ERROR
could be done as ${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@}.
.It Va .OBJDIR
A path to the directory where the targets are built.
@@ -1102,13 +1117,13 @@ to the following directories in order and using the first match:
.Ev ${MAKEOBJDIRPREFIX}${.CURDIR}
.Pp
(Only if
-.Ql Ev MAKEOBJDIRPREFIX
+.Sq Ev MAKEOBJDIRPREFIX
is set in the environment or on the command line.)
.It
.Ev ${MAKEOBJDIR}
.Pp
(Only if
-.Ql Ev MAKEOBJDIR
+.Sq Ev MAKEOBJDIR
is set in the environment or on the command line.)
.It
.Ev ${.CURDIR} Ns Pa /obj. Ns Ev ${MACHINE}
@@ -1125,77 +1140,77 @@ so expressions such as
.Dl ${.CURDIR:S,^/usr/src,/var/obj,}
may be used.
This is especially useful with
-.Ql Ev MAKEOBJDIR .
+.Sq Ev MAKEOBJDIR .
.Pp
-.Ql Va .OBJDIR
+.Sq Va .OBJDIR
may be modified in the makefile via the special target
-.Ql Ic .OBJDIR .
+.Sq Ic .OBJDIR .
In all cases,
.Nm
will
.Xr chdir 2
to the specified directory if it exists, and set
-.Ql Va .OBJDIR
+.Sq Va .OBJDIR
and
-.Ql Ev PWD
+.Sq Ev PWD
to that directory before executing any targets.
.Pp
Except in the case of an explicit
-.Ql Ic .OBJDIR
+.Sq Ic .OBJDIR
target,
.Nm
will check that the specified directory is writable and ignore it if not.
This check can be skipped by setting the environment variable
-.Ql Ev MAKE_OBJDIR_CHECK_WRITABLE
+.Sq Ev MAKE_OBJDIR_CHECK_WRITABLE
to "no".
.
.It Va .PARSEDIR
A path to the directory of the current
-.Ql Pa Makefile
+.Sq Pa Makefile
being parsed.
.It Va .PARSEFILE
The basename of the current
-.Ql Pa Makefile
+.Sq Pa Makefile
being parsed.
This variable and
-.Ql Va .PARSEDIR
+.Sq Va .PARSEDIR
are both set only while the
-.Ql Pa Makefiles
+.Sq Pa Makefiles
are being parsed.
If you want to retain their current values, assign them to a variable
-using assignment with expansion:
-.Pq Ql Cm \&:= .
+using assignment with expansion
+.Sq Cm \&:= .
.It Va .PATH
A variable that represents the list of directories that
.Nm
will search for files.
The search list should be updated using the target
-.Ql Va .PATH
+.Sq Va .PATH
rather than the variable.
.It Ev PWD
Alternate path to the current directory.
.Nm
normally sets
-.Ql Va .CURDIR
+.Sq Va .CURDIR
to the canonical path given by
.Xr getcwd 3 .
However, if the environment variable
-.Ql Ev PWD
+.Sq Ev PWD
is set and gives a path to the current directory, then
.Nm
sets
-.Ql Va .CURDIR
+.Sq Va .CURDIR
to the value of
-.Ql Ev PWD
+.Sq Ev PWD
instead.
This behavior is disabled if
-.Ql Ev MAKEOBJDIRPREFIX
+.Sq Ev MAKEOBJDIRPREFIX
is set or
-.Ql Ev MAKEOBJDIR
+.Sq Ev MAKEOBJDIR
contains a variable transform.
-.Ql Ev PWD
+.Sq Ev PWD
is set to the value of
-.Ql Va .OBJDIR
+.Sq Va .OBJDIR
for all programs which
.Nm
executes.
@@ -1215,7 +1230,7 @@ lists of directories that
will search for files.
The variable is supported for compatibility with old make programs only,
use
-.Ql Va .PATH
+.Sq Va .PATH
instead.
.El
.Ss Variable modifiers
@@ -1249,14 +1264,14 @@ The supported modifiers are:
Replaces each word in the variable with its suffix.
.It Cm \&:H
Replaces each word in the variable with everything but the last component.
-.It Cm \&:M Ns Ar pattern
+.It Cm \&:M\| Ns Ar pattern
Selects only those words that match
.Ar pattern .
The standard shell wildcard characters
.Pf ( Ql * ,
.Ql \&? ,
and
-.Ql Oo Oc )
+.Ql \&[] )
may
be used.
The wildcard characters may be escaped with a backslash
@@ -1268,9 +1283,9 @@ will normalize the inter-word spacing, removing all leading and
trailing space, and converting multiple consecutive spaces
to single spaces.
.
-.It Cm \&:N Ns Ar pattern
+.It Cm \&:N\| Ns Ar pattern
This is identical to
-.Ql Cm \&:M ,
+.Sq Cm \&:M ,
but selects all words which do not match
.Ar pattern .
.It Cm \&:O
@@ -1293,7 +1308,7 @@ Orders every word in variable in reverse numerical order.
Shuffles the words in variable.
The results will be different each time you are referring to the
modified variable; use the assignment with expansion
-.Pq Ql Cm \&:=
+.Sq Cm \&:=
to prevent such behavior.
For example,
.Bd -literal -offset indent
@@ -1327,11 +1342,11 @@ This is equivalent to:
.Sq \&:S/\e\&$/&&/g:Q .
.It Cm \&:R
Replaces each word in the variable with everything but its suffix.
-.It Cm \&:range[=count]
+.It Cm \&:range Ns Oo = Ns Ar count Oc
The value is an integer sequence representing the words of the original
value, or the supplied
.Va count .
-.It Cm \&:gmtime[=utc]
+.It Cm \&:gmtime Ns Oo = Ns Ar utc Oc
The value is a format string for
.Xr strftime 3 ,
using
@@ -1341,7 +1356,7 @@ If a
value is not provided or is 0, the current time is used.
.It Cm \&:hash
Computes a 32-bit hash of the value and encode it as hex digits.
-.It Cm \&:localtime[=utc]
+.It Cm \&:localtime Ns Oo = Ns Ar utc Oc
The value is a format string for
.Xr strftime 3 ,
using
@@ -1369,14 +1384,14 @@ Converts variable to upper-case letters.
Causes the value to be treated as a single word
(possibly containing embedded white space).
See also
-.Ql Cm \&:[*] .
+.Sq Cm \&:[*] .
.It Cm \&:tw
Causes the value to be treated as a sequence of
words delimited by white space.
See also
-.Ql Cm \&:[@] .
+.Sq Cm \&:[@] .
.Sm off
-.It Cm \&:S No \&/ Ar old_string No \&/ Ar new_string No \&/ Op Cm 1gW
+.It Cm \&:S\| No \&/ Ar old_string\| No \&/ Ar new_string\| No \&/ Op Cm 1gW
.Sm on
Modifies the first occurrence of
.Ar old_string
@@ -1431,7 +1446,7 @@ of a dollar sign
.Pq Ql \&$ ,
not a preceding dollar sign as is usual.
.Sm off
-.It Cm \&:C No \&/ Ar pattern No \&/ Ar replacement No \&/ Op Cm 1gW
+.It Cm \&:C\| No \&/ Ar pattern\| No \&/ Ar replacement\| No \&/ Op Cm 1gW
.Sm on
The
.Cm \&:C
@@ -1476,7 +1491,7 @@ Replaces each word in the variable with its last path component.
Removes adjacent duplicate words (like
.Xr uniq 1 ) .
.Sm off
-.It Cm \&:\&? Ar true_string Cm \&: Ar false_string
+.It Cm \&:\&?\| Ar true_string\| Cm \&: Ar false_string
.Sm on
If the variable name (not its value), when parsed as a .if conditional
expression, evaluates to true, return as its value the
@@ -1491,7 +1506,7 @@ A common error is trying to use expressions like
which actually tests defined(NUMBERS),
to determine if any words match "42" you need to use something like:
.Dl ${"${NUMBERS:M42}" != \&"\&":?match:no} .
-.It Ar :old_string=new_string
+.It Cm :\| Ns Ar old_string\| Ns Cm = Ns Ar new_string
This is the
.At V
style variable substitution.
@@ -1544,7 +1559,7 @@ expansion of a dollar sign
.Pq Ql \&$ ,
not a preceding dollar sign as is usual.
.Sm off
-.It Cm \&:@ Ar temp Cm @ Ar string Cm @
+.It Cm \&:@ Ar temp\| Cm @ Ar string\| Cm @
.Sm on
This is the loop expansion mechanism from the OSF Development
Environment (ODE) make.
@@ -1563,7 +1578,7 @@ For example.
.Pp
However a single character variable is often more readable:
.Dl ${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@}
-.It Cm \&:_[=var]
+.It Cm \&:_ Ns Oo Cm = Ns Ar var Oc
Saves the current variable value in
.Ql $_
or the named
@@ -1584,7 +1599,7 @@ is used to save the result of the
.Ql :S
modifier which is later referenced using the index values from
.Ql :range .
-.It Cm \&:U Ns Ar newval
+.It Cm \&:U\| Ns Ar newval
If the variable is undefined,
.Ar newval
is the value.
@@ -1594,7 +1609,7 @@ It is handy for setting per-target CFLAGS for instance:
.Dl ${_${.TARGET:T}_CFLAGS:U${DEF_CFLAGS}}
If a value is only required if the variable is undefined, use:
.Dl ${VAR:D:Unewval}
-.It Cm \&:D Ns Ar newval
+.It Cm \&:D\| Ns Ar newval
If the variable is defined,
.Ar newval
is the value.
@@ -1608,7 +1623,7 @@ name of the variable is used.
In order for this modifier to work, the name (node) must at least have
appeared on the rhs of a dependency.
.Sm off
-.It Cm \&:\&! Ar cmd Cm \&!
+.It Cm \&:\&! Ar cmd\| Cm \&!
.Sm on
The output of running
.Ar cmd
@@ -1630,7 +1645,7 @@ preceded with something to keep
happy.
.Pp
The
-.Ql Cm \&::
+.Sq Cm \&::
helps avoid false matches with the
.At V
style
@@ -1663,7 +1678,7 @@ causing a value to be treated as a single word
An empty value, or a value that consists entirely of white-space,
is treated as a single word.
For the purposes of the
-.Ql Cm \&:[]
+.Sq Cm \&:[]
modifier, the words are indexed both forwards using positive integers
(where index 1 represents the first word),
and backwards using negative integers
@@ -1685,7 +1700,7 @@ to
.Ar end ,
inclusive.
For example,
-.Ql Cm \&:[2..-1]
+.Sq Cm \&:[2..-1]
selects all words from the second word to the last word.
If
.Ar start
@@ -1693,13 +1708,13 @@ is greater than
.Ar end ,
then the words are output in reverse order.
For example,
-.Ql Cm \&:[-1..1]
+.Sq Cm \&:[-1..1]
selects all the words from last to first.
If the list is already ordered, then this effectively reverses
the list, but it is more efficient to use
-.Ql Cm \&:Or
+.Sq Cm \&:Or
instead of
-.Ql Cm \&:O:[-1..1] .
+.Sq Cm \&:O:[-1..1] .
.\" :[*]
.It Cm \&*
Causes subsequent modifiers to treat the value as a single word
@@ -1710,7 +1725,7 @@ in Bourne shell.
.\" :[0]
.It 0
Means the same as
-.Ql Cm \&:[*] .
+.Sq Cm \&:[*] .
.\" :[*]
.It Cm \&@
Causes subsequent modifiers to treat the value as a sequence of words
@@ -1837,14 +1852,14 @@ PATH := ${PATH}
.Pp
.Ed
Would result in an environment containing only
-.Ql Ev PATH ,
+.Sq Ev PATH ,
which is the minimal useful environment.
Actually
-.Ql Ev .MAKE.LEVEL
+.Sq Ev .MAKE.LEVEL
will also be pushed into the new environment.
.It Ic .warning Ar message
The message prefixed by
-.Ql Pa warning:
+.Sq Pa warning:
is printed along with the name of the makefile and line number.
.It Ic \&.if Oo \&! Oc Ns Ar expression Op Ar operator expression ...
Test the value of an expression.
@@ -1860,29 +1875,29 @@ Test the target being built.
Reverse the sense of the last conditional.
.It Ic .elif Oo \&! Ns Oc Ar expression Op Ar operator expression ...
A combination of
-.Ql Ic .else
+.Sq Ic .else
followed by
-.Ql Ic .if .
+.Sq Ic .if .
.It Ic .elifdef Oo \&! Oc Ns Ar variable Op Ar operator variable ...
A combination of
-.Ql Ic .else
+.Sq Ic .else
followed by
-.Ql Ic .ifdef .
+.Sq Ic .ifdef .
.It Ic .elifndef Oo \&! Oc Ns Ar variable Op Ar operator variable ...
A combination of
-.Ql Ic .else
+.Sq Ic .else
followed by
-.Ql Ic .ifndef .
+.Sq Ic .ifndef .
.It Ic .elifmake Oo \&! Oc Ns Ar target Op Ar operator target ...
A combination of
-.Ql Ic .else
+.Sq Ic .else
followed by
-.Ql Ic .ifmake .
+.Sq Ic .ifmake .
.It Ic .elifnmake Oo \&! Oc Ns Ar target Op Ar operator target ...
A combination of
-.Ql Ic .else
+.Sq Ic .else
followed by
-.Ql Ic .ifnmake .
+.Sq Ic .ifnmake .
.It Ic .endif
End the body of the conditional.
.El
@@ -1906,11 +1921,11 @@ will only evaluate a conditional as far as is necessary to determine
its value.
Parentheses may be used to change the order of evaluation.
The boolean operator
-.Ql Ic \&!
+.Sq Ic \&!
may be used to logically negate an entire
conditional.
It is of higher precedence than
-.Ql Ic \&&& .
+.Sq Ic \&&& .
.Pp
The value of
.Ar expression
@@ -1952,9 +1967,9 @@ preceded by 0x, otherwise it is decimal; octal numbers are not supported.
The standard C relational operators are all supported.
If after
variable expansion, either the left or right hand side of a
-.Ql Ic ==
+.Sq Ic ==
or
-.Ql Ic "!="
+.Sq Ic "!="
operator is not a numerical value, then
string comparison is performed between the expanded
variables.
@@ -1971,17 +1986,17 @@ or
.Dq defined
expression is applied to it, depending on the form of the conditional.
If the form is
-.Ql Ic .ifdef ,
-.Ql Ic .ifndef ,
+.Sq Ic .ifdef ,
+.Sq Ic .ifndef ,
or
-.Ql Ic .if
+.Sq Ic .if
the
.Dq defined
expression is applied.
Similarly, if the form is
-.Ql Ic .ifmake
+.Sq Ic .ifmake
or
-.Ql Ic .ifnmake ,
+.Sq Ic .ifnmake ,
the
.Dq make
expression is applied.
@@ -1990,9 +2005,9 @@ If the conditional evaluates to true the parsing of the makefile continues
as before.
If it evaluates to false, the following lines are skipped.
In both cases this continues until a
-.Ql Ic .else
+.Sq Ic .else
or
-.Ql Ic .endif
+.Sq Ic .endif
is found.
.Pp
For loops are typically used to apply a set of rules to a list of files.
@@ -2243,16 +2258,17 @@ Synonym for
for compatibility with other pmake variants.
.It Ic .OBJDIR
The source is a new value for
-.Ql Va .OBJDIR .
+.Sq Va .OBJDIR .
If it exists,
.Nm
will
.Xr chdir 2
to it and update the value of
-.Ql Va .OBJDIR .
+.Sq Va .OBJDIR .
.It Ic .ORDER
-The named targets are made in sequence.
+In parallel mode, the named targets are made in sequence.
This ordering does not add targets to the list of targets to be made.
+.Pp
Since the dependents of a target do not get built until the target itself
could be built, unless
.Ql a
@@ -2263,9 +2279,6 @@ the following is a dependency loop:
b: a
.Ed
.Pp
-The ordering imposed by
-.Ic .ORDER
-is only relevant for parallel makes.
.\" XXX: NOT YET!!!!
.\" .It Ic .PARALLEL
.\" The named targets are executed in parallel mode.
@@ -2409,7 +2422,7 @@ may only be set in the environment or on the command line to
.Nm
and not as makefile variables;
see the description of
-.Ql Va .OBJDIR
+.Sq Va .OBJDIR
for more details.
.Sh FILES
.Bl -tag -width /usr/share/mk -compact
diff --git a/bmake.cat1 b/bmake.cat1
index b4442ea67b2e..ff19b554c8c3 100644
--- a/bmake.cat1
+++ b/bmake.cat1
@@ -1,7 +1,7 @@
BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
NAME
- bmake -- maintain program dependencies
+ bmake — maintain program dependencies
SYNOPSIS
bmake [-BeikNnqrSstWwX] [-C directory] [-D variable] [-d flags]
@@ -10,11 +10,11 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
[variable=value] [target ...]
DESCRIPTION
- bmake is a program designed to simplify the maintenance of other pro-
+ bmake is a program designed to simplify the maintenance of other pro‐
grams. Its input is a list of specifications as to the files upon which
programs and other files depend. If no -f makefile makefile option is
- given, bmake will try to open `makefile' then `Makefile' in order to find
- the specifications. If the file `.depend' exists, it is read (see
+ given, bmake will try to open ‘makefile’ then ‘Makefile’ in order to find
+ the specifications. If the file ‘.depend’ exists, it is read (see
mkdep(1)).
This manual page is intended as a reference document only. For a more
@@ -31,8 +31,8 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
dependency line in sequence.
-C directory
- Change to directory before reading the makefiles or doing any-
- thing else. If multiple -C options are specified, each is inter-
+ Change to directory before reading the makefiles or doing any‐
+ thing else. If multiple -C options are specified, each is inter‐
preted relative to the previous one: -C / -C etc is equivalent to
-C /etc.
@@ -42,11 +42,11 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
-d [-]flags
Turn on debugging, and specify which portions of bmake are to
print debugging information. Unless the flags are preceded by
- `-' they are added to the MAKEFLAGS environment variable and will
+ ‘-’ they are added to the MAKEFLAGS environment variable and will
be processed by any child make processes. By default, debugging
information is printed to standard error, but this can be changed
- using the F debugging flag. The debugging output is always un-
- buffered; in addition, if debugging is enabled but debugging out-
+ using the F debugging flag. The debugging output is always un‐
+ buffered; in addition, if debugging is enabled but debugging out‐
put is not directed to standard output, then the standard output
is line buffered. Flags is one or more of the following:
@@ -56,7 +56,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
a Print debugging information about archive searching and
caching.
- C Print debugging information about current working direc-
+ C Print debugging information about current working direc‐
tory.
c Print debugging information about conditional evaluation.
@@ -70,14 +70,14 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
F[+]filename
Specify where debugging output is written. This must be
the last flag, because it consumes the remainder of the
- argument. If the character immediately after the `F'
- flag is `+', then the file will be opened in append mode;
+ argument. If the character immediately after the ‘F’
+ flag is ‘+’, then the file will be opened in append mode;
otherwise the file will be overwritten. If the file name
- is `stdout' or `stderr' then debugging output will be
+ is ‘stdout’ or ‘stderr’ then debugging output will be
written to the standard output or standard error output
- file descriptors respectively (and the `+' option has no
+ file descriptors respectively (and the ‘+’ option has no
effect). Otherwise, the output will be written to the
- named file. If the file name ends `.%d' then the `%d' is
+ named file. If the file name ends ‘.%d’ then the ‘%d’ is
replaced by the pid.
f Print debugging information about loop evaluation.
@@ -99,18 +99,18 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
assignment so the file and line number are available.
l Print commands in Makefiles regardless of whether or not
- they are prefixed by `@' or other "quiet" flags. Also
+ they are prefixed by ‘@’ or other "quiet" flags. Also
known as "loud" behavior.
M Print debugging information about "meta" mode decisions
about targets.
- m Print debugging information about making targets, includ-
+ m Print debugging information about making targets, includ‐
ing modification dates.
n Don't delete the temporary command scripts created when
running commands. These temporary scripts are created in
- the directory referred to by the TMPDIR environment vari-
+ the directory referred to by the TMPDIR environment vari‐
able, or in /tmp if TMPDIR is unset or set to the empty
string. The temporary scripts are created by mkstemp(3),
and have names of the form makeXXXXXX. NOTE: This can
@@ -121,7 +121,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
s Print debugging information about suffix-transformation
rules.
- t Print debugging information about target list mainte-
+ t Print debugging information about target list mainte‐
nance.
V Force the -V option to print raw values of variables,
@@ -137,8 +137,8 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
within makefiles.
-f makefile
- Specify a makefile to read instead of the default `makefile'. If
- makefile is `-', standard input is read. Multiple makefiles may
+ Specify a makefile to read instead of the default ‘makefile’. If
+ makefile is ‘-’, standard input is read. Multiple makefiles may
be specified, and are read in the order specified.
-I directory
@@ -146,27 +146,27 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
makefiles. The system makefile directory (or directories, see
the -m option) is automatically included as part of this list.
- -i Ignore non-zero exit of shell commands in the makefile. Equiva-
- lent to specifying `-' before each command line in the makefile.
+ -i Ignore non-zero exit of shell commands in the makefile. Equiva‐
+ lent to specifying ‘-’ before each command line in the makefile.
-J private
This option should not be specified by the user.
- When the j option is in use in a recursive build, this option is
+ When the -j option is in use in a recursive build, this option is
passed by a make to child makes to allow all the make processes
in the build to cooperate to avoid overloading the system.
-j max_jobs
Specify the maximum number of jobs that bmake may have running at
- any one time. The value is saved in .MAKE.JOBS. Turns compati-
- bility mode off, unless the B flag is also specified. When com-
- patibility mode is off, all commands associated with a target are
- executed in a single shell invocation as opposed to the tradi-
- tional one shell invocation per line. This can break traditional
- scripts which change directories on each command invocation and
- then expect to start with a fresh environment on the next line.
- It is more efficient to correct the scripts rather than turn
- backwards compatibility on.
+ any one time. The value is saved in .MAKE.JOBS. Turns compati‐
+ bility mode off, unless the -B option is also specified. When
+ compatibility mode is off, all commands associated with a target
+ are executed in a single shell invocation as opposed to the tra‐
+ ditional one shell invocation per line. This can break tradi‐
+ tional scripts which change directories on each command invoca‐
+ tion and then expect to start with a fresh environment on the
+ next line. It is more efficient to correct the scripts rather
+ than turn backwards compatibility on.
-k Continue processing after errors are encountered, but only on
those targets that do not depend on the target whose creation
@@ -176,9 +176,9 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
Specify a directory in which to search for sys.mk and makefiles
included via the <file>-style include statement. The -m option
can be used multiple times to form a search path. This path will
- override the default system include path: /usr/share/mk. Fur-
+ override the default system include path: /usr/share/mk. Fur‐
thermore the system include path will be appended to the search
- path used for "file"-style include statements (see the -I op-
+ path used for "file"-style include statements (see the -I op‐
tion).
If a file or directory name in the -m argument (or the
@@ -186,15 +186,15 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
then bmake will search for the specified file or directory named
in the remaining part of the argument string. The search starts
with the current directory of the Makefile and then works upward
- towards the root of the file system. If the search is success-
- ful, then the resulting directory replaces the ".../" specifica-
+ towards the root of the file system. If the search is success‐
+ ful, then the resulting directory replaces the ".../" specifica‐
tion in the -m argument. If used, this feature allows bmake to
easily search in the current source tree for customized sys.mk
files (e.g., by using ".../mk/sys.mk" as an argument).
-n Display the commands that would have been executed, but do not
- actually execute them unless the target depends on the .MAKE spe-
- cial source (see below) or the command is prefixed with `+'.
+ actually execute them unless the target depends on the .MAKE spe‐
+ cial source (see below) or the command is prefixed with ‘+’.
-N Display the commands which would have been executed, but do not
actually execute any of them; useful for debugging top-level
@@ -209,7 +209,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
behavior and the opposite of -k.
-s Do not echo any commands as they are executed. Equivalent to
- specifying `@' before each command line in the makefile.
+ specifying ‘@’ before each command line in the makefile.
-T tracefile
When used with the -j flag, append a trace record to tracefile
@@ -222,17 +222,17 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
-V variable
Print the value of variable. Do not build any targets. Multiple
instances of this option may be specified; the variables will be
- printed one per line, with a blank line for each null or unde-
+ printed one per line, with a blank line for each null or unde‐
fined variable. The value printed is extracted from the global
scope after all makefiles have been read. By default, the raw
- variable contents (which may include additional unexpanded vari-
- able references) are shown. If variable contains a `$' then the
+ variable contents (which may include additional unexpanded vari‐
+ able references) are shown. If variable contains a ‘$’ then the
value will be recursively expanded to its complete resultant text
before printing. The expanded value will also be printed if
.MAKE.EXPAND_VARIABLES is set to true and the -dV option has not
been used to override it. Note that loop-local and target-local
- variables, as well as values taken temporarily by global vari-
- ables during makefile processing, are not accessible via this op-
+ variables, as well as values taken temporarily by global vari‐
+ ables during makefile processing, are not accessible via this op‐
tion. The -dv debug mode can be used to see these at the cost of
generating substantial extraneous output.
@@ -242,19 +242,19 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
-W Treat any warnings during makefile parsing as errors.
- -w Print entering and leaving directory messages, pre and post pro-
+ -w Print entering and leaving directory messages, pre and post pro‐
cessing.
- -X Don't export variables passed on the command line to the environ-
+ -X Don't export variables passed on the command line to the environ‐
ment individually. Variables passed on the command line are
- still exported via the MAKEFLAGS environment variable. This op-
+ still exported via the MAKEFLAGS environment variable. This op‐
tion may be useful on systems which have a small limit on the
size of command arguments.
variable=value
Set the value of the variable variable to value. Normally, all
values passed on the command line are also exported to sub-makes
- in the environment. The -X flag disables this behavior. Vari-
+ in the environment. The -X flag disables this behavior. Vari‐
able assignments should follow options for POSIX compatibility
but no ordering is enforced.
@@ -263,13 +263,13 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
conditional directives, for loops, and comments.
In general, lines may be continued from one line to the next by ending
- them with a backslash (`\'). The trailing newline character and initial
+ them with a backslash (‘\’). The trailing newline character and initial
whitespace on the following line are compressed into a single space.
FILE DEPENDENCY SPECIFICATIONS
Dependency lines consist of one or more targets, an operator, and zero or
- more sources. This creates a relationship where the targets "depend" on
- the sources and are customarily created from them. A target is consid-
+ more sources. This creates a relationship where the targets “depend” on
+ the sources and are customarily created from them. A target is consid‐
ered out-of-date if it does not exist, or if its modification time is
less than that of any of its sources. An out-of-date target will be re-
created, but not until all sources have been examined and themselves re-
@@ -278,63 +278,63 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
: Many dependency lines may name this target but only one may have
attached shell commands. All sources named in all dependency lines
are considered together, and if needed the attached shell commands
- are run to create or re-create the target. If bmake is inter-
+ are run to create or re-create the target. If bmake is inter‐
rupted, the target is removed.
! The same, but the target is always re-created whether or not it is
out of date.
:: Any dependency line may have attached shell commands, but each one
- is handled independently: its sources are considered and the at-
- tached shell commands are run if the target is out of date with re-
- spect to (only) those sources. Thus, different groups of the at-
+ is handled independently: its sources are considered and the at‐
+ tached shell commands are run if the target is out of date with re‐
+ spect to (only) those sources. Thus, different groups of the at‐
tached shell commands may be run depending on the circumstances.
Furthermore, unlike :, for dependency lines with no sources, the
attached shell commands are always run. Also unlike :, the target
will not be removed if bmake is interrupted.
- All dependency lines mentioning a particular target must use the same op-
+ All dependency lines mentioning a particular target must use the same op‐
erator.
- Targets and sources may contain the shell wildcard values `?', `*', `[]',
- and `{}'. The values `?', `*', and `[]' may only be used as part of the
- final component of the target or source, and must be used to describe ex-
- isting files. The value `{}' need not necessarily be used to describe
+ Targets and sources may contain the shell wildcard values ‘?’, ‘*’, ‘[]’,
+ and ‘{}’. The values ‘?’, ‘*’, and ‘[]’ may only be used as part of the
+ final component of the target or source, and must be used to describe ex‐
+ isting files. The value ‘{}’ need not necessarily be used to describe
existing files. Expansion is in directory order, not alphabetically as
done in the shell.
SHELL COMMANDS
- Each target may have associated with it one or more lines of shell com-
+ Each target may have associated with it one or more lines of shell com‐
mands, normally used to create the target. Each of the lines in this
script must be preceded by a tab. (For historical reasons, spaces are
- not accepted.) While targets can appear in many dependency lines if de-
+ not accepted.) While targets can appear in many dependency lines if de‐
sired, by default only one of these rules may be followed by a creation
- script. If the `::' operator is used, however, all rules may include
+ script. If the ‘::’ operator is used, however, all rules may include
scripts and the scripts are executed in the order found.
Each line is treated as a separate shell command, unless the end of line
- is escaped with a backslash (`\') in which case that line and the next
+ is escaped with a backslash (‘\’) in which case that line and the next
are combined. If the first characters of the command are any combination
- of `@', `+', or `-', the command is treated specially. A `@' causes the
- command not to be echoed before it is executed. A `+' causes the command
+ of ‘@’, ‘+’, or ‘-’, the command is treated specially. A ‘@’ causes the
+ command not to be echoed before it is executed. A ‘+’ causes the command
to be executed even when -n is given. This is similar to the effect of
- the .MAKE special source, except that the effect can be limited to a sin-
- gle line of a script. A `-' in compatibility mode causes any non-zero
+ the .MAKE special source, except that the effect can be limited to a sin‐
+ gle line of a script. A ‘-’ in compatibility mode causes any non-zero
exit status of the command line to be ignored.
When bmake is run in jobs mode with -j max_jobs, the entire script for
the target is fed to a single instance of the shell. In compatibility
- (non-jobs) mode, each command is run in a separate process. If the com-
- mand contains any shell meta characters (`#=|^(){};&<>*?[]:$`\\n') it
- will be passed to the shell; otherwise bmake will attempt direct execu-
- tion. If a line starts with `-' and the shell has ErrCtl enabled then
+ (non-jobs) mode, each command is run in a separate process. If the com‐
+ mand contains any shell meta characters (‘#=|^(){};&<>*?[]:$`\\n’) it
+ will be passed to the shell; otherwise bmake will attempt direct execu‐
+ tion. If a line starts with ‘-’ and the shell has ErrCtl enabled then
failure of the command line will be ignored as in compatibility mode.
- Otherwise `-' affects the entire job; the script will stop at the first
+ Otherwise ‘-’ affects the entire job; the script will stop at the first
command line that fails, but the target will not be deemed to have
failed.
Makefiles should be written so that the mode of bmake operation does not
- change their behavior. For example, any command which needs to use "cd"
- or "chdir" without potentially changing the directory for subsequent com-
+ change their behavior. For example, any command which needs to use “cd”
+ or “chdir” without potentially changing the directory for subsequent com‐
mands should be put in parentheses so it executes in a subshell. To
force the use of one shell, escape the line breaks so as to make the
whole script one command. For example:
@@ -349,63 +349,75 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
(cd ${.CURDIR} && ${MAKE} $@); \
echo Back in `pwd`
- Since bmake will chdir(2) to `.OBJDIR' before executing any targets, each
+ Since bmake will chdir(2) to ‘.OBJDIR’ before executing any targets, each
child process starts with that as its current working directory.
VARIABLE ASSIGNMENTS
- Variables in make are much like variables in the shell, and, by tradi-
- tion, consist of all upper-case letters.
+ Variables in make behave much like macros in the C preprocessor.
- Variable assignment modifiers
- The five operators that can be used to assign values to variables are as
- follows:
+ Variable assignments have the form ‘NAME op value’, where:
- = Assign the value to the variable. Any previous value is overrid-
- den.
+ NAME is a single-word variable name, consisting, by tradition, of all
+ upper-case letters,
- += Append the value to the current value of the variable.
+ op is one of the five variable assignment operators described below,
+ and
+
+ value is interpreted according to the variable assignment operator.
+
+ Whitespace around NAME, op and value is discarded.
+
+ Variable assignment operators
+ The five operators that can be used to assign values to variables are:
+
+ = Assign the value to the variable. Any previous value is over‐
+ written.
+
+ += Append the value to the current value of the variable, separating
+ them by a single space.
?= Assign the value to the variable if it is not already defined.
:= Assign with expansion, i.e. expand the value before assigning it
- to the variable. Normally, expansion is not done until the vari-
- able is referenced. NOTE: References to undefined variables are
- not expanded. This can cause problems when variable modifiers
- are used.
+ to the variable. Normally, expansion is not done until the vari‐
+ able is referenced.
+
+ NOTE: References to undefined variables are not expanded. This
+ can cause problems when variable modifiers are used.
- != Expand the value and pass it to the shell for execution and as-
+ != Expand the value and pass it to the shell for execution and as‐
sign the result to the variable. Any newlines in the result are
replaced with spaces.
- Any white-space before the assigned value is removed; if the value is be-
- ing appended, a single space is inserted between the previous contents of
- the variable and the appended value.
-
- Variables are expanded by surrounding the variable name with either curly
- braces (`{}') or parentheses (`()') and preceding it with a dollar sign
- (`$'). If the variable name contains only a single letter, the surround-
- ing braces or parentheses are not required. This shorter form is not
- recommended.
+ Expansion of variables
+ In contexts where variables are expanded, ‘$$’ expands to a single dollar
+ sign. References to variables have the form ‘${name[:modifiers]}’ or
+ ‘$(name[:modifiers]’). If the variable name contains only a single char‐
+ acter, the surrounding curly braces or parentheses are not required.
+ This shorter form is not recommended.
If the variable name contains a dollar, then the name itself is expanded
- first. This allows almost arbitrary variable names, however names con-
+ first. This allows almost arbitrary variable names, however names con‐
taining dollar, braces, parentheses, or whitespace are really best
- avoided!
+ avoided.
- If the result of expanding a variable contains a dollar sign (`$') the
+ If the result of expanding a variable contains a dollar sign (‘$’), the
string is expanded again.
- Variable substitution occurs at three distinct times, depending on where
+ Variable substitution occurs at four distinct times, depending on where
the variable is being used.
1. Variables in dependency lines are expanded as the line is read.
- 2. Variables in shell commands are expanded when the shell command is
+ 2. Variables in conditionals are expanded individually, but only as far
+ as necessary to determine the result of the conditional.
+
+ 3. Variables in shell commands are expanded when the shell command is
executed.
- 3. ".for" loop index variables are expanded on each loop iteration.
- Note that other variables are not expanded inside loops so the fol-
- lowing example code:
+ 4. “.for” loop index variables are expanded on each loop iteration.
+ Note that other variables are not expanded when composing the body
+ of a loop, so the following example code:
.for i in 1 2 3
@@ -423,12 +435,12 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
1 2 3
3 3 3
- Because while ${a} contains "1 2 3" after the loop is executed, ${b}
- contains "${j} ${j} ${j}" which expands to "3 3 3" since after the
- loop completes ${j} contains "3".
+ Because while ${a} contains “1 2 3” after the loop is executed, ${b}
+ contains “${j} ${j} ${j}” which expands to “3 3 3” since after the
+ loop completes ${j} contains “3”.
Variable classes
- The four different classes of variables (in order of increasing prece-
+ The four different classes of variables (in order of increasing prece‐
dence) are:
Environment variables
@@ -444,7 +456,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
Variables that are defined specific to a certain target.
Local variables can be set on a dependency line, if
- .MAKE.TARGET_LOCAL_VARIABLES is not set to `false'. The rest of the line
+ .MAKE.TARGET_LOCAL_VARIABLES is not set to ‘false’. The rest of the line
(which will already have had global variables expanded) is the variable
value. For example:
@@ -452,7 +464,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
${OBJS}: .MAKE.META.CMP_FILTER=${COMPILER_WRAPPERS:S,^,N,}
- Only the targets `${OBJS}' will be impacted by that filter (in "meta"
+ Only the targets ‘${OBJS}’ will be impacted by that filter (in "meta"
mode) and simply enabling/disabling any of the compiler wrappers will not
render all of those targets out-of-date.
@@ -467,55 +479,52 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
The seven built-in local variables are as follows:
.ALLSRC The list of all sources for this target; also known as
- `>'.
+ ‘>’.
- .ARCHIVE The name of the archive file; also known as `!'.
+ .ARCHIVE The name of the archive file; also known as ‘!’.
.IMPSRC In suffix-transformation rules, the name/path of the
source from which the target is to be transformed (the
- "implied" source); also known as `<'. It is not defined
+ “implied” source); also known as ‘<’. It is not defined
in explicit rules.
- .MEMBER The name of the archive member; also known as `%'.
+ .MEMBER The name of the archive member; also known as ‘%’.
.OODATE The list of sources for this target that were deemed out-
- of-date; also known as `?'.
+ of-date; also known as ‘?’.
.PREFIX The file prefix of the target, containing only the file
portion, no suffix or preceding directory components;
- also known as `*'. The suffix must be one of the known
- suffixes declared with .SUFFIXES or it will not be recog-
+ also known as ‘*’. The suffix must be one of the known
+ suffixes declared with .SUFFIXES or it will not be recog‐
nized.
- .TARGET The name of the target; also known as `@'. For compati-
+ .TARGET The name of the target; also known as ‘@’. For compati‐
bility with other makes this is an alias for .ARCHIVE in
archive member rules.
- The shorter forms (`>', `!', `<', `%', `?', `*', and `@') are permitted
+ The shorter forms (‘>’, ‘!’, ‘<’, ‘%’, ‘?’, ‘*’, and ‘@’) are permitted
for backward compatibility with historical makefiles and legacy POSIX
make and are not recommended.
Variants of these variables with the punctuation followed immediately by
- `D' or `F', e.g. `$(@D)', are legacy forms equivalent to using the `:H'
- and `:T' modifiers. These forms are accepted for compatibility with AT&T
+ ‘D’ or ‘F’, e.g. ‘$(@D)’, are legacy forms equivalent to using the ‘:H’
+ and ‘:T’ modifiers. These forms are accepted for compatibility with AT&T
System V UNIX makefiles and POSIX but are not recommended.
Four of the local variables may be used in sources on dependency lines
because they expand to the proper value for each target on the line.
- These variables are `.TARGET', `.PREFIX', `.ARCHIVE', and `.MEMBER'.
+ These variables are ‘.TARGET’, ‘.PREFIX’, ‘.ARCHIVE’, and ‘.MEMBER’.
Additional built-in variables
In addition, bmake sets or knows about the following variables:
- $ A single dollar sign `$', i.e. `$$' expands to a single
- dollar sign.
-
.ALLTARGETS The list of all targets encountered in the Makefile. If
- evaluated during Makefile parsing, lists only those tar-
+ evaluated during Makefile parsing, lists only those tar‐
gets encountered thus far.
.CURDIR A path to the directory where bmake was executed. Refer
- to the description of `PWD' for more details.
+ to the description of ‘PWD’ for more details.
.INCLUDEDFROMDIR
The directory of the file this Makefile was included
@@ -532,14 +541,14 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
the same name.
.MAKE.DEPENDFILE
- Names the makefile (default `.depend') from which gener-
+ Names the makefile (default ‘.depend’) from which gener‐
ated dependencies are read.
.MAKE.EXPAND_VARIABLES
A boolean that controls the default behavior of the -V
option. If true, variable values printed with -V are
fully expanded; if false, the raw variable contents
- (which may include additional unexpanded variable refer-
+ (which may include additional unexpanded variable refer‐
ences) are shown.
.MAKE.EXPORTED The list of variables exported by bmake.
@@ -547,36 +556,35 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
.MAKE.JOBS The argument to the -j option.
.MAKE.JOB.PREFIX
- If bmake is run with j then output for each target is
- prefixed with a token `--- target ---' the first part of
+ If bmake is run with -j, the output for each target is
+ prefixed with a token ‘--- target ---’ the first part of
which can be controlled via .MAKE.JOB.PREFIX. If
- .MAKE.JOB.PREFIX is empty, no token is printed.
- For example:
- .MAKE.JOB.PREFIX=${.newline}---${.MAKE:T}[${.MAKE.PID}]
- would produce tokens like `---make[1234] target ---' mak-
- ing it easier to track the degree of parallelism being
- achieved.
+ .MAKE.JOB.PREFIX is empty, no token is printed. For ex‐
+ ample, setting .MAKE.JOB.PREFIX to
+ ${.newline}---${.MAKE:T}[${.MAKE.PID}] would produce to‐
+ kens like ‘---make[1234] target ---’ making it easier to
+ track the degree of parallelism being achieved.
.MAKE.TARGET_LOCAL_VARIABLES
- If set to `false', apparent variable assignments in de-
+ If set to ‘false’, apparent variable assignments in de‐
pendency lines are treated as normal sources.
- MAKEFLAGS The environment variable `MAKEFLAGS' may contain anything
+ MAKEFLAGS The environment variable ‘MAKEFLAGS’ may contain anything
that may be specified on bmake's command line. Anything
specified on bmake's command line is appended to the
- `MAKEFLAGS' variable which is then entered into the envi-
+ ‘MAKEFLAGS’ variable which is then entered into the envi‐
ronment for all programs which bmake executes.
.MAKE.LEVEL The recursion depth of bmake. The initial instance of
bmake will be 0, and an incremented value is put into the
- environment to be seen by the next generation. This al-
+ environment to be seen by the next generation. This al‐
lows tests like: .if ${.MAKE.LEVEL} == 0 to protect
- things which should only be evaluated in the initial in-
+ things which should only be evaluated in the initial in‐
stance of bmake.
.MAKE.MAKEFILE_PREFERENCE
- The ordered list of makefile names (default `makefile',
- `Makefile') that bmake will look for.
+ The ordered list of makefile names (default ‘makefile’,
+ ‘Makefile’) that bmake will look for.
.MAKE.MAKEFILES
The list of makefiles read by bmake, which is useful for
@@ -584,23 +592,23 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
once, regardless of the number of times read.
.MAKE.MODE Processed after reading all makefiles. Can affect the
- mode that bmake runs in. It can contain a number of key-
+ mode that bmake runs in. It can contain a number of key‐
words:
compat Like -B, puts bmake into "compat"
mode.
meta Puts bmake into "meta" mode, where
- meta files are created for each tar-
+ meta files are created for each tar‐
get to capture the command run, the
output generated and if filemon(4)
is available, the system calls which
- are of interest to bmake. The cap-
+ are of interest to bmake. The cap‐
tured output can be very useful when
diagnosing errors.
curdirOk= bf Normally bmake will not create .meta
- files in `.CURDIR'. This can be
+ files in ‘.CURDIR’. This can be
overridden by setting bf to a value
which represents True.
@@ -625,7 +633,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
ignore-cmd Some makefiles have commands which
are simply not stable. This keyword
- causes them to be ignored for deter-
+ causes them to be ignored for deter‐
mining whether a target is out of
date in "meta" mode. See also
.NOMETA_CMP.
@@ -633,6 +641,13 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
silent= bf If bf is True, when a .meta file is
created, mark the target .SILENT.
+ randomize-targets In both compat and parallel mode, do
+ not make the targets in the usual
+ order, but instead randomize their
+ order. This mode can be used to de‐
+ tect undeclared dependencies between
+ files.
+
.MAKE.META.BAILIWICK
In "meta" mode, provides a list of prefixes which match
the directories controlled by bmake. If a file that was
@@ -643,7 +658,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
In "meta" mode, it can (very rarely!) be useful to filter
command lines before comparison. This variable can be
set to a set of modifiers that will be applied to each
- line of the old and new command that differ, if the fil-
+ line of the old and new command that differ, if the fil‐
tered commands still differ, the target is considered
out-of-date.
@@ -655,14 +670,14 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
.MAKE.META.FILES
In "meta" mode, this variable contains a list of all the
meta files used (updated or not). This list can be used
- to process the meta files to extract dependency informa-
+ to process the meta files to extract dependency informa‐
tion.
.MAKE.META.IGNORE_PATHS
Provides a list of path prefixes that should be ignored;
because the contents are expected to change over time.
- The default list includes: `/dev /etc /proc /tmp /var/run
- /var/tmp'
+ The default list includes: ‘/dev /etc /proc /tmp /var/run
+ /var/tmp’
.MAKE.META.IGNORE_PATTERNS
Provides a list of patterns to match against pathnames.
@@ -678,12 +693,12 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
Building ${.TARGET:H:tA}/${.TARGET:T}
.MAKEOVERRIDES This variable is used to record the names of variables
- assigned to on the command line, so that they may be ex-
- ported as part of `MAKEFLAGS'. This behavior can be dis-
- abled by assigning an empty value to `.MAKEOVERRIDES'
+ assigned to on the command line, so that they may be ex‐
+ ported as part of ‘MAKEFLAGS’. This behavior can be dis‐
+ abled by assigning an empty value to ‘.MAKEOVERRIDES’
within a makefile. Extra variables can be exported from
- a makefile by appending their names to `.MAKEOVERRIDES'.
- `MAKEFLAGS' is re-exported whenever `.MAKEOVERRIDES' is
+ a makefile by appending their names to ‘.MAKEOVERRIDES’.
+ ‘MAKEFLAGS’ is re-exported whenever ‘.MAKEOVERRIDES’ is
modified.
.MAKE.PATH_FILEMON
@@ -696,45 +711,45 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
.MAKE.PPID The parent process-id of bmake.
.MAKE.SAVE_DOLLARS
- value should be a boolean that controls whether `$$' are
- preserved when doing `:=' assignments. The default is
- false, for backwards compatibility. Set to true for com-
- patability with other makes. If set to false, `$$' be-
- comes `$' per normal evaluation rules.
+ value should be a boolean that controls whether ‘$$’ are
+ preserved when doing ‘:=’ assignments. The default is
+ false, for backwards compatibility. Set to true for com‐
+ patability with other makes. If set to false, ‘$$’ be‐
+ comes ‘$’ per normal evaluation rules.
.MAKE.UID The user-id running bmake.
.MAKE.GID The group-id running bmake.
MAKE_PRINT_VAR_ON_ERROR
- When bmake stops due to an error, it sets `.ERROR_TARGET'
- to the name of the target that failed, `.ERROR_CMD' to
+ When bmake stops due to an error, it sets ‘.ERROR_TARGET’
+ to the name of the target that failed, ‘.ERROR_CMD’ to
the commands of the failed target, and in "meta" mode, it
- also sets `.ERROR_CWD' to the getcwd(3), and
- `.ERROR_META_FILE' to the path of the meta file (if any)
+ also sets ‘.ERROR_CWD’ to the getcwd(3), and
+ ‘.ERROR_META_FILE’ to the path of the meta file (if any)
describing the failed target. It then prints its name
- and the value of `.CURDIR' as well as the value of any
- variables named in `MAKE_PRINT_VAR_ON_ERROR'.
+ and the value of ‘.CURDIR’ as well as the value of any
+ variables named in ‘MAKE_PRINT_VAR_ON_ERROR’.
.newline This variable is simply assigned a newline character as
its value. This allows expansions using the :@ modifier
to put a newline between iterations of the loop rather
than a space. For example, the printing of
- `MAKE_PRINT_VAR_ON_ERROR' could be done as
+ ‘MAKE_PRINT_VAR_ON_ERROR’ could be done as
${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@}.
.OBJDIR A path to the directory where the targets are built. Its
- value is determined by trying to chdir(2) to the follow-
+ value is determined by trying to chdir(2) to the follow‐
ing directories in order and using the first match:
1. ${MAKEOBJDIRPREFIX}${.CURDIR}
- (Only if `MAKEOBJDIRPREFIX' is set in the environ-
+ (Only if ‘MAKEOBJDIRPREFIX’ is set in the environ‐
ment or on the command line.)
2. ${MAKEOBJDIR}
- (Only if `MAKEOBJDIR' is set in the environment or
+ (Only if ‘MAKEOBJDIR’ is set in the environment or
on the command line.)
3. ${.CURDIR}/obj.${MACHINE}
@@ -749,41 +764,41 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
used, so expressions such as
${.CURDIR:S,^/usr/src,/var/obj,}
may be used. This is especially useful with
- `MAKEOBJDIR'.
+ ‘MAKEOBJDIR’.
- `.OBJDIR' may be modified in the makefile via the special
- target `.OBJDIR'. In all cases, bmake will chdir(2) to
- the specified directory if it exists, and set `.OBJDIR'
- and `PWD' to that directory before executing any targets.
+ ‘.OBJDIR’ may be modified in the makefile via the special
+ target ‘.OBJDIR’. In all cases, bmake will chdir(2) to
+ the specified directory if it exists, and set ‘.OBJDIR’
+ and ‘PWD’ to that directory before executing any targets.
- Except in the case of an explicit `.OBJDIR' target, bmake
+ Except in the case of an explicit ‘.OBJDIR’ target, bmake
will check that the specified directory is writable and
ignore it if not. This check can be skipped by setting
- the environment variable `MAKE_OBJDIR_CHECK_WRITABLE' to
+ the environment variable ‘MAKE_OBJDIR_CHECK_WRITABLE’ to
"no".
- .PARSEDIR A path to the directory of the current `Makefile' being
+ .PARSEDIR A path to the directory of the current ‘Makefile’ being
parsed.
- .PARSEFILE The basename of the current `Makefile' being parsed.
- This variable and `.PARSEDIR' are both set only while the
- `Makefiles' are being parsed. If you want to retain
- their current values, assign them to a variable using as-
- signment with expansion: (`:=').
+ .PARSEFILE The basename of the current ‘Makefile’ being parsed.
+ This variable and ‘.PARSEDIR’ are both set only while the
+ ‘Makefiles’ are being parsed. If you want to retain
+ their current values, assign them to a variable using as‐
+ signment with expansion ‘:=’.
.PATH A variable that represents the list of directories that
bmake will search for files. The search list should be
- updated using the target `.PATH' rather than the vari-
+ updated using the target ‘.PATH’ rather than the vari‐
able.
PWD Alternate path to the current directory. bmake normally
- sets `.CURDIR' to the canonical path given by getcwd(3).
- However, if the environment variable `PWD' is set and
+ sets ‘.CURDIR’ to the canonical path given by getcwd(3).
+ However, if the environment variable ‘PWD’ is set and
gives a path to the current directory, then bmake sets
- `.CURDIR' to the value of `PWD' instead. This behavior
- is disabled if `MAKEOBJDIRPREFIX' is set or `MAKEOBJDIR'
- contains a variable transform. `PWD' is set to the value
- of `.OBJDIR' for all programs which bmake executes.
+ ‘.CURDIR’ to the value of ‘PWD’ instead. This behavior
+ is disabled if ‘MAKEOBJDIRPREFIX’ is set or ‘MAKEOBJDIR’
+ contains a variable transform. ‘PWD’ is set to the value
+ of ‘.OBJDIR’ for all programs which bmake executes.
.SHELL The pathname of the shell used to run target scripts. It
is read-only.
@@ -793,20 +808,20 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
.TARGETS The list of targets explicitly specified on the command
line, if any.
- VPATH Colon-separated (":") lists of directories that bmake
+ VPATH Colon-separated (“:”) lists of directories that bmake
will search for files. The variable is supported for
- compatibility with old make programs only, use `.PATH'
+ compatibility with old make programs only, use ‘.PATH’
instead.
Variable modifiers
Variable expansion may be modified to select or modify each word of the
- variable (where a "word" is white-space delimited sequence of charac-
+ variable (where a “word” is white-space delimited sequence of charac‐
ters). The general format of a variable expansion is as follows:
${variable[:modifier[:...]]}
Each modifier begins with a colon, which may be escaped with a backslash
- (`\').
+ (‘\’).
A set of modifiers can be specified via a variable, as follows:
@@ -815,20 +830,20 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
In this case the first modifier in the modifier_variable does not start
with a colon, since that must appear in the referencing variable. If any
- of the modifiers in the modifier_variable contain a dollar sign (`$'),
+ of the modifiers in the modifier_variable contain a dollar sign (‘$’),
these must be doubled to avoid early expansion.
The supported modifiers are:
:E Replaces each word in the variable with its suffix.
- :H Replaces each word in the variable with everything but the last com-
+ :H Replaces each word in the variable with everything but the last com‐
ponent.
:Mpattern
Selects only those words that match pattern. The standard shell
- wildcard characters (`*', `?', and `[]') may be used. The wildcard
- characters may be escaped with a backslash (`\'). As a consequence
+ wildcard characters (‘*’, ‘?’, and ‘[]’) may be used. The wildcard
+ characters may be escaped with a backslash (‘\’). As a consequence
of the way values are split into words, matched, and then joined, a
construct like
${VAR:M*}
@@ -837,13 +852,13 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
spaces.
:Npattern
- This is identical to `:M', but selects all words which do not match
+ This is identical to ‘:M’, but selects all words which do not match
pattern.
:O Orders every word in variable alphabetically.
:On Orders every word in variable numerically. A number followed by one
- of `k', `M' or `G' is multiplied by the appropriate factor (1024
+ of ‘k’, ‘M’ or ‘G’ is multiplied by the appropriate factor (1024
(k), 1048576 (M), or 1073741824 (G)). Both upper- and lower-case
letters are accepted.
@@ -854,7 +869,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
:Ox Shuffles the words in variable. The results will be different each
time you are referring to the modified variable; use the assignment
- with expansion (`:=') to prevent such behavior. For example,
+ with expansion ‘:=’ to prevent such behavior. For example,
LIST= uno due tre quattro
RANDOM_LIST= ${LIST:Ox}
@@ -876,23 +891,23 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
passed safely to the shell.
:q Quotes every shell meta-character in the variable, and also doubles
- `$' characters so that it can be passed safely through recursive in-
- vocations of bmake. This is equivalent to: `:S/\$/&&/g:Q'.
+ ‘$’ characters so that it can be passed safely through recursive in‐
+ vocations of bmake. This is equivalent to: ‘:S/\$/&&/g:Q’.
:R Replaces each word in the variable with everything but its suffix.
- :range[=count]
- The value is an integer sequence representing the words of the orig-
+ :range[=count]
+ The value is an integer sequence representing the words of the orig‐
inal value, or the supplied count.
- :gmtime[=utc]
+ :gmtime[=utc]
The value is a format string for strftime(3), using gmtime(3). If a
utc value is not provided or is 0, the current time is used.
:hash
Computes a 32-bit hash of the value and encode it as hex digits.
- :localtime[=utc]
+ :localtime[=utc]
The value is a format string for strftime(3), using localtime(3).
If a utc value is not provided or is 0, the current time is used.
@@ -902,7 +917,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
:tl Converts variable to lower-case letters.
:tsc
- Words in the variable are normally separated by a space on expan-
+ Words in the variable are normally separated by a space on expan‐
sion. This modifier sets the separator to the character c. If c is
omitted, then no separator is used. The common escapes (including
octal numeric codes) work as expected.
@@ -910,42 +925,42 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
:tu Converts variable to upper-case letters.
:tW Causes the value to be treated as a single word (possibly containing
- embedded white space). See also `:[*]'.
+ embedded white space). See also ‘:[*]’.
:tw Causes the value to be treated as a sequence of words delimited by
- white space. See also `:[@]'.
+ white space. See also ‘:[@]’.
:S/old_string/new_string/[1gW]
Modifies the first occurrence of old_string in each word of the
- variable's value, replacing it with new_string. If a `g' is ap-
+ variable's value, replacing it with new_string. If a ‘g’ is ap‐
pended to the last delimiter of the pattern, all occurrences in each
- word are replaced. If a `1' is appended to the last delimiter of
- the pattern, only the first occurrence is affected. If a `W' is ap-
+ word are replaced. If a ‘1’ is appended to the last delimiter of
+ the pattern, only the first occurrence is affected. If a ‘W’ is ap‐
pended to the last delimiter of the pattern, then the value is
treated as a single word (possibly containing embedded white space).
- If old_string begins with a caret (`^'), old_string is anchored at
+ If old_string begins with a caret (‘^’), old_string is anchored at
the beginning of each word. If old_string ends with a dollar sign
- (`$'), it is anchored at the end of each word. Inside new_string,
- an ampersand (`&') is replaced by old_string (without any `^' or
- `$'). Any character may be used as a delimiter for the parts of the
+ (‘$’), it is anchored at the end of each word. Inside new_string,
+ an ampersand (‘&’) is replaced by old_string (without any ‘^’ or
+ ‘$’). Any character may be used as a delimiter for the parts of the
modifier string. The anchoring, ampersand and delimiter characters
- may be escaped with a backslash (`\').
+ may be escaped with a backslash (‘\’).
Variable expansion occurs in the normal fashion inside both
old_string and new_string with the single exception that a backslash
- is used to prevent the expansion of a dollar sign (`$'), not a pre-
+ is used to prevent the expansion of a dollar sign (‘$’), not a pre‐
ceding dollar sign as is usual.
:C/pattern/replacement/[1gW]
The :C modifier is just like the :S modifier except that the old and
- new strings, instead of being simple strings, are an extended regu-
+ new strings, instead of being simple strings, are an extended regu‐
lar expression (see regex(3)) string pattern and an ed(1)-style
string replacement. Normally, the first occurrence of the pattern
pattern in each word of the value is substituted with replacement.
- The `1' modifier causes the substitution to apply to at most one
- word; the `g' modifier causes the substitution to apply to as many
+ The ‘1’ modifier causes the substitution to apply to at most one
+ word; the ‘g’ modifier causes the substitution to apply to as many
instances of the search pattern pattern as occur in the word or
- words it is found in; the `W' modifier causes the value to be
+ words it is found in; the ‘W’ modifier causes the value to be
treated as a single word (possibly containing embedded white space).
As for the :S modifier, the pattern and replacement are subjected to
@@ -956,7 +971,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
:u Removes adjacent duplicate words (like uniq(1)).
:?true_string:false_string
- If the variable name (not its value), when parsed as a .if condi-
+ If the variable name (not its value), when parsed as a .if condi‐
tional expression, evaluates to true, return as its value the
true_string, otherwise return the false_string. Since the variable
name is used as the expression, :? must be the first modifier after
@@ -968,13 +983,13 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
match "42" you need to use something like:
${"${NUMBERS:M42}" != "":?match:no}.
- :old_string=new_string
+ :old_string=new_string
This is the AT&T System V UNIX style variable substitution. It must
be the last modifier specified. If old_string or new_string do not
contain the pattern matching character % then it is assumed that
- they are anchored at the end of each word, so only suffixes or en-
+ they are anchored at the end of each word, so only suffixes or en‐
tire words may be replaced. Otherwise % is the substring of
- old_string to be replaced in new_string. If only old_string con-
+ old_string to be replaced in new_string. If only old_string con‐
tains the pattern matching character %, and old_string matches, then
the result is the new_string. If only the new_string contains the
pattern matching character %, then it is not treated specially and
@@ -986,13 +1001,13 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
Variable expansion occurs in the normal fashion inside both
old_string and new_string with the single exception that a backslash
- is used to prevent the expansion of a dollar sign (`$'), not a pre-
+ is used to prevent the expansion of a dollar sign (‘$’), not a pre‐
ceding dollar sign as is usual.
:@temp@string@
- This is the loop expansion mechanism from the OSF Development Envi-
+ This is the loop expansion mechanism from the OSF Development Envi‐
ronment (ODE) make. Unlike .for loops, expansion occurs at the time
- of reference. Assigns temp to each word in the variable and evalu-
+ of reference. Assigns temp to each word in the variable and evalu‐
ates string. The ODE convention is that temp should start and end
with a period. For example.
${LINKS:@.LINK.@${LN} ${TARGET} ${.LINK.}@}
@@ -1000,8 +1015,8 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
However a single character variable is often more readable:
${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@}
- :_[=var]
- Saves the current variable value in `$_' or the named var for later
+ :_[=var]
+ Saves the current variable value in ‘$_’ or the named var for later
reference. Example usage:
M_cmpv.units = 1 1000 1000000
@@ -1010,13 +1025,13 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
.if ${VERSION:${M_cmpv}} < ${3.1.12:L:${M_cmpv}}
- Here `$_' is used to save the result of the `:S' modifier which is
- later referenced using the index values from `:range'.
+ Here ‘$_’ is used to save the result of the ‘:S’ modifier which is
+ later referenced using the index values from ‘:range’.
:Unewval
If the variable is undefined, newval is the value. If the variable
is defined, the existing value is returned. This is another ODE
- make feature. It is handy for setting per-target CFLAGS for in-
+ make feature. It is handy for setting per-target CFLAGS for in‐
stance:
${_${.TARGET:T}_CFLAGS:U${DEF_CFLAGS}}
If a value is only required if the variable is undefined, use:
@@ -1046,7 +1061,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
in a rule line by themselves should be preceded with something to
keep bmake happy.
- The `::' helps avoid false matches with the AT&T System V UNIX style
+ The ‘::’ helps avoid false matches with the AT&T System V UNIX style
:= modifier and since substitution always occurs the ::= form is
vaguely appropriate.
@@ -1060,37 +1075,37 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
Assign the output of cmd to the variable.
:[range]
- Selects one or more words from the value, or performs other opera-
+ Selects one or more words from the value, or performs other opera‐
tions related to the way in which the value is divided into words.
Ordinarily, a value is treated as a sequence of words delimited by
white space. Some modifiers suppress this behavior, causing a value
to be treated as a single word (possibly containing embedded white
space). An empty value, or a value that consists entirely of white-
- space, is treated as a single word. For the purposes of the `:[]'
- modifier, the words are indexed both forwards using positive inte-
+ space, is treated as a single word. For the purposes of the ‘:[]’
+ modifier, the words are indexed both forwards using positive inte‐
gers (where index 1 represents the first word), and backwards using
negative integers (where index -1 represents the last word).
- The range is subjected to variable expansion, and the expanded re-
+ The range is subjected to variable expansion, and the expanded re‐
sult is then interpreted as follows:
index Selects a single word from the value.
start..end
Selects all words from start to end, inclusive. For example,
- `:[2..-1]' selects all words from the second word to the last
- word. If start is greater than end, then the words are out-
- put in reverse order. For example, `:[-1..1]' selects all
- the words from last to first. If the list is already or-
+ ‘:[2..-1]’ selects all words from the second word to the last
+ word. If start is greater than end, then the words are out‐
+ put in reverse order. For example, ‘:[-1..1]’ selects all
+ the words from last to first. If the list is already or‐
dered, then this effectively reverses the list, but it is
- more efficient to use `:Or' instead of `:O:[-1..1]'.
+ more efficient to use ‘:Or’ instead of ‘:O:[-1..1]’.
* Causes subsequent modifiers to treat the value as a single
word (possibly containing embedded white space). Analogous
to the effect of "$*" in Bourne shell.
- 0 Means the same as `:[*]'.
+ 0 Means the same as ‘:[*]’.
@ Causes subsequent modifiers to treat the value as a sequence
of words delimited by white space. Analogous to the effect
@@ -1101,20 +1116,20 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
INCLUDE STATEMENTS, CONDITIONALS AND FOR LOOPS
Makefile inclusion, conditional structures and for loops reminiscent of
the C programming language are provided in bmake. All such structures
- are identified by a line beginning with a single dot (`.') character.
- Files are included with either .include <file> or .include "file". Vari-
+ are identified by a line beginning with a single dot (‘.’) character.
+ Files are included with either .include <file> or .include "file". Vari‐
ables between the angle brackets or double quotes are expanded to form
- the file name. If angle brackets are used, the included makefile is ex-
+ the file name. If angle brackets are used, the included makefile is ex‐
pected to be in the system makefile directory. If double quotes are
used, the including makefile's directory and any directories specified
using the -I option are searched before the system makefile directory.
- For compatibility with other versions of bmake `include file ...' is also
+ For compatibility with other versions of bmake ‘include file ...’ is also
accepted.
- If the include statement is written as .-include or as .sinclude then er-
+ If the include statement is written as .-include or as .sinclude then er‐
rors locating and/or opening include files are ignored.
- If the include statement is written as .dinclude not only are errors lo-
+ If the include statement is written as .dinclude not only are errors lo‐
cating and/or opening include files ignored, but stale dependencies
within the included file will be ignored just like .MAKE.DEPENDFILE.
@@ -1128,20 +1143,20 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
.export variable ...
Export the specified global variable. If no variable list is
provided, all globals are exported except for internal variables
- (those that start with `.'). This is not affected by the -X
+ (those that start with ‘.’). This is not affected by the -X
flag, so should be used with caution. For compatibility with
- other bmake programs `export variable=value' is also accepted.
+ other bmake programs ‘export variable=value’ is also accepted.
- Appending a variable name to .MAKE.EXPORTED is equivalent to ex-
+ Appending a variable name to .MAKE.EXPORTED is equivalent to ex‐
porting a variable.
.export-env variable ...
- The same as `.export', except that the variable is not appended
- to .MAKE.EXPORTED. This allows exporting a value to the environ-
+ The same as ‘.export’, except that the variable is not appended
+ to .MAKE.EXPORTED. This allows exporting a value to the environ‐
ment which is different from that used by bmake internally.
.export-literal variable ...
- The same as `.export-env', except that variables in the value are
+ The same as ‘.export-env’, except that variables in the value are
not expanded.
.info message
@@ -1153,16 +1168,16 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
can be un-defined.
.unexport variable ...
- The opposite of `.export'. The specified global variable will be
+ The opposite of ‘.export’. The specified global variable will be
removed from .MAKE.EXPORTED. If no variable list is provided,
all globals are unexported, and .MAKE.EXPORTED deleted.
.unexport-env
- Unexport all globals previously exported and clear the environ-
- ment inherited from the parent. This operation will cause a mem-
- ory leak of the original environment, so should be used spar-
+ Unexport all globals previously exported and clear the environ‐
+ ment inherited from the parent. This operation will cause a mem‐
+ ory leak of the original environment, so should be used spar‐
ingly. Testing for .MAKE.LEVEL being 0, would make sense. Also
- note that any variables which originated in the parent environ-
+ note that any variables which originated in the parent environ‐
ment should be explicitly preserved if desired. For example:
.if ${.MAKE.LEVEL} == 0
@@ -1171,12 +1186,12 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
.export PATH
.endif
- Would result in an environment containing only `PATH', which is
- the minimal useful environment. Actually `.MAKE.LEVEL' will also
+ Would result in an environment containing only ‘PATH’, which is
+ the minimal useful environment. Actually ‘.MAKE.LEVEL’ will also
be pushed into the new environment.
.warning message
- The message prefixed by `warning:' is printed along with the name
+ The message prefixed by ‘warning:’ is printed along with the name
of the makefile and line number.
.if [!]expression [operator expression ...]
@@ -1197,19 +1212,19 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
.else Reverse the sense of the last conditional.
.elif [!] expression [operator expression ...]
- A combination of `.else' followed by `.if'.
+ A combination of ‘.else’ followed by ‘.if’.
.elifdef [!]variable [operator variable ...]
- A combination of `.else' followed by `.ifdef'.
+ A combination of ‘.else’ followed by ‘.ifdef’.
.elifndef [!]variable [operator variable ...]
- A combination of `.else' followed by `.ifndef'.
+ A combination of ‘.else’ followed by ‘.ifndef’.
.elifmake [!]target [operator target ...]
- A combination of `.else' followed by `.ifmake'.
+ A combination of ‘.else’ followed by ‘.ifmake’.
.elifnmake [!]target [operator target ...]
- A combination of `.else' followed by `.ifnmake'.
+ A combination of ‘.else’ followed by ‘.ifnmake’.
.endif End the body of the conditional.
@@ -1217,12 +1232,12 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
|| Logical OR.
- && Logical AND; of higher precedence than "||".
+ && Logical AND; of higher precedence than “||”.
As in C, bmake will only evaluate a conditional as far as is necessary to
determine its value. Parentheses may be used to change the order of
- evaluation. The boolean operator `!' may be used to logically negate an
- entire conditional. It is of higher precedence than `&&'.
+ evaluation. The boolean operator ‘!’ may be used to logically negate an
+ entire conditional. It is of higher precedence than ‘&&’.
The value of expression may be any of the following:
@@ -1230,7 +1245,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
the variable has been defined.
make Takes a target name as an argument and evaluates to true if the
- target was specified as part of bmake's command line or was de-
+ target was specified as part of bmake's command line or was de‐
clared the default target (either implicitly or explicitly, see
.MAIN) before the line containing the conditional.
@@ -1249,34 +1264,34 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
Takes a target name as an argument and evaluates to true if the
target has been defined and has commands associated with it.
- Expression may also be an arithmetic or string comparison. Variable ex-
- pansion is performed on both sides of the comparison, after which the nu-
+ Expression may also be an arithmetic or string comparison. Variable ex‐
+ pansion is performed on both sides of the comparison, after which the nu‐
merical values are compared. A value is interpreted as hexadecimal if it
- is preceded by 0x, otherwise it is decimal; octal numbers are not sup-
+ is preceded by 0x, otherwise it is decimal; octal numbers are not sup‐
ported. The standard C relational operators are all supported. If after
- variable expansion, either the left or right hand side of a `==' or `!='
+ variable expansion, either the left or right hand side of a ‘==’ or ‘!=’
operator is not a numerical value, then string comparison is performed
between the expanded variables. If no relational operator is given, it
is assumed that the expanded variable is being compared against 0, or an
empty string in the case of a string comparison.
- When bmake is evaluating one of these conditional expressions, and it en-
+ When bmake is evaluating one of these conditional expressions, and it en‐
counters a (white-space separated) word it doesn't recognize, either the
- "make" or "defined" expression is applied to it, depending on the form of
- the conditional. If the form is `.ifdef', `.ifndef', or `.if' the
- "defined" expression is applied. Similarly, if the form is `.ifmake' or
- `.ifnmake', the "make" expression is applied.
+ “make” or “defined” expression is applied to it, depending on the form of
+ the conditional. If the form is ‘.ifdef’, ‘.ifndef’, or ‘.if’ the
+ “defined” expression is applied. Similarly, if the form is ‘.ifmake’ or
+ ‘.ifnmake’, the “make” expression is applied.
- If the conditional evaluates to true the parsing of the makefile contin-
+ If the conditional evaluates to true the parsing of the makefile contin‐
ues as before. If it evaluates to false, the following lines are
- skipped. In both cases this continues until a `.else' or `.endif' is
+ skipped. In both cases this continues until a ‘.else’ or ‘.endif’ is
found.
For loops are typically used to apply a set of rules to a list of files.
The syntax of a for loop is:
.for variable [variable ...] in expression
- <make-lines>
+ ⟨make-lines⟩
.endfor
After the for expression is evaluated, it is split into words. On each
@@ -1287,15 +1302,15 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
must be a multiple of three.
COMMENTS
- Comments begin with a hash (`#') character, anywhere but in a shell com-
+ Comments begin with a hash (‘#’) character, anywhere but in a shell com‐
mand line, and continue to the end of an unescaped new line.
SPECIAL SOURCES (ATTRIBUTES)
- .EXEC Target is never out of date, but always execute commands any-
+ .EXEC Target is never out of date, but always execute commands any‐
way.
- .IGNORE Ignore any errors from the commands associated with this tar-
- get, exactly as if they all were preceded by a dash (`-').
+ .IGNORE Ignore any errors from the commands associated with this tar‐
+ get, exactly as if they all were preceded by a dash (‘-’).
.MADE Mark all sources of this target as being up-to-date.
@@ -1317,7 +1332,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
always changes. If the number of commands change, though, the
target will still be out of date. The same effect applies to
any command line that uses the variable .OODATE, which can be
- used for that purpose even when not otherwise needed or de-
+ used for that purpose even when not otherwise needed or de‐
sired:
@@ -1326,7 +1341,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
@echo this will not ${.OODATE:M.NOMETA_CMP}
@echo this will also be compared
- The :M pattern suppresses any expansion of the unwanted vari-
+ The :M pattern suppresses any expansion of the unwanted vari‐
able.
.NOPATH Do not search for the target in the directories specified by
@@ -1337,7 +1352,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
source prevents this target from being selected.
.OPTIONAL
- If a target is marked with this attribute and bmake can't fig-
+ If a target is marked with this attribute and bmake can't fig‐
ure out how to create it, it will ignore this fact and assume
the file isn't needed or already exists.
@@ -1348,16 +1363,16 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
.PRECIOUS
When bmake is interrupted, it normally removes any partially
- made targets. This source prevents the target from being re-
+ made targets. This source prevents the target from being re‐
moved.
.RECURSIVE
Synonym for .MAKE.
.SILENT Do not echo any of the commands associated with this target,
- exactly as if they all were preceded by an at sign (`@').
+ exactly as if they all were preceded by an at sign (‘@’).
- .USE Turn the target into bmake's version of a macro. When the tar-
+ .USE Turn the target into bmake's version of a macro. When the tar‐
get is used as a source for another target, the other target
acquires the commands, sources, and attributes (except for
.USE) of the source. If the target already has commands, the
@@ -1369,7 +1384,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
.WAIT If .WAIT appears in a dependency line, the sources that precede
it are made before the sources that succeed it in the line.
- Since the dependents of files are not made until the file it-
+ Since the dependents of files are not made until the file it‐
self could be made, this also stops the dependents being built
unless they are needed for another branch of the dependency
tree. So given:
@@ -1383,7 +1398,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
b1:
echo b1
- the output is always `a', `b1', `b', `x'.
+ the output is always ‘a’, ‘b1’, ‘b’, ‘x’.
The ordering imposed by .WAIT is only relevant for parallel
makes.
@@ -1396,7 +1411,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
.DEFAULT
This is sort of a .USE rule for any target (that was used only
- as a source) that bmake can't figure out any other way to cre-
+ as a source) that bmake can't figure out any other way to cre‐
ate. Only the shell script is used. The .IMPSRC variable of a
target that inherits .DEFAULT's commands is set to the target's
own name.
@@ -1406,13 +1421,13 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
make to delete targets whose commands fail. (By default, only
targets whose commands are interrupted during execution are
deleted. This is the historical behavior.) This setting can be
- used to help prevent half-finished or malformed targets from be-
+ used to help prevent half-finished or malformed targets from be‐
ing left around and corrupting future rebuilds.
- .END Any command lines attached to this target are executed after ev-
+ .END Any command lines attached to this target are executed after ev‐
erything else is done.
- .ERROR Any command lines attached to this target are executed when an-
+ .ERROR Any command lines attached to this target are executed when an‐
other target fails. The .ERROR_TARGET variable is set to the
target that failed. See also MAKE_PRINT_VAR_ON_ERROR.
@@ -1441,23 +1456,21 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
Synonym for .NOTPARALLEL, for compatibility with other pmake
variants.
- .OBJDIR The source is a new value for `.OBJDIR'. If it exists, bmake
- will chdir(2) to it and update the value of `.OBJDIR'.
+ .OBJDIR The source is a new value for ‘.OBJDIR’. If it exists, bmake
+ will chdir(2) to it and update the value of ‘.OBJDIR’.
+
+ .ORDER In parallel mode, the named targets are made in sequence. This
+ ordering does not add targets to the list of targets to be made.
- .ORDER The named targets are made in sequence. This ordering does not
- add targets to the list of targets to be made. Since the depen-
- dents of a target do not get built until the target itself could
- be built, unless `a' is built by another part of the dependency
- graph, the following is a dependency loop:
+ Since the dependents of a target do not get built until the tar‐
+ get itself could be built, unless ‘a’ is built by another part
+ of the dependency graph, the following is a dependency loop:
.ORDER: b a
b: a
- The ordering imposed by .ORDER is only relevant for parallel
- makes.
-
.PATH The sources are directories which are to be searched for files
- not found in the current directory. If no sources are speci-
+ not found in the current directory. If no sources are speci‐
fied, any previously specified directories are deleted. If the
source is the special .DOTLAST target, then the current working
directory is searched last.
@@ -1469,14 +1482,14 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
.PHONY Apply the .PHONY attribute to any specified sources.
.POSIX If this is the first non-comment line in the main makefile, the
- variable %POSIX is set to the value `1003.2' and the makefile
- `<posix.mk>' is included if it exists, to provide POSIX-compati-
+ variable %POSIX is set to the value ‘1003.2’ and the makefile
+ ‘<posix.mk>’ is included if it exists, to provide POSIX-compati‐
ble default rules. If bmake is run with the -r flag, then only
- `posix.mk' will contribute to the default rules.
+ ‘posix.mk’ will contribute to the default rules.
.PRECIOUS
Apply the .PRECIOUS attribute to any specified sources. If no
- sources are specified, the .PRECIOUS attribute is applied to ev-
+ sources are specified, the .PRECIOUS attribute is applied to ev‐
ery target in the file.
.SHELL Sets the shell that bmake will use to execute commands. The
@@ -1495,15 +1508,15 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
echo The command to turn on echoing of commands executed.
- quiet The command to turn off echoing of commands exe-
+ quiet The command to turn off echoing of commands exe‐
cuted.
- filter The output to filter after issuing the quiet com-
+ filter The output to filter after issuing the quiet com‐
mand. It is typically identical to quiet.
errFlag The flag to pass the shell to enable error checking.
- echoFlag The flag to pass the shell to enable command echo-
+ echoFlag The flag to pass the shell to enable command echo‐
ing.
newline The string literal to pass the shell that results in
@@ -1520,7 +1533,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
sources are specified, the .SILENT attribute is applied to every
command in the file.
- .STALE This target gets run when a dependency file contains stale en-
+ .STALE This target gets run when a dependency file contains stale en‐
tries, having .ALLSRC set to the name of that dependency file.
.SUFFIXES
@@ -1540,8 +1553,8 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
PWD, and TMPDIR.
MAKEOBJDIRPREFIX and MAKEOBJDIR may only be set in the environment or on
- the command line to bmake and not as makefile variables; see the descrip-
- tion of `.OBJDIR' for more details.
+ the command line to bmake and not as makefile variables; see the descrip‐
+ tion of ‘.OBJDIR’ for more details.
FILES
.depend list of dependencies
@@ -1560,46 +1573,46 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
The way that .for loop variables are substituted changed after NetBSD 5.0
so that they still appear to be variable expansions. In particular this
- stops them being treated as syntax, and removes some obscure problems us-
+ stops them being treated as syntax, and removes some obscure problems us‐
ing them in .if statements.
The way that parallel makes are scheduled changed in NetBSD 4.0 so that
- .ORDER and .WAIT apply recursively to the dependent nodes. The algo-
+ .ORDER and .WAIT apply recursively to the dependent nodes. The algo‐
rithms used may change again in the future.
Other make dialects
- Other make dialects (GNU make, SVR4 make, POSIX make, etc.) do not sup-
- port most of the features of bmake as described in this manual. Most no-
+ Other make dialects (GNU make, SVR4 make, POSIX make, etc.) do not sup‐
+ port most of the features of bmake as described in this manual. Most no‐
tably:
- +o The .WAIT and .ORDER declarations and most functionality per-
+ • The .WAIT and .ORDER declarations and most functionality per‐
taining to parallelization. (GNU make supports parallelization
but lacks these features needed to control it effectively.)
- +o Directives, including for loops and conditionals and most of
+ • Directives, including for loops and conditionals and most of
the forms of include files. (GNU make has its own incompatible
and less powerful syntax for conditionals.)
- +o All built-in variables that begin with a dot.
+ • All built-in variables that begin with a dot.
- +o Most of the special sources and targets that begin with a dot,
+ • Most of the special sources and targets that begin with a dot,
with the notable exception of .PHONY, .PRECIOUS, and .SUFFIXES.
- +o Variable modifiers, except for the
+ • Variable modifiers, except for the
:old=new
string substitution, which does not portably support globbing
- with `%' and historically only works on declared suffixes.
+ with ‘%’ and historically only works on declared suffixes.
- +o The $> variable even in its short form; most makes support this
+ • The $> variable even in its short form; most makes support this
functionality but its name varies.
Some features are somewhat more portable, such as assignment with +=, ?=,
and !=. The .PATH functionality is based on an older feature VPATH found
- in GNU make and many versions of SVR4 make; however, historically its be-
+ in GNU make and many versions of SVR4 make; however, historically its be‐
havior is too ill-defined (and too buggy) to rely upon.
The $@ and $< variables are more or less universally portable, as is the
- $(MAKE) variable. Basic use of suffix rules (for files only in the cur-
+ $(MAKE) variable. Basic use of suffix rules (for files only in the cur‐
rent directory, not trying to chain transformations together, etc.) is
also reasonably portable.
@@ -1613,11 +1626,11 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
A make command appeared in Version 7 AT&T UNIX. This make implementation
is based on Adam De Boor's pmake program which was written for Sprite at
Berkeley. It was designed to be a parallel distributed make running jobs
- on different machines using a daemon called "customs".
+ on different machines using a daemon called “customs”.
- Historically the target/dependency "FRC" has been used to FoRCe rebuild-
+ Historically the target/dependency “FRC” has been used to FoRCe rebuild‐
ing (since the target/dependency does not exist... unless someone creates
- an "FRC" file).
+ an “FRC” file).
BUGS
The make syntax is difficult to parse without actually acting on the
@@ -1628,4 +1641,4 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
There is no way of escaping a space character in a filename.
-FreeBSD 13.0 April 18, 2022 FreeBSD 13.0
+FreeBSD 13.0 July 12, 2022 FreeBSD 13.0
diff --git a/compat.c b/compat.c
index ad280206157a..b1996b91af6d 100644
--- a/compat.c
+++ b/compat.c
@@ -1,4 +1,4 @@
-/* $NetBSD: compat.c,v 1.238 2022/01/22 18:59:23 rillig Exp $ */
+/* $NetBSD: compat.c,v 1.240 2022/05/07 17:49:47 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -70,16 +70,11 @@
*/
/*
- * compat.c --
- * The routines in this file implement the full-compatibility
- * mode of PMake. Most of the special functionality of PMake
- * is available in this mode. Things not supported:
- * - different shells.
- * - friendly variable substitution.
+ * This file implements the full-compatibility mode of make, which makes the
+ * targets without parallelism and without a custom shell.
*
* Interface:
- * Compat_Run Initialize things for this module and recreate
- * thems as need creatin'
+ * Compat_MakeAll Initialize this module and make the given targets.
*/
#ifdef HAVE_CONFIG_H
@@ -99,7 +94,7 @@
#include "pathnames.h"
/* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: compat.c,v 1.238 2022/01/22 18:59:23 rillig Exp $");
+MAKE_RCSID("$NetBSD: compat.c,v 1.240 2022/05/07 17:49:47 rillig Exp $");
static GNode *curTarg = NULL;
static pid_t compatChild;
@@ -467,13 +462,65 @@ RunCommands(GNode *gn)
}
static void
+MakeInRandomOrder(GNode **gnodes, GNode **end, GNode *pgn)
+{
+ GNode **it;
+ size_t r;
+
+ for (r = (size_t)(end - gnodes); r >= 2; r--) {
+ /* Biased, but irrelevant in practice. */
+ size_t i = (size_t)random() % r;
+ GNode *t = gnodes[r - 1];
+ gnodes[r - 1] = gnodes[i];
+ gnodes[i] = t;
+ }
+
+ for (it = gnodes; it != end; it++)
+ Compat_Make(*it, pgn);
+}
+
+static void
+MakeWaitGroupsInRandomOrder(GNodeList *gnodes, GNode *pgn)
+{
+ Vector vec;
+ GNodeListNode *ln;
+ GNode **nodes;
+ size_t i, n, start;
+
+ Vector_Init(&vec, sizeof(GNode *));
+ for (ln = gnodes->first; ln != NULL; ln = ln->next)
+ *(GNode **)Vector_Push(&vec) = ln->datum;
+ nodes = vec.items;
+ n = vec.len;
+
+ start = 0;
+ for (i = 0; i < n; i++) {
+ if (nodes[i]->type & OP_WAIT) {
+ MakeInRandomOrder(nodes + start, nodes + i, pgn);
+ Compat_Make(nodes[i], pgn);
+ start = i + 1;
+ }
+ }
+ MakeInRandomOrder(nodes + start, nodes + i, pgn);
+
+ Vector_Done(&vec);
+}
+
+static void
MakeNodes(GNodeList *gnodes, GNode *pgn)
{
GNodeListNode *ln;
+ if (Lst_IsEmpty(gnodes))
+ return;
+ if (opts.randomizeTargets) {
+ MakeWaitGroupsInRandomOrder(gnodes, pgn);
+ return;
+ }
+
for (ln = gnodes->first; ln != NULL; ln = ln->next) {
- GNode *cohort = ln->datum;
- Compat_Make(cohort, pgn);
+ GNode *cgn = ln->datum;
+ Compat_Make(cgn, pgn);
}
}
@@ -692,14 +739,8 @@ InitSignals(void)
bmake_signal(SIGQUIT, CompatInterrupt);
}
-/*
- * Initialize this module and start making.
- *
- * Input:
- * targs The target nodes to re-create
- */
void
-Compat_Run(GNodeList *targs)
+Compat_MakeAll(GNodeList *targs)
{
GNode *errorNode = NULL;
diff --git a/dir.c b/dir.c
index 93479271c94a..3ceca51f5800 100644
--- a/dir.c
+++ b/dir.c
@@ -1,4 +1,4 @@
-/* $NetBSD: dir.c,v 1.278 2022/02/04 23:22:19 rillig Exp $ */
+/* $NetBSD: dir.c,v 1.279 2022/05/07 21:19:43 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -138,7 +138,7 @@
#include "job.h"
/* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */
-MAKE_RCSID("$NetBSD: dir.c,v 1.278 2022/02/04 23:22:19 rillig Exp $");
+MAKE_RCSID("$NetBSD: dir.c,v 1.279 2022/05/07 21:19:43 rillig Exp $");
/*
* A search path is a list of CachedDir structures. A CachedDir has in it the
@@ -1035,7 +1035,7 @@ DirLookupAbs(CachedDir *dir, const char *name, const char *cp)
}
/*
- * Find the file given on "." or curdir.
+ * Find the given file in "." or curdir.
* Return the freshly allocated path to the file, or NULL.
*/
static char *
diff --git a/for.c b/for.c
index c36641fa8c4e..65cb612fdc5b 100644
--- a/for.c
+++ b/for.c
@@ -1,4 +1,4 @@
-/* $NetBSD: for.c,v 1.167 2022/02/04 23:22:19 rillig Exp $ */
+/* $NetBSD: for.c,v 1.168 2022/06/12 16:09:21 rillig Exp $ */
/*
* Copyright (c) 1992, The Regents of the University of California.
@@ -58,7 +58,7 @@
#include "make.h"
/* "@(#)for.c 8.1 (Berkeley) 6/6/93" */
-MAKE_RCSID("$NetBSD: for.c,v 1.167 2022/02/04 23:22:19 rillig Exp $");
+MAKE_RCSID("$NetBSD: for.c,v 1.168 2022/06/12 16:09:21 rillig Exp $");
typedef struct ForLoop {
@@ -269,7 +269,14 @@ For_Accum(const char *line, int *forLevel)
return true;
}
-
+/*
+ * When the body of a '.for i' loop is prepared for an iteration, each
+ * occurrence of $i in the body is replaced with ${:U...}, inserting the
+ * value of the item. If this item contains a '$', it may be the start of a
+ * variable expression. This expression is copied verbatim, its length is
+ * determined here, in a rather naive way, ignoring escape characters and
+ * funny delimiters in modifiers like ':S}from}to}'.
+ */
static size_t
ExprLen(const char *s, const char *e)
{
diff --git a/job.c b/job.c
index 8630d4217403..6c31e6bcf98b 100644
--- a/job.c
+++ b/job.c
@@ -1,4 +1,4 @@
-/* $NetBSD: job.c,v 1.452 2022/02/12 11:14:48 rillig Exp $ */
+/* $NetBSD: job.c,v 1.453 2022/05/07 08:01:20 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -155,7 +155,7 @@
#include "trace.h"
/* "@(#)job.c 8.2 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: job.c,v 1.452 2022/02/12 11:14:48 rillig Exp $");
+MAKE_RCSID("$NetBSD: job.c,v 1.453 2022/05/07 08:01:20 rillig Exp $");
/*
* A shell defines how the commands are run. All commands for a target are
@@ -2323,7 +2323,7 @@ Job_Init(void)
(void)Job_RunTarget(".BEGIN", NULL);
/*
* Create the .END node now, even though no code in the unit tests
- * depends on it. See also Targ_GetEndNode in Compat_Run.
+ * depends on it. See also Targ_GetEndNode in Compat_MakeAll.
*/
(void)Targ_GetEndNode();
}
diff --git a/main.c b/main.c
index 04ac7589027f..b6401ee39959 100644
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.580 2022/04/18 15:06:27 rillig Exp $ */
+/* $NetBSD: main.c,v 1.582 2022/05/07 17:49:47 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.580 2022/04/18 15:06:27 rillig Exp $");
+MAKE_RCSID("$NetBSD: main.c,v 1.582 2022/05/07 17:49:47 rillig Exp $");
#if defined(MAKE_NATIVE) && !defined(lint)
__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
"The Regents of the University of California. "
@@ -817,6 +817,8 @@ MakeMode(void)
if (strstr(mode, "meta") != NULL)
meta_mode_init(mode);
#endif
+ if (strstr(mode, "randomize-targets") != NULL)
+ opts.randomizeTargets = true;
}
free(mode);
@@ -921,11 +923,7 @@ runTargets(void)
/* Traverse the graph, checking on all the targets */
outOfDate = Make_Run(&targs);
} else {
- /*
- * Compat_Init will take care of creating all the
- * targets as well as initializing the module.
- */
- Compat_Run(&targs);
+ Compat_MakeAll(&targs);
outOfDate = false;
}
Lst_Done(&targs); /* Don't free the targets themselves. */
diff --git a/make.1 b/make.1
index 7c44356eefc7..c64bd09c2972 100644
--- a/make.1
+++ b/make.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: make.1,v 1.308 2022/04/18 15:06:27 rillig Exp $
+.\" $NetBSD: make.1,v 1.315 2022/07/12 23:47:00 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 April 18, 2022
+.Dd July 12, 2022
.Dt MAKE 1
.Os
.Sh NAME
@@ -61,12 +61,12 @@ If no
makefile option is given,
.Nm
will try to open
-.Ql Pa makefile
+.Sq Pa makefile
then
-.Ql Pa Makefile
+.Sq Pa Makefile
in order to find the specifications.
If the file
-.Ql Pa .depend
+.Sq Pa .depend
exists, it is read (see
.Xr mkdep 1 ) .
.Pp
@@ -229,11 +229,11 @@ Specify that environment variables override macro assignments within
makefiles.
.It Fl f Ar makefile
Specify a makefile to read instead of the default
-.Ql Pa makefile .
+.Sq Pa makefile .
If
.Ar makefile
is
-.Ql Fl ,
+.Sq Fl ,
standard input is read.
Multiple makefiles may be specified, and are read in the order specified.
.It Fl I Ar directory
@@ -244,7 +244,7 @@ option) is automatically included as part of this list.
.It Fl i
Ignore non-zero exit of shell commands in the makefile.
Equivalent to specifying
-.Ql Fl
+.Sq Fl
before each command line in the makefile.
.It Fl J Ar private
This option should
@@ -252,7 +252,7 @@ This option should
be specified by the user.
.Pp
When the
-.Ar j
+.Fl j
option is in use in a recursive build, this option is passed by a make
to child makes to allow all the make processes in the build to
cooperate to avoid overloading the system.
@@ -263,8 +263,8 @@ may have running at any one time.
The value is saved in
.Va .MAKE.JOBS .
Turns compatibility mode off, unless the
-.Ar B
-flag is also specified.
+.Fl B
+option is also specified.
When compatibility mode is off, all commands associated with a
target are executed in a single shell invocation as opposed to the
traditional one shell invocation per line.
@@ -319,7 +319,7 @@ as an argument).
Display the commands that would have been executed, but do not
actually execute them unless the target depends on the .MAKE special
source (see below) or the command is prefixed with
-.Ql Ic + .
+.Sq Ic + .
.It Fl N
Display the commands which would have been executed, but do not
actually execute any of them; useful for debugging top-level makefiles
@@ -336,7 +336,7 @@ This is the default behavior and the opposite of
.It Fl s
Do not echo any commands as they are executed.
Equivalent to specifying
-.Ql Ic @
+.Sq Ic @
before each command line in the makefile.
.It Fl T Ar tracefile
When used with the
@@ -493,7 +493,7 @@ While targets can appear in many dependency lines if desired, by
default only one of these rules may be followed by a creation
script.
If the
-.Ql Ic \&::
+.Sq Ic \&::
operator is used, however, all rules may include scripts and the
scripts are executed in the order found.
.Pp
@@ -505,23 +505,23 @@ in which case that line and the next are combined.
.\" normally ignores it.
.\" However, the tab at the beginning of the following line is removed.
If the first characters of the command are any combination of
-.Ql Ic @ ,
-.Ql Ic + ,
+.Sq Ic @ ,
+.Sq Ic + ,
or
-.Ql Ic \- ,
+.Sq Ic \- ,
the command is treated specially.
A
-.Ql Ic @
+.Sq Ic @
causes the command not to be echoed before it is executed.
A
-.Ql Ic +
+.Sq Ic +
causes the command to be executed even when
.Fl n
is given.
This is similar to the effect of the .MAKE special source,
except that the effect can be limited to a single line of a script.
A
-.Ql Ic \-
+.Sq Ic \-
in compatibility mode
causes any non-zero exit status of the command line to be ignored.
.Pp
@@ -538,11 +538,11 @@ it will be passed to the shell; otherwise
.Nm
will attempt direct execution.
If a line starts with
-.Ql Ic \-
+.Sq Ic \-
and the shell has ErrCtl enabled then failure of the command line
will be ignored as in compatibility mode.
Otherwise
-.Ql Ic \-
+.Sq Ic \-
affects the entire job;
the script will stop at the first command line that fails,
but the target will not be deemed to have failed.
@@ -576,27 +576,47 @@ Since
will
.Xr chdir 2
to
-.Ql Va .OBJDIR
+.Sq Va .OBJDIR
before executing any targets, each child process
starts with that as its current working directory.
.Sh VARIABLE ASSIGNMENTS
-Variables in make are much like variables in the shell, and, by tradition,
-consist of all upper-case letters.
-.Ss Variable assignment modifiers
-The five operators that can be used to assign values to variables are as
-follows:
+Variables in make behave much like macros in the C preprocessor.
+.Pp
+Variable assignments have the form
+.Sq Ar NAME Ar op Ar value ,
+where:
+.Bl -tag -width Ds
+.It Ar NAME
+is a single-word variable name,
+consisting, by tradition, of all upper-case letters,
+.It Ar op
+is one of the five variable assignment operators described below, and
+.It Ar value
+is interpreted according to the variable assignment operator.
+.El
+.Pp
+Whitespace around
+.Ar NAME ,
+.Ar op
+and
+.Ar value
+is discarded.
+.Ss Variable assignment operators
+The five operators that can be used to assign values to variables are:
.Bl -tag -width Ds
.It Ic \&=
Assign the value to the variable.
-Any previous value is overridden.
+Any previous value is overwritten.
.It Ic \&+=
-Append the value to the current value of the variable.
+Append the value to the current value of the variable,
+separating them by a single space.
.It Ic \&?=
Assign the value to the variable if it is not already defined.
.It Ic \&:=
Assign with expansion, i.e. expand the value before assigning it
to the variable.
Normally, expansion is not done until the variable is referenced.
+.Pp
.Em NOTE :
References to undefined variables are
.Em not
@@ -607,45 +627,42 @@ Expand the value and pass it to the shell for execution and assign
the result to the variable.
Any newlines in the result are replaced with spaces.
.El
-.Pp
-Any white-space before the assigned
-.Ar value
-is removed; if the value is being appended, a single space is inserted
-between the previous contents of the variable and the appended value.
-.Pp
-Variables are expanded by surrounding the variable name with either
-curly braces
-.Pq Ql {}
-or parentheses
-.Pq Ql ()
-and preceding it with
-a dollar sign
-.Pq Ql \&$ .
-If the variable name contains only a single letter, the surrounding
-braces or parentheses are not required.
+.Ss Expansion of variables
+In contexts where variables are expanded,
+.Ql \&$$
+expands to a single dollar sign.
+References to variables have the form
+.Ql \&${ Ns Ar name Ns Oo \&: Ns Ar modifiers Oc Ns }
+or
+.Ql \&$( Ns Ar name Ns Oo \&: Ns Ar modifiers Oc Ns ) .
+If the variable name contains only a single character,
+the surrounding curly braces or parentheses are not required.
This shorter form is not recommended.
.Pp
If the variable name contains a dollar, then the name itself is expanded first.
This allows almost arbitrary variable names, however names containing dollar,
-braces, parentheses, or whitespace are really best avoided!
+braces, parentheses, or whitespace are really best avoided.
.Pp
If the result of expanding a variable contains a dollar sign
-.Pq Ql \&$
+.Pq Ql \&$ ,
the string is expanded again.
.Pp
-Variable substitution occurs at three distinct times, depending on where
+Variable substitution occurs at four distinct times, depending on where
the variable is being used.
.Bl -enum
.It
Variables in dependency lines are expanded as the line is read.
.It
+Variables in conditionals are expanded individually,
+but only as far as necessary to determine the result of the conditional.
+.It
Variables in shell commands are expanded when the shell command is
executed.
.It
.Dq .for
loop index variables are expanded on each loop iteration.
-Note that other variables are not expanded inside loops so
-the following example code:
+Note that other variables are not expanded when composing the body of a loop,
+so the following example code:
.Bd -literal -offset indent
.Dv .for i in 1 2 3
@@ -726,34 +743,34 @@ The seven built-in local variables are as follows:
.Bl -tag -width ".ARCHIVE" -offset indent
.It Va .ALLSRC
The list of all sources for this target; also known as
-.Ql Va \&> .
+.Sq Va \&> .
.It Va .ARCHIVE
The name of the archive file; also known as
-.Ql Va \&! .
+.Sq Va \&! .
.It Va .IMPSRC
In suffix-transformation rules, the name/path of the source from which the
target is to be transformed (the
.Dq implied
source); also known as
-.Ql Va \&< .
+.Sq Va \&< .
It is not defined in explicit rules.
.It Va .MEMBER
The name of the archive member; also known as
-.Ql Va % .
+.Sq Va % .
.It Va .OODATE
The list of sources for this target that were deemed out-of-date; also
known as
-.Ql Va \&? .
+.Sq Va \&? .
.It Va .PREFIX
The file prefix of the target, containing only the file portion, no suffix
or preceding directory components; also known as
-.Ql Va * .
+.Sq Va * .
The suffix must be one of the known suffixes declared with
.Ic .SUFFIXES
or it will not be recognized.
.It Va .TARGET
The name of the target; also known as
-.Ql Va @ .
+.Sq Va @ .
For compatibility with other makes this is an alias for
.Ic .ARCHIVE
in archive member rules.
@@ -761,13 +778,13 @@ in archive member rules.
.Pp
The shorter forms
.Ql ( Va > ,
-.Ql Va \&! ,
-.Ql Va < ,
-.Ql Va % ,
-.Ql Va \&? ,
-.Ql Va * ,
+.Sq Va \&! ,
+.Sq Va < ,
+.Sq Va % ,
+.Sq Va \&? ,
+.Sq Va * ,
and
-.Ql Va @ )
+.Sq Va @ )
are permitted for backward
compatibility with historical makefiles and legacy POSIX make and are
not recommended.
@@ -776,8 +793,8 @@ Variants of these variables with the punctuation followed immediately by
.Ql D
or
.Ql F ,
-e.g.
-.Ql Va $(@D) ,
+e.g.\&
+.Sq Va $(@D) ,
are legacy forms equivalent to using the
.Ql :H
and
@@ -790,23 +807,16 @@ makefiles and POSIX but are not recommended.
Four of the local variables may be used in sources on dependency lines
because they expand to the proper value for each target on the line.
These variables are
-.Ql Va .TARGET ,
-.Ql Va .PREFIX ,
-.Ql Va .ARCHIVE ,
+.Sq Va .TARGET ,
+.Sq Va .PREFIX ,
+.Sq Va .ARCHIVE ,
and
-.Ql Va .MEMBER .
+.Sq Va .MEMBER .
.Ss Additional built-in variables
In addition,
.Nm
sets or knows about the following variables:
.Bl -tag -width .MAKEOVERRIDES
-.It Va \&$
-A single dollar sign
-.Ql \&$ ,
-i.e.
-.Ql \&$$
-expands to a single dollar
-sign.
.It Va .ALLTARGETS
The list of all targets encountered in the Makefile.
If evaluated during
@@ -816,7 +826,7 @@ A path to the directory where
.Nm
was executed.
Refer to the description of
-.Ql Ev PWD
+.Sq Ev PWD
for more details.
.It Va .INCLUDEDFROMDIR
The directory of the file this Makefile was included from.
@@ -839,7 +849,7 @@ because it is more compatible with other versions of
and cannot be confused with the special target with the same name.
.It Va .MAKE.DEPENDFILE
Names the makefile (default
-.Ql Pa .depend )
+.Sq Pa .depend )
from which generated dependencies are read.
.It Va .MAKE.EXPAND_VARIABLES
A boolean that controls the default behavior of the
@@ -860,17 +870,18 @@ option.
If
.Nm
is run with
-.Ar j
-then output for each target is prefixed with a token
+.Fl j ,
+the output for each target is prefixed with a token
.Ql --- target ---
the first part of which can be controlled via
.Va .MAKE.JOB.PREFIX .
If
.Va .MAKE.JOB.PREFIX
is empty, no token is printed.
-.br
-For example:
-.Li .MAKE.JOB.PREFIX=${.newline}---${.MAKE:T}[${.MAKE.PID}]
+For example, setting
+.Va .MAKE.JOB.PREFIX
+to
+.Li ${.newline}---${.MAKE:T}[${.MAKE.PID}]
would produce tokens like
.Ql ---make[1234] target ---
making it easier to track the degree of parallelism being achieved.
@@ -881,7 +892,7 @@ apparent variable assignments in dependency lines are
treated as normal sources.
.It Ev MAKEFLAGS
The environment variable
-.Ql Ev MAKEFLAGS
+.Sq Ev MAKEFLAGS
may contain anything that
may be specified on
.Nm Ns 's
@@ -889,7 +900,7 @@ command line.
Anything specified on
.Nm Ns 's
command line is appended to the
-.Ql Ev MAKEFLAGS
+.Sq Ev MAKEFLAGS
variable which is then
entered into the environment for all programs which
.Nm
@@ -908,8 +919,8 @@ to protect things which should only be evaluated in the initial instance of
.It Va .MAKE.MAKEFILE_PREFERENCE
The ordered list of makefile names
(default
-.Ql Pa makefile ,
-.Ql Pa Makefile )
+.Sq Pa makefile ,
+.Sq Pa Makefile )
that
.Nm
will look for.
@@ -944,7 +955,7 @@ The captured output can be very useful when diagnosing errors.
Normally
.Nm
will not create .meta files in
-.Ql Va .CURDIR .
+.Sq Va .CURDIR .
This can be overridden by setting
.Va bf
to a value which represents True.
@@ -978,6 +989,10 @@ If
.Va bf
is True, when a .meta file is created, mark the target
.Ic .SILENT .
+.It Pa randomize-targets
+In both compat and parallel mode, do not make the targets in the usual order,
+but instead randomize their order.
+This mode can be used to detect undeclared dependencies between files.
.El
.It Va .MAKE.META.BAILIWICK
In "meta" mode, provides a list of prefixes which
@@ -1007,7 +1022,7 @@ information.
Provides a list of path prefixes that should be ignored;
because the contents are expected to change over time.
The default list includes:
-.Ql Pa /dev /etc /proc /tmp /var/run /var/tmp
+.Sq Pa /dev /etc /proc /tmp /var/run /var/tmp
.It Va .MAKE.META.IGNORE_PATTERNS
Provides a list of patterns to match against pathnames.
Ignore any that match.
@@ -1021,16 +1036,16 @@ The default value is:
.It Va .MAKEOVERRIDES
This variable is used to record the names of variables assigned to
on the command line, so that they may be exported as part of
-.Ql Ev MAKEFLAGS .
+.Sq Ev MAKEFLAGS .
This behavior can be disabled by assigning an empty value to
-.Ql Va .MAKEOVERRIDES
+.Sq Va .MAKEOVERRIDES
within a makefile.
Extra variables can be exported from a makefile
by appending their names to
-.Ql Va .MAKEOVERRIDES .
-.Ql Ev MAKEFLAGS
+.Sq Va .MAKEOVERRIDES .
+.Sq Ev MAKEFLAGS
is re-exported whenever
-.Ql Va .MAKEOVERRIDES
+.Sq Va .MAKEOVERRIDES
is modified.
.It Va .MAKE.PATH_FILEMON
If
@@ -1068,21 +1083,21 @@ The group-id running
When
.Nm
stops due to an error, it sets
-.Ql Va .ERROR_TARGET
+.Sq Va .ERROR_TARGET
to the name of the target that failed,
-.Ql Va .ERROR_CMD
+.Sq Va .ERROR_CMD
to the commands of the failed target,
and in "meta" mode, it also sets
-.Ql Va .ERROR_CWD
+.Sq Va .ERROR_CWD
to the
.Xr getcwd 3 ,
and
-.Ql Va .ERROR_META_FILE
+.Sq Va .ERROR_META_FILE
to the path of the meta file (if any) describing the failed target.
It then prints its name and the value of
-.Ql Va .CURDIR
+.Sq Va .CURDIR
as well as the value of any variables named in
-.Ql Va MAKE_PRINT_VAR_ON_ERROR .
+.Sq Va MAKE_PRINT_VAR_ON_ERROR .
.It Va .newline
This variable is simply assigned a newline character as its value.
This allows expansions using the
@@ -1090,7 +1105,7 @@ This allows expansions using the
modifier to put a newline between
iterations of the loop rather than a space.
For example, the printing of
-.Ql Va MAKE_PRINT_VAR_ON_ERROR
+.Sq Va MAKE_PRINT_VAR_ON_ERROR
could be done as ${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@}.
.It Va .OBJDIR
A path to the directory where the targets are built.
@@ -1102,13 +1117,13 @@ to the following directories in order and using the first match:
.Ev ${MAKEOBJDIRPREFIX}${.CURDIR}
.Pp
(Only if
-.Ql Ev MAKEOBJDIRPREFIX
+.Sq Ev MAKEOBJDIRPREFIX
is set in the environment or on the command line.)
.It
.Ev ${MAKEOBJDIR}
.Pp
(Only if
-.Ql Ev MAKEOBJDIR
+.Sq Ev MAKEOBJDIR
is set in the environment or on the command line.)
.It
.Ev ${.CURDIR} Ns Pa /obj. Ns Ev ${MACHINE}
@@ -1125,77 +1140,77 @@ so expressions such as
.Dl ${.CURDIR:S,^/usr/src,/var/obj,}
may be used.
This is especially useful with
-.Ql Ev MAKEOBJDIR .
+.Sq Ev MAKEOBJDIR .
.Pp
-.Ql Va .OBJDIR
+.Sq Va .OBJDIR
may be modified in the makefile via the special target
-.Ql Ic .OBJDIR .
+.Sq Ic .OBJDIR .
In all cases,
.Nm
will
.Xr chdir 2
to the specified directory if it exists, and set
-.Ql Va .OBJDIR
+.Sq Va .OBJDIR
and
-.Ql Ev PWD
+.Sq Ev PWD
to that directory before executing any targets.
.Pp
Except in the case of an explicit
-.Ql Ic .OBJDIR
+.Sq Ic .OBJDIR
target,
.Nm
will check that the specified directory is writable and ignore it if not.
This check can be skipped by setting the environment variable
-.Ql Ev MAKE_OBJDIR_CHECK_WRITABLE
+.Sq Ev MAKE_OBJDIR_CHECK_WRITABLE
to "no".
.
.It Va .PARSEDIR
A path to the directory of the current
-.Ql Pa Makefile
+.Sq Pa Makefile
being parsed.
.It Va .PARSEFILE
The basename of the current
-.Ql Pa Makefile
+.Sq Pa Makefile
being parsed.
This variable and
-.Ql Va .PARSEDIR
+.Sq Va .PARSEDIR
are both set only while the
-.Ql Pa Makefiles
+.Sq Pa Makefiles
are being parsed.
If you want to retain their current values, assign them to a variable
-using assignment with expansion:
-.Pq Ql Cm \&:= .
+using assignment with expansion
+.Sq Cm \&:= .
.It Va .PATH
A variable that represents the list of directories that
.Nm
will search for files.
The search list should be updated using the target
-.Ql Va .PATH
+.Sq Va .PATH
rather than the variable.
.It Ev PWD
Alternate path to the current directory.
.Nm
normally sets
-.Ql Va .CURDIR
+.Sq Va .CURDIR
to the canonical path given by
.Xr getcwd 3 .
However, if the environment variable
-.Ql Ev PWD
+.Sq Ev PWD
is set and gives a path to the current directory, then
.Nm
sets
-.Ql Va .CURDIR
+.Sq Va .CURDIR
to the value of
-.Ql Ev PWD
+.Sq Ev PWD
instead.
This behavior is disabled if
-.Ql Ev MAKEOBJDIRPREFIX
+.Sq Ev MAKEOBJDIRPREFIX
is set or
-.Ql Ev MAKEOBJDIR
+.Sq Ev MAKEOBJDIR
contains a variable transform.
-.Ql Ev PWD
+.Sq Ev PWD
is set to the value of
-.Ql Va .OBJDIR
+.Sq Va .OBJDIR
for all programs which
.Nm
executes.
@@ -1215,7 +1230,7 @@ lists of directories that
will search for files.
The variable is supported for compatibility with old make programs only,
use
-.Ql Va .PATH
+.Sq Va .PATH
instead.
.El
.Ss Variable modifiers
@@ -1249,14 +1264,14 @@ The supported modifiers are:
Replaces each word in the variable with its suffix.
.It Cm \&:H
Replaces each word in the variable with everything but the last component.
-.It Cm \&:M Ns Ar pattern
+.It Cm \&:M\| Ns Ar pattern
Selects only those words that match
.Ar pattern .
The standard shell wildcard characters
.Pf ( Ql * ,
.Ql \&? ,
and
-.Ql Oo Oc )
+.Ql \&[] )
may
be used.
The wildcard characters may be escaped with a backslash
@@ -1268,9 +1283,9 @@ will normalize the inter-word spacing, removing all leading and
trailing space, and converting multiple consecutive spaces
to single spaces.
.
-.It Cm \&:N Ns Ar pattern
+.It Cm \&:N\| Ns Ar pattern
This is identical to
-.Ql Cm \&:M ,
+.Sq Cm \&:M ,
but selects all words which do not match
.Ar pattern .
.It Cm \&:O
@@ -1293,7 +1308,7 @@ Orders every word in variable in reverse numerical order.
Shuffles the words in variable.
The results will be different each time you are referring to the
modified variable; use the assignment with expansion
-.Pq Ql Cm \&:=
+.Sq Cm \&:=
to prevent such behavior.
For example,
.Bd -literal -offset indent
@@ -1327,11 +1342,11 @@ This is equivalent to:
.Sq \&:S/\e\&$/&&/g:Q .
.It Cm \&:R
Replaces each word in the variable with everything but its suffix.
-.It Cm \&:range[=count]
+.It Cm \&:range Ns Oo = Ns Ar count Oc
The value is an integer sequence representing the words of the original
value, or the supplied
.Va count .
-.It Cm \&:gmtime[=utc]
+.It Cm \&:gmtime Ns Oo = Ns Ar utc Oc
The value is a format string for
.Xr strftime 3 ,
using
@@ -1341,7 +1356,7 @@ If a
value is not provided or is 0, the current time is used.
.It Cm \&:hash
Computes a 32-bit hash of the value and encode it as hex digits.
-.It Cm \&:localtime[=utc]
+.It Cm \&:localtime Ns Oo = Ns Ar utc Oc
The value is a format string for
.Xr strftime 3 ,
using
@@ -1369,14 +1384,14 @@ Converts variable to upper-case letters.
Causes the value to be treated as a single word
(possibly containing embedded white space).
See also
-.Ql Cm \&:[*] .
+.Sq Cm \&:[*] .
.It Cm \&:tw
Causes the value to be treated as a sequence of
words delimited by white space.
See also
-.Ql Cm \&:[@] .
+.Sq Cm \&:[@] .
.Sm off
-.It Cm \&:S No \&/ Ar old_string No \&/ Ar new_string No \&/ Op Cm 1gW
+.It Cm \&:S\| No \&/ Ar old_string\| No \&/ Ar new_string\| No \&/ Op Cm 1gW
.Sm on
Modifies the first occurrence of
.Ar old_string
@@ -1431,7 +1446,7 @@ of a dollar sign
.Pq Ql \&$ ,
not a preceding dollar sign as is usual.
.Sm off
-.It Cm \&:C No \&/ Ar pattern No \&/ Ar replacement No \&/ Op Cm 1gW
+.It Cm \&:C\| No \&/ Ar pattern\| No \&/ Ar replacement\| No \&/ Op Cm 1gW
.Sm on
The
.Cm \&:C
@@ -1476,7 +1491,7 @@ Replaces each word in the variable with its last path component.
Removes adjacent duplicate words (like
.Xr uniq 1 ) .
.Sm off
-.It Cm \&:\&? Ar true_string Cm \&: Ar false_string
+.It Cm \&:\&?\| Ar true_string\| Cm \&: Ar false_string
.Sm on
If the variable name (not its value), when parsed as a .if conditional
expression, evaluates to true, return as its value the
@@ -1491,7 +1506,7 @@ A common error is trying to use expressions like
which actually tests defined(NUMBERS),
to determine if any words match "42" you need to use something like:
.Dl ${"${NUMBERS:M42}" != \&"\&":?match:no} .
-.It Ar :old_string=new_string
+.It Cm :\| Ns Ar old_string\| Ns Cm = Ns Ar new_string
This is the
.At V
style variable substitution.
@@ -1544,7 +1559,7 @@ expansion of a dollar sign
.Pq Ql \&$ ,
not a preceding dollar sign as is usual.
.Sm off
-.It Cm \&:@ Ar temp Cm @ Ar string Cm @
+.It Cm \&:@ Ar temp\| Cm @ Ar string\| Cm @
.Sm on
This is the loop expansion mechanism from the OSF Development
Environment (ODE) make.
@@ -1563,7 +1578,7 @@ For example.
.Pp
However a single character variable is often more readable:
.Dl ${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@}
-.It Cm \&:_[=var]
+.It Cm \&:_ Ns Oo Cm = Ns Ar var Oc
Saves the current variable value in
.Ql $_
or the named
@@ -1584,7 +1599,7 @@ is used to save the result of the
.Ql :S
modifier which is later referenced using the index values from
.Ql :range .
-.It Cm \&:U Ns Ar newval
+.It Cm \&:U\| Ns Ar newval
If the variable is undefined,
.Ar newval
is the value.
@@ -1594,7 +1609,7 @@ It is handy for setting per-target CFLAGS for instance:
.Dl ${_${.TARGET:T}_CFLAGS:U${DEF_CFLAGS}}
If a value is only required if the variable is undefined, use:
.Dl ${VAR:D:Unewval}
-.It Cm \&:D Ns Ar newval
+.It Cm \&:D\| Ns Ar newval
If the variable is defined,
.Ar newval
is the value.
@@ -1608,7 +1623,7 @@ name of the variable is used.
In order for this modifier to work, the name (node) must at least have
appeared on the rhs of a dependency.
.Sm off
-.It Cm \&:\&! Ar cmd Cm \&!
+.It Cm \&:\&! Ar cmd\| Cm \&!
.Sm on
The output of running
.Ar cmd
@@ -1630,7 +1645,7 @@ preceded with something to keep
happy.
.Pp
The
-.Ql Cm \&::
+.Sq Cm \&::
helps avoid false matches with the
.At V
style
@@ -1663,7 +1678,7 @@ causing a value to be treated as a single word
An empty value, or a value that consists entirely of white-space,
is treated as a single word.
For the purposes of the
-.Ql Cm \&:[]
+.Sq Cm \&:[]
modifier, the words are indexed both forwards using positive integers
(where index 1 represents the first word),
and backwards using negative integers
@@ -1685,7 +1700,7 @@ to
.Ar end ,
inclusive.
For example,
-.Ql Cm \&:[2..-1]
+.Sq Cm \&:[2..-1]
selects all words from the second word to the last word.
If
.Ar start
@@ -1693,13 +1708,13 @@ is greater than
.Ar end ,
then the words are output in reverse order.
For example,
-.Ql Cm \&:[-1..1]
+.Sq Cm \&:[-1..1]
selects all the words from last to first.
If the list is already ordered, then this effectively reverses
the list, but it is more efficient to use
-.Ql Cm \&:Or
+.Sq Cm \&:Or
instead of
-.Ql Cm \&:O:[-1..1] .
+.Sq Cm \&:O:[-1..1] .
.\" :[*]
.It Cm \&*
Causes subsequent modifiers to treat the value as a single word
@@ -1710,7 +1725,7 @@ in Bourne shell.
.\" :[0]
.It 0
Means the same as
-.Ql Cm \&:[*] .
+.Sq Cm \&:[*] .
.\" :[*]
.It Cm \&@
Causes subsequent modifiers to treat the value as a sequence of words
@@ -1837,14 +1852,14 @@ PATH := ${PATH}
.Pp
.Ed
Would result in an environment containing only
-.Ql Ev PATH ,
+.Sq Ev PATH ,
which is the minimal useful environment.
Actually
-.Ql Ev .MAKE.LEVEL
+.Sq Ev .MAKE.LEVEL
will also be pushed into the new environment.
.It Ic .warning Ar message
The message prefixed by
-.Ql Pa warning:
+.Sq Pa warning:
is printed along with the name of the makefile and line number.
.It Ic \&.if Oo \&! Oc Ns Ar expression Op Ar operator expression ...
Test the value of an expression.
@@ -1860,29 +1875,29 @@ Test the target being built.
Reverse the sense of the last conditional.
.It Ic .elif Oo \&! Ns Oc Ar expression Op Ar operator expression ...
A combination of
-.Ql Ic .else
+.Sq Ic .else
followed by
-.Ql Ic .if .
+.Sq Ic .if .
.It Ic .elifdef Oo \&! Oc Ns Ar variable Op Ar operator variable ...
A combination of
-.Ql Ic .else
+.Sq Ic .else
followed by
-.Ql Ic .ifdef .
+.Sq Ic .ifdef .
.It Ic .elifndef Oo \&! Oc Ns Ar variable Op Ar operator variable ...
A combination of
-.Ql Ic .else
+.Sq Ic .else
followed by
-.Ql Ic .ifndef .
+.Sq Ic .ifndef .
.It Ic .elifmake Oo \&! Oc Ns Ar target Op Ar operator target ...
A combination of
-.Ql Ic .else
+.Sq Ic .else
followed by
-.Ql Ic .ifmake .
+.Sq Ic .ifmake .
.It Ic .elifnmake Oo \&! Oc Ns Ar target Op Ar operator target ...
A combination of
-.Ql Ic .else
+.Sq Ic .else
followed by
-.Ql Ic .ifnmake .
+.Sq Ic .ifnmake .
.It Ic .endif
End the body of the conditional.
.El
@@ -1906,11 +1921,11 @@ will only evaluate a conditional as far as is necessary to determine
its value.
Parentheses may be used to change the order of evaluation.
The boolean operator
-.Ql Ic \&!
+.Sq Ic \&!
may be used to logically negate an entire
conditional.
It is of higher precedence than
-.Ql Ic \&&& .
+.Sq Ic \&&& .
.Pp
The value of
.Ar expression
@@ -1952,9 +1967,9 @@ preceded by 0x, otherwise it is decimal; octal numbers are not supported.
The standard C relational operators are all supported.
If after
variable expansion, either the left or right hand side of a
-.Ql Ic ==
+.Sq Ic ==
or
-.Ql Ic "!="
+.Sq Ic "!="
operator is not a numerical value, then
string comparison is performed between the expanded
variables.
@@ -1971,17 +1986,17 @@ or
.Dq defined
expression is applied to it, depending on the form of the conditional.
If the form is
-.Ql Ic .ifdef ,
-.Ql Ic .ifndef ,
+.Sq Ic .ifdef ,
+.Sq Ic .ifndef ,
or
-.Ql Ic .if
+.Sq Ic .if
the
.Dq defined
expression is applied.
Similarly, if the form is
-.Ql Ic .ifmake
+.Sq Ic .ifmake
or
-.Ql Ic .ifnmake ,
+.Sq Ic .ifnmake ,
the
.Dq make
expression is applied.
@@ -1990,9 +2005,9 @@ If the conditional evaluates to true the parsing of the makefile continues
as before.
If it evaluates to false, the following lines are skipped.
In both cases this continues until a
-.Ql Ic .else
+.Sq Ic .else
or
-.Ql Ic .endif
+.Sq Ic .endif
is found.
.Pp
For loops are typically used to apply a set of rules to a list of files.
@@ -2243,16 +2258,17 @@ Synonym for
for compatibility with other pmake variants.
.It Ic .OBJDIR
The source is a new value for
-.Ql Va .OBJDIR .
+.Sq Va .OBJDIR .
If it exists,
.Nm
will
.Xr chdir 2
to it and update the value of
-.Ql Va .OBJDIR .
+.Sq Va .OBJDIR .
.It Ic .ORDER
-The named targets are made in sequence.
+In parallel mode, the named targets are made in sequence.
This ordering does not add targets to the list of targets to be made.
+.Pp
Since the dependents of a target do not get built until the target itself
could be built, unless
.Ql a
@@ -2263,9 +2279,6 @@ the following is a dependency loop:
b: a
.Ed
.Pp
-The ordering imposed by
-.Ic .ORDER
-is only relevant for parallel makes.
.\" XXX: NOT YET!!!!
.\" .It Ic .PARALLEL
.\" The named targets are executed in parallel mode.
@@ -2409,7 +2422,7 @@ may only be set in the environment or on the command line to
.Nm
and not as makefile variables;
see the description of
-.Ql Va .OBJDIR
+.Sq Va .OBJDIR
for more details.
.Sh FILES
.Bl -tag -width /usr/share/mk -compact
diff --git a/make.c b/make.c
index 5fb8f8840772..fa1e594a1b16 100644
--- a/make.c
+++ b/make.c
@@ -1,4 +1,4 @@
-/* $NetBSD: make.c,v 1.252 2022/01/09 15:48:30 rillig Exp $ */
+/* $NetBSD: make.c,v 1.255 2022/05/07 17:49:47 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -104,7 +104,7 @@
#include "job.h"
/* "@(#)make.c 8.1 (Berkeley) 6/6/93" */
-MAKE_RCSID("$NetBSD: make.c,v 1.252 2022/01/09 15:48:30 rillig Exp $");
+MAKE_RCSID("$NetBSD: make.c,v 1.255 2022/05/07 17:49:47 rillig Exp $");
/* Sequence # to detect recursion. */
static unsigned int checked_seqno = 1;
@@ -127,17 +127,6 @@ debug_printf(const char *fmt, ...)
va_end(ap);
}
-MAKE_ATTR_DEAD static void
-make_abort(GNode *gn, int lineno)
-{
-
- debug_printf("make_abort from line %d\n", lineno);
- Targ_PrintNode(gn, 2);
- Targ_PrintNodes(&toBeMade, 2);
- Targ_PrintGraph(3);
- abort();
-}
-
static const char *
GNodeType_ToString(GNodeType type, void **freeIt)
{
@@ -644,7 +633,7 @@ IsWaitingForOrder(GNode *gn)
return false;
}
-static void MakeBuildParent(GNode *, GNodeListNode *);
+static bool MakeBuildChild(GNode *, GNodeListNode *);
static void
ScheduleOrderSuccessors(GNode *gn)
@@ -652,8 +641,13 @@ ScheduleOrderSuccessors(GNode *gn)
GNodeListNode *toBeMadeNext = toBeMade.first;
GNodeListNode *ln;
- for (ln = gn->order_succ.first; ln != NULL; ln = ln->next)
- MakeBuildParent(ln->datum, toBeMadeNext);
+ for (ln = gn->order_succ.first; ln != NULL; ln = ln->next) {
+ GNode *succ = ln->datum;
+
+ if (succ->made == DEFERRED &&
+ !MakeBuildChild(succ, toBeMadeNext))
+ succ->flags.doneOrder = true;
+ }
}
/*
@@ -938,6 +932,28 @@ GNode_SetLocalVars(GNode *gn)
gn->flags.doneAllsrc = true;
}
+static void
+ScheduleRandomly(GNode *gn)
+{
+ GNodeListNode *ln;
+ size_t i, n;
+
+ n = 0;
+ for (ln = toBeMade.first; ln != NULL; ln = ln->next)
+ n++;
+ i = n > 0 ? (size_t)random() % (n + 1) : 0;
+
+ if (i == 0) {
+ Lst_Append(&toBeMade, gn);
+ return;
+ }
+ i--;
+
+ for (ln = toBeMade.first; i > 0; ln = ln->next)
+ i--;
+ Lst_InsertBefore(&toBeMade, ln, gn);
+}
+
static bool
MakeBuildChild(GNode *cn, GNodeListNode *toBeMadeNext)
{
@@ -963,7 +979,9 @@ MakeBuildChild(GNode *cn, GNodeListNode *toBeMadeNext)
cn->name, cn->cohort_num);
cn->made = REQUESTED;
- if (toBeMadeNext == NULL)
+ if (opts.randomizeTargets && !(cn->type & OP_WAIT))
+ ScheduleRandomly(cn);
+ else if (toBeMadeNext == NULL)
Lst_Append(&toBeMade, cn);
else
Lst_InsertBefore(&toBeMade, toBeMadeNext, cn);
@@ -983,19 +1001,6 @@ MakeBuildChild(GNode *cn, GNodeListNode *toBeMadeNext)
return cn->type & OP_WAIT && cn->unmade > 0;
}
-/* When a .ORDER LHS node completes, we do this on each RHS. */
-static void
-MakeBuildParent(GNode *pn, GNodeListNode *toBeMadeNext)
-{
- if (pn->made != DEFERRED)
- return;
-
- if (!MakeBuildChild(pn, toBeMadeNext)) {
- /* When this node is built, reschedule its parents. */
- pn->flags.doneOrder = true;
- }
-}
-
static void
MakeChildren(GNode *gn)
{
@@ -1033,13 +1038,12 @@ MakeStartJobs(void)
DEBUG2(MAKE, "Examining %s%s...\n", gn->name, gn->cohort_num);
if (gn->made != REQUESTED) {
- /*
- * XXX: Replace %d with string representation;
- * see made_name.
- */
- DEBUG1(MAKE, "state %d\n", gn->made);
-
- make_abort(gn, __LINE__);
+ debug_printf("internal error: made = %s\n",
+ GNodeMade_Name(gn->made));
+ Targ_PrintNode(gn, 2);
+ Targ_PrintNodes(&toBeMade, 2);
+ Targ_PrintGraph(3);
+ abort();
}
if (gn->checked_seqno == checked_seqno) {
diff --git a/make.h b/make.h
index 9b73b04abb74..e4e374f71e0c 100644
--- a/make.h
+++ b/make.h
@@ -1,4 +1,4 @@
-/* $NetBSD: make.h,v 1.300 2022/04/18 15:06:27 rillig Exp $ */
+/* $NetBSD: make.h,v 1.303 2022/06/12 13:37:32 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -785,6 +785,11 @@ typedef struct CmdOpts {
*/
StringList create;
+ /*
+ * Randomize the order in which the targets from toBeMade are made,
+ * to catch undeclared dependencies.
+ */
+ bool randomizeTargets;
} CmdOpts;
extern CmdOpts opts;
@@ -804,7 +809,7 @@ bool Arch_IsLib(GNode *) MAKE_ATTR_USE;
/* compat.c */
bool Compat_RunCommand(const char *, GNode *, StringListNode *);
-void Compat_Run(GNodeList *);
+void Compat_MakeAll(GNodeList *);
void Compat_Make(GNode *, GNode *);
/* cond.c */
@@ -863,7 +868,7 @@ bool GetBooleanExpr(const char *, bool);
void Parse_Init(void);
void Parse_End(void);
-void PrintLocation(FILE *, bool, const char *, unsigned);
+void PrintLocation(FILE *, bool, const GNode *);
void PrintStackTrace(bool);
void Parse_Error(ParseErrorLevel, const char *, ...) MAKE_ATTR_PRINTFLIKE(2, 3);
bool Parse_VarAssign(const char *, bool, GNode *) MAKE_ATTR_USE;
diff --git a/mk/ChangeLog b/mk/ChangeLog
index d888c129cb52..b1a8313b929d 100644
--- a/mk/ChangeLog
+++ b/mk/ChangeLog
@@ -1,3 +1,23 @@
+2022-07-20 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * install-mk (MK_VERSION): 20220720
+
+ * prog.mk: handle PROG_CXX for more than just NetBSD
+
+2022-06-20 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * install-mk (MK_VERSION): 20220620
+
+ * yacc.mk: when we have *.y in SRCS used explicit rules and .ORDER
+ rather than just suffix rules
+
+2022-04-23 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * install-mk (MK_VERSION): 20220422
+
+ * gendirdeps.mk: If LOCAL_DEPENDS_GUARD is set to "no"
+ do not capture any local depends in Makefile.depend
+
2022-03-25 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20220323
diff --git a/mk/gendirdeps.mk b/mk/gendirdeps.mk
index b977f3c48d99..b449bb5cc9d9 100644
--- a/mk/gendirdeps.mk
+++ b/mk/gendirdeps.mk
@@ -1,4 +1,4 @@
-# $Id: gendirdeps.mk,v 1.46 2020/08/19 17:51:53 sjg Exp $
+# $Id: gendirdeps.mk,v 1.47 2022/04/23 21:37:03 sjg Exp $
# Copyright (c) 2011-2020, Simon J. Gerraty
# Copyright (c) 2010-2018, Juniper Networks, Inc.
@@ -339,6 +339,8 @@ CAT_DEPEND ?= .depend
.PHONY: ${_DEPENDFILE}
.endif
+# set this to 'no' and we will not capture any
+# local depends
LOCAL_DEPENDS_GUARD ?= _{.MAKE.LEVEL} > 0
# 'cat .depend' should suffice, but if we are mixing build modes
@@ -351,6 +353,7 @@ ${_DEPENDFILE}: .NOMETA ${CAT_DEPEND:M.depend} ${META_FILES:O:u:@m@${exists($m):
echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \
${_include_src_dirdeps} \
echo '.include <dirdeps.mk>'; \
+ [ "${LOCAL_DEPENDS_GUARD:[1]:tl}" != no ] || exit 0; \
echo; \
echo '.if ${LOCAL_DEPENDS_GUARD}'; \
echo '# local dependencies - needed for -jN in clean tree'; \
diff --git a/mk/install-mk b/mk/install-mk
index 7d0ee92c9397..5fbdd49e26b5 100644
--- a/mk/install-mk
+++ b/mk/install-mk
@@ -55,7 +55,7 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
-# $Id: install-mk,v 1.217 2022/03/25 23:43:43 sjg Exp $
+# $Id: install-mk,v 1.220 2022/07/22 20:08:56 sjg Exp $
#
# @(#) Copyright (c) 1994 Simon J. Gerraty
#
@@ -70,7 +70,7 @@
# sjg@crufty.net
#
-MK_VERSION=20220323
+MK_VERSION=20220720
OWNER=
GROUP=
MODE=444
diff --git a/mk/mkopt.sh b/mk/mkopt.sh
index 4a42c0ddf122..91dd8f0d9cbe 100644
--- a/mk/mkopt.sh
+++ b/mk/mkopt.sh
@@ -1,8 +1,8 @@
#!/bin/sh
-# $Id: mkopt.sh,v 1.13 2020/08/19 17:51:53 sjg Exp $
+# $Id: mkopt.sh,v 1.15 2022/06/06 21:34:21 sjg Exp $
#
-# @(#) Copyright (c) 2014, 2020, Simon J. Gerraty
+# @(#) Copyright (c) 2014-2022, Simon J. Gerraty
#
# This file is provided in the hope that it will
# be of use. There is absolutely NO WARRANTY.
@@ -84,9 +84,36 @@ _mk_opts_defaults() {
$OPTIONS_DEFAULT_DEPENDENT $__DEFAULT_DEPENDENT_OPTIONS
}
+# _mk_cmdline_opts opt ...
+# look at the command line (saved in _cmdline)
+# to see any options we care about are being set with -DWITH*
+# or MK_*= if 'opt' is '*' then all options are of interest.
+_cmdline="$0 $@"
+_mk_cmdline_opts() {
+ for _x in $_cmdline
+ do
+ case "$_x" in
+ -DWITH*|${_MKOPT_PREFIX:-MK_}*)
+ for _o in "$@"
+ do
+ case "$_x" in
+ -DWITH_$_o|-DWITHOUT_$_o) eval ${_x#-D}=1;;
+ -DWITH_$_o=*|-DWITHOUT_$_o=*) eval ${_x#-D};;
+ ${_MKOPT_PREFIX:-MK_}$_o=*) eval "$_x";;
+ esac
+ done
+ ;;
+ esac
+ done
+}
+
+
case "/$0" in
*/mkopt*)
_list=no
+ _mk_cmdline_opts '*'
+ _mk_opts no DEBUG
+ [ $MK_DEBUG = no ] || set -x
while :
do
case "$1" in
diff --git a/mk/prog.mk b/mk/prog.mk
index 902b221f7fe5..b281cf08b320 100644
--- a/mk/prog.mk
+++ b/mk/prog.mk
@@ -1,4 +1,4 @@
-# $Id: prog.mk,v 1.37 2021/12/08 05:56:50 sjg Exp $
+# $Id: prog.mk,v 1.38 2022/07/22 20:08:56 sjg Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__: .NOTMAIN
@@ -73,6 +73,13 @@ ${CXX_SUFFIXES:%=%.o}:
@rm -f x.cc
.endif
+.if defined(PROG_CXX)
+PROG= ${PROG_CXX}
+_CCLINK= ${CXX}
+_SUPCXX?= -lstdc++ -lm
+.endif
+
+_CCLINK?= ${CC}
.if defined(PROG)
BINDIR ?= ${prefix}/bin
@@ -100,15 +107,8 @@ _PROGLDOPTS+= -Wl,-rpath-link,${DESTDIR}${SHLIBDIR}:${DESTDIR}/usr/lib \
-L${DESTDIR}${SHLIBDIR}
.endif
_PROGLDOPTS+= -Wl,-rpath,${SHLIBDIR}:/usr/lib
-
-.if defined(PROG_CXX)
-_CCLINK= ${CXX}
-_SUPCXX= -lstdc++ -lm
-.endif
.endif # NetBSD
-_CCLINK?= ${CC}
-
.if ${MK_PROG_LDORDER_MK} != "no"
${PROG}: ldorder
diff --git a/mk/yacc.mk b/mk/yacc.mk
index 7f7e99578d70..cdb8a657b542 100644
--- a/mk/yacc.mk
+++ b/mk/yacc.mk
@@ -1,4 +1,4 @@
-# $Id: yacc.mk,v 1.7 2020/08/19 17:51:53 sjg Exp $
+# $Id: yacc.mk,v 1.8 2022/06/22 04:51:06 sjg Exp $
#
# @(#) Copyright (c) 1999-2011, Simon J. Gerraty
@@ -23,6 +23,28 @@ RM?= rm
YACC.y?= ${YACC} ${YFLAGS}
+# first deal with explicit *.y in SRCS
+.for y in ${SRCS:M*.y}
+.if ${YACC.y:M-d} == "" || defined(NO_RENAME_Y_TAB_H)
+.ORDER: ${y:T:R}.c y.tab.h
+y.tab.h: .NOMETA
+${y:T:R}.c y.tab.h: $y
+ ${YACC.y} ${.IMPSRC}
+ [ ! -s y.tab.c ] || mv y.tab.c ${.TARGET}
+ ${RM} -f y.tab.[!h]
+.else
+.ORDER: ${y:T:R}.c ${y:T:R}.h
+${y:T:R}.h: .NOMETA
+${y:T:R}.c ${y:T:R}.h: $y
+ ${YACC.y} ${.IMPSRC}
+ [ ! -s y.tab.c ] || mv y.tab.c ${.TARGET:T:R}.c
+ [ ! -s y.tab.h ] || cmp -s y.tab.h ${.TARGET:T:R}.h \
+ || mv y.tab.h ${.TARGET:T:R}.h
+ ${RM} -f y.tab.*
+.endif
+.endfor
+
+.if ${SRCS:M*.y} == ""
.if ${YACC.y:M-d} == "" || defined(NO_RENAME_Y_TAB_H)
.y.c:
@@ -50,8 +72,10 @@ YACC.y?= ${YACC} ${YFLAGS}
{ [ ! -s y.tab.c ] || mv y.tab.c ${.TARGET}; \
${RM} y.tab.*; }; }
.endif
+.endif
beforedepend: ${SRCS:T:M*.y:S/.y/.c/g}
CLEANFILES+= ${SRCS:T:M*.y:S/.y/.[ch]/g}
CLEANFILES+= y.tab.[ch]
+
diff --git a/parse.c b/parse.c
index 398c594f523e..c2ecdbe875bf 100644
--- a/parse.c
+++ b/parse.c
@@ -1,4 +1,4 @@
-/* $NetBSD: parse.c,v 1.670 2022/04/18 16:09:05 sjg Exp $ */
+/* $NetBSD: parse.c,v 1.681 2022/07/24 20:25:23 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -121,7 +121,7 @@
#include "pathnames.h"
/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: parse.c,v 1.670 2022/04/18 16:09:05 sjg Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.681 2022/07/24 20:25:23 rillig Exp $");
/*
* A file being read.
@@ -325,7 +325,7 @@ CurFile(void)
}
static Buffer
-loadfile(const char *path, int fd)
+LoadFile(const char *path, int fd)
{
ssize_t n;
Buffer buf;
@@ -452,10 +452,22 @@ FindKeyword(const char *str)
}
void
-PrintLocation(FILE *f, bool useVars, const char *fname, unsigned lineno)
+PrintLocation(FILE *f, bool useVars, const GNode *gn)
{
char dirbuf[MAXPATHLEN + 1];
FStr dir, base;
+ const char *fname;
+ unsigned lineno;
+
+ if (gn != NULL) {
+ fname = gn->fname;
+ lineno = gn->lineno;
+ } else if (includes.len > 0) {
+ IncludedFile *curFile = CurFile();
+ fname = curFile->name.str;
+ lineno = curFile->lineno;
+ } else
+ return;
if (!useVars || fname[0] == '/' || strcmp(fname, "(stdin)") == 0) {
(void)fprintf(f, "\"%s\" line %u: ", fname, lineno);
@@ -478,16 +490,15 @@ PrintLocation(FILE *f, bool useVars, const char *fname, unsigned lineno)
FStr_Done(&dir);
}
-static void MAKE_ATTR_PRINTFLIKE(6, 0)
-ParseVErrorInternal(FILE *f, bool useVars, const char *fname, unsigned lineno,
+static void MAKE_ATTR_PRINTFLIKE(5, 0)
+ParseVErrorInternal(FILE *f, bool useVars, const GNode *gn,
ParseErrorLevel level, const char *fmt, va_list ap)
{
static bool fatal_warning_error_printed = false;
(void)fprintf(f, "%s: ", progname);
- if (fname != NULL)
- PrintLocation(f, useVars, fname, lineno);
+ PrintLocation(f, useVars, gn);
if (level == PARSE_WARNING)
(void)fprintf(f, "warning: ");
(void)vfprintf(f, fmt, ap);
@@ -508,20 +519,20 @@ ParseVErrorInternal(FILE *f, bool useVars, const char *fname, unsigned lineno,
PrintStackTrace(false);
}
-static void MAKE_ATTR_PRINTFLIKE(4, 5)
-ParseErrorInternal(const char *fname, unsigned lineno,
+static void MAKE_ATTR_PRINTFLIKE(3, 4)
+ParseErrorInternal(const GNode *gn,
ParseErrorLevel level, const char *fmt, ...)
{
va_list ap;
(void)fflush(stdout);
va_start(ap, fmt);
- ParseVErrorInternal(stderr, false, fname, lineno, level, fmt, ap);
+ ParseVErrorInternal(stderr, false, gn, level, fmt, ap);
va_end(ap);
if (opts.debug_file != stdout && opts.debug_file != stderr) {
va_start(ap, fmt);
- ParseVErrorInternal(opts.debug_file, false, fname, lineno,
+ ParseVErrorInternal(opts.debug_file, false, gn,
level, fmt, ap);
va_end(ap);
}
@@ -539,26 +550,15 @@ void
Parse_Error(ParseErrorLevel level, const char *fmt, ...)
{
va_list ap;
- const char *fname;
- unsigned lineno;
-
- if (includes.len == 0) {
- fname = NULL;
- lineno = 0;
- } else {
- IncludedFile *curFile = CurFile();
- fname = curFile->name.str;
- lineno = curFile->lineno;
- }
(void)fflush(stdout);
va_start(ap, fmt);
- ParseVErrorInternal(stderr, true, fname, lineno, level, fmt, ap);
+ ParseVErrorInternal(stderr, true, NULL, level, fmt, ap);
va_end(ap);
if (opts.debug_file != stdout && opts.debug_file != stderr) {
va_start(ap, fmt);
- ParseVErrorInternal(opts.debug_file, true, fname, lineno,
+ ParseVErrorInternal(opts.debug_file, true, NULL,
level, fmt, ap);
va_end(ap);
}
@@ -714,11 +714,11 @@ static void
ApplyDependencySourceWait(bool isSpecial)
{
static unsigned wait_number = 0;
- char wait_src[16];
+ char name[6 + 10 + 1];
GNode *gn;
- snprintf(wait_src, sizeof wait_src, ".WAIT_%u", ++wait_number);
- gn = Targ_NewInternalNode(wait_src);
+ snprintf(name, sizeof name, ".WAIT_%u", ++wait_number);
+ gn = Targ_NewInternalNode(name);
if (doing_depend)
RememberLocation(gn);
gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN;
@@ -1037,27 +1037,34 @@ HandleDependencyTarget(const char *targetName,
}
static void
-HandleDependencyTargetMundane(char *targetName)
+HandleSingleDependencyTargetMundane(const char *name)
{
- StringList targetNames = LST_INIT;
+ GNode *gn = Suff_IsTransform(name)
+ ? Suff_AddTransform(name)
+ : Targ_GetNode(name);
+ if (doing_depend)
+ RememberLocation(gn);
+ Lst_Append(targets, gn);
+}
+
+static void
+HandleDependencyTargetMundane(const char *targetName)
+{
if (Dir_HasWildcards(targetName)) {
+ StringList targetNames = LST_INIT;
+
SearchPath *emptyPath = SearchPath_New();
SearchPath_Expand(emptyPath, targetName, &targetNames);
SearchPath_Free(emptyPath);
- } else
- Lst_Append(&targetNames, targetName);
-
- while (!Lst_IsEmpty(&targetNames)) {
- char *targName = Lst_Dequeue(&targetNames);
- GNode *gn = Suff_IsTransform(targName)
- ? Suff_AddTransform(targName)
- : Targ_GetNode(targName);
- if (doing_depend)
- RememberLocation(gn);
- Lst_Append(targets, gn);
- }
+ while (!Lst_IsEmpty(&targetNames)) {
+ char *targName = Lst_Dequeue(&targetNames);
+ HandleSingleDependencyTargetMundane(targName);
+ free(targName);
+ }
+ } else
+ HandleSingleDependencyTargetMundane(targetName);
}
static void
@@ -1113,10 +1120,12 @@ ParseDependencyOp(char **pp)
{
if (**pp == '!')
return (*pp)++, OP_FORCE;
- if ((*pp)[1] == ':')
+ if (**pp == ':' && (*pp)[1] == ':')
return *pp += 2, OP_DOUBLEDEP;
- else
+ else if (**pp == ':')
return (*pp)++, OP_DEPENDS;
+ else
+ return OP_NONE;
}
static void
@@ -1131,6 +1140,56 @@ ClearPaths(SearchPathList *paths)
Dir_SetPATH();
}
+static char *
+FindInDirOfIncludingFile(const char *file)
+{
+ char *fullname, *incdir, *slash, *newName;
+ int i;
+
+ fullname = NULL;
+ incdir = bmake_strdup(CurFile()->name.str);
+ slash = strrchr(incdir, '/');
+ if (slash != NULL) {
+ *slash = '\0';
+ /*
+ * Now do lexical processing of leading "../" on the
+ * filename.
+ */
+ for (i = 0; strncmp(file + i, "../", 3) == 0; i += 3) {
+ slash = strrchr(incdir + 1, '/');
+ if (slash == NULL || strcmp(slash, "/..") == 0)
+ break;
+ *slash = '\0';
+ }
+ newName = str_concat3(incdir, "/", file + i);
+ fullname = Dir_FindFile(newName, parseIncPath);
+ if (fullname == NULL)
+ fullname = Dir_FindFile(newName, &dirSearchPath);
+ free(newName);
+ }
+ free(incdir);
+ return fullname;
+}
+
+static char *
+FindInQuotPath(const char *file)
+{
+ const char *suff;
+ SearchPath *suffPath;
+ char *fullname;
+
+ fullname = FindInDirOfIncludingFile(file);
+ if (fullname == NULL &&
+ (suff = strrchr(file, '.')) != NULL &&
+ (suffPath = Suff_GetPath(suff)) != NULL)
+ fullname = Dir_FindFile(file, suffPath);
+ if (fullname == NULL)
+ fullname = Dir_FindFile(file, parseIncPath);
+ if (fullname == NULL)
+ fullname = Dir_FindFile(file, &dirSearchPath);
+ return fullname;
+}
+
/*
* Handle one of the .[-ds]include directives by remembering the current file
* and pushing the included file on the stack. After the included file has
@@ -1146,77 +1205,14 @@ IncludeFile(const char *file, bool isSystem, bool depinc, bool silent)
{
Buffer buf;
char *fullname; /* full pathname of file */
- char *newName;
- char *slash, *incdir;
int fd;
- int i;
fullname = file[0] == '/' ? bmake_strdup(file) : NULL;
- if (fullname == NULL && !isSystem) {
- /*
- * Include files contained in double-quotes are first searched
- * relative to the including file's location. We don't want to
- * cd there, of course, so we just tack on the old file's
- * leading path components and call Dir_FindFile to see if
- * we can locate the file.
- */
-
- incdir = bmake_strdup(CurFile()->name.str);
- slash = strrchr(incdir, '/');
- if (slash != NULL) {
- *slash = '\0';
- /*
- * Now do lexical processing of leading "../" on the
- * filename.
- */
- for (i = 0; strncmp(file + i, "../", 3) == 0; i += 3) {
- slash = strrchr(incdir + 1, '/');
- if (slash == NULL || strcmp(slash, "/..") == 0)
- break;
- *slash = '\0';
- }
- newName = str_concat3(incdir, "/", file + i);
- fullname = Dir_FindFile(newName, parseIncPath);
- if (fullname == NULL)
- fullname = Dir_FindFile(newName,
- &dirSearchPath);
- free(newName);
- }
- free(incdir);
-
- if (fullname == NULL) {
- /*
- * Makefile wasn't found in same directory as included
- * makefile.
- *
- * Search for it first on the -I search path, then on
- * the .PATH search path, if not found in a -I
- * directory. If we have a suffix-specific path, we
- * should use that.
- */
- const char *suff;
- SearchPath *suffPath = NULL;
+ if (fullname == NULL && !isSystem)
+ fullname = FindInQuotPath(file);
- if ((suff = strrchr(file, '.')) != NULL) {
- suffPath = Suff_GetPath(suff);
- if (suffPath != NULL)
- fullname = Dir_FindFile(file, suffPath);
- }
- if (fullname == NULL) {
- fullname = Dir_FindFile(file, parseIncPath);
- if (fullname == NULL)
- fullname = Dir_FindFile(file,
- &dirSearchPath);
- }
- }
- }
-
- /* Looking for a system file or file still not found */
if (fullname == NULL) {
- /*
- * Look for it on the system path
- */
SearchPath *path = Lst_IsEmpty(&sysIncPath->dirs)
? defSysIncPath : sysIncPath;
fullname = Dir_FindFile(file, path);
@@ -1228,16 +1224,14 @@ IncludeFile(const char *file, bool isSystem, bool depinc, bool silent)
return;
}
- /* Actually open the file... */
- fd = open(fullname, O_RDONLY);
- if (fd == -1) {
+ if ((fd = open(fullname, O_RDONLY)) == -1) {
if (!silent)
Parse_Error(PARSE_FATAL, "Cannot open %s", fullname);
free(fullname);
return;
}
- buf = loadfile(fullname, fd);
+ buf = LoadFile(fullname, fd);
(void)close(fd);
Parse_PushInput(fullname, 1, 0, buf, NULL);
@@ -1586,6 +1580,7 @@ ParseDependency(char *line)
ParseSpecial special; /* in special targets, the children are
* linked as children of the parent but not
* vice versa */
+ GNodeType op;
DEBUG1(PARSE, "ParseDependency(%s)\n", line);
p = line;
@@ -1599,7 +1594,12 @@ ParseDependency(char *line)
if (!Lst_IsEmpty(targets))
CheckSpecialMundaneMixture(special);
- ApplyDependencyOperator(ParseDependencyOp(&p));
+ op = ParseDependencyOp(&p);
+ if (op == OP_NONE) {
+ InvalidLineType(line);
+ goto out;
+ }
+ ApplyDependencyOperator(op);
pp_skip_whitespace(&p);
@@ -1945,7 +1945,7 @@ GNode_AddCommand(GNode *gn, char *cmd)
Parse_Error(PARSE_WARNING,
"duplicate script for target \"%s\" ignored",
gn->name);
- ParseErrorInternal(gn->fname, gn->lineno, PARSE_WARNING,
+ ParseErrorInternal(gn, PARSE_WARNING,
"using previous script for \"%s\" defined here",
gn->name);
#endif
@@ -2894,7 +2894,7 @@ Parse_File(const char *name, int fd)
char *line;
Buffer buf;
- buf = loadfile(name, fd != -1 ? fd : STDIN_FILENO);
+ buf = LoadFile(name, fd != -1 ? fd : STDIN_FILENO);
if (fd != -1)
(void)close(fd);
diff --git a/str.c b/str.c
index c64d407cf676..d88f895630e5 100644
--- a/str.c
+++ b/str.c
@@ -1,4 +1,4 @@
-/* $NetBSD: str.c,v 1.89 2022/03/03 19:50:01 rillig Exp $ */
+/* $NetBSD: str.c,v 1.93 2022/06/11 09:24:07 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -71,7 +71,7 @@
#include "make.h"
/* "@(#)str.c 5.8 (Berkeley) 6/1/90" */
-MAKE_RCSID("$NetBSD: str.c,v 1.89 2022/03/03 19:50:01 rillig Exp $");
+MAKE_RCSID("$NetBSD: str.c,v 1.93 2022/06/11 09:24:07 rillig Exp $");
static HashTable interned_strings;
@@ -219,7 +219,7 @@ Substring_Words(const char *str, bool expand)
if (word_start == NULL)
word_start = word_end;
*word_end++ = '\\';
- /* catch '\' at end of line */
+ /* catch lonely '\' at end of string */
if (str_p[1] == '\0')
continue;
ch = *++str_p;
@@ -293,54 +293,56 @@ Str_Words(const char *str, bool expand)
}
/*
+ * XXX: In the extreme edge case that one of the characters is from the basic
+ * execution character set and the other isn't, the result of the comparison
+ * differs depending on whether plain char is signed or unsigned.
+ *
+ * An example is the character range from \xE4 to 'a', where \xE4 may come
+ * from U+00E4 'Latin small letter A with diaeresis'.
+ *
+ * If char is signed, \xE4 evaluates to -28, the first half of the condition
+ * becomes -28 <= '0' && '0' <= 'a', which evaluates to true.
+ *
+ * If char is unsigned, \xE4 evaluates to 228, the second half of the
+ * condition becomes 'a' <= '0' && '0' <= 228, which evaluates to false.
+ */
+static bool
+in_range(char e1, char c, char e2)
+{
+ return (e1 <= c && c <= e2) || (e2 <= c && c <= e1);
+}
+
+/*
* Str_Match -- Test if a string matches a pattern like "*.[ch]".
* The following special characters are known *?\[] (as in fnmatch(3)).
*
* XXX: this function does not detect or report malformed patterns.
+ *
+ * See varmod-match.mk for examples and edge cases.
*/
bool
Str_Match(const char *str, const char *pat)
{
- for (;;) {
- /*
- * See if we're at the end of both the pattern and the
- * string. If so, we succeeded. If we're at the end of the
- * pattern but not at the end of the string, we failed.
- */
- if (*pat == '\0')
- return *str == '\0';
- if (*str == '\0' && *pat != '*')
- return false;
-
- /*
- * A '*' in the pattern matches any substring. We handle this
- * by calling ourselves for each suffix of the string.
- */
- if (*pat == '*') {
+ for (; *pat != '\0'; pat++, str++) {
+ if (*pat == '*') { /* match any substring */
pat++;
while (*pat == '*')
pat++;
if (*pat == '\0')
return true;
- while (*str != '\0') {
+ for (; *str != '\0'; str++)
if (Str_Match(str, pat))
return true;
- str++;
- }
return false;
}
- /* A '?' in the pattern matches any single character. */
- if (*pat == '?')
- goto thisCharOK;
-
- /*
- * A '[' in the pattern matches a character from a list.
- * The '[' is followed by the list of acceptable characters,
- * or by ranges (two characters separated by '-'). In these
- * character lists, the backslash is an ordinary character.
- */
- if (*pat == '[') {
+ if (*str == '\0')
+ return false;
+
+ if (*pat == '?') /* match any single character */
+ continue;
+
+ if (*pat == '[') { /* match a character from a list */
bool neg = pat[1] == '^';
pat += neg ? 2 : 1;
@@ -350,23 +352,12 @@ Str_Match(const char *str, const char *pat)
break;
return false;
}
- /*
- * XXX: This naive comparison makes the
- * control flow of the pattern parser
- * dependent on the actual value of the
- * string. This is unpredictable. It may be
- * though that the code only looks wrong but
- * actually all code paths result in the same
- * behavior. This needs further tests.
- */
if (*pat == *str)
break;
if (pat[1] == '-') {
if (pat[2] == '\0')
return neg;
- if (pat[0] <= *str && *str <= pat[2])
- break;
- if (pat[2] <= *str && *str <= pat[0])
+ if (in_range(pat[0], *str, pat[2]))
break;
pat += 2;
}
@@ -378,26 +369,16 @@ Str_Match(const char *str, const char *pat)
pat++;
if (*pat == '\0')
pat--;
- goto thisCharOK;
+ continue;
}
- /*
- * A backslash in the pattern matches the character following
- * it exactly.
- */
- if (*pat == '\\') {
+ if (*pat == '\\') /* match the next character exactly */
pat++;
- if (*pat == '\0')
- return false;
- }
if (*pat != *str)
return false;
-
- thisCharOK:
- pat++;
- str++;
}
+ return *str == '\0';
}
void
diff --git a/unit-tests/Makefile b/unit-tests/Makefile
index c3b64abad84a..de9720131535 100644
--- a/unit-tests/Makefile
+++ b/unit-tests/Makefile
@@ -1,6 +1,6 @@
-# $Id: Makefile,v 1.180 2022/04/18 21:25:37 sjg Exp $
+# $Id: Makefile,v 1.181 2022/06/13 00:18:20 sjg Exp $
#
-# $NetBSD: Makefile,v 1.312 2022/04/18 15:06:28 rillig Exp $
+# $NetBSD: Makefile,v 1.318 2022/06/10 21:28:50 rillig Exp $
#
# Unit tests for make(1)
#
@@ -83,7 +83,6 @@ TESTS+= cond-token-plain
TESTS+= cond-token-string
TESTS+= cond-token-var
TESTS+= cond-undef-lint
-TESTS+= cond1
TESTS+= counter
TESTS+= counter-append
TESTS+= dep
@@ -168,6 +167,7 @@ TESTS+= directive-export-impl
TESTS+= directive-export-gmake
TESTS+= directive-export-literal
TESTS+= directive-for
+TESTS+= directive-for-empty
TESTS+= directive-for-errors
TESTS+= directive-for-escape
TESTS+= directive-for-generating-endif
@@ -439,7 +439,6 @@ TESTS+= varparse-dynamic
TESTS+= varparse-errors
TESTS+= varparse-mod
TESTS+= varparse-undef-partial
-TESTS+= varquote
# some shells have quirks
_shell := ${.SHELL:tA:T}
@@ -579,8 +578,10 @@ SED_CMDS.varname-dot-shell+= -e 's,\[/[^] ]*\],[(details omitted)],g'
SED_CMDS.varname-empty= ${.OBJDIR .PARSEDIR .PATH .SHELL:L:@v@-e '/\\$v/d'@}
# Some tests need an additional round of postprocessing.
+POSTPROC.depsrc-wait= sed -e '/^---/d' -e 's,^\(: Making 3[abc]\)[123]$$,\1,'
POSTPROC.deptgt-suffixes= awk '/^\#\*\*\* Suffixes/,/^never-stop/'
POSTPROC.gnode-submake= awk '/Input graph/, /^$$/'
+POSTPROC.varname-dot-make-mode= sed 's,^\(: Making [abc]\)[123]$$,\1,'
# Some tests reuse other tests, which makes them unnecessarily fragile.
export-all.rawout: export.mk
@@ -724,7 +725,7 @@ MAKE_TEST_ENV+= MALLOC_CONF="junk:true" # for jemalloc 510
MAKE_TEST_ENV+= TMPDIR=${TMPDIR}
.if ${.MAKE.OS} == "NetBSD"
-LIMIT_RESOURCES?= ulimit -v 200000
+LIMIT_RESOURCES?= ulimit -v 300000
.endif
LIMIT_RESOURCES?= :
@@ -746,7 +747,7 @@ LIMIT_RESOURCES?= :
echo $$status > ${.TARGET:R}.status
@mv ${.TARGET}.tmp ${.TARGET}
-# Postprocess the test output so that the results can be compared.
+# Postprocess the test output to make the output platform-independent.
#
# always pretend .MAKE was called 'make'
_SED_CMDS+= -e 's,^${TEST_MAKE:T:S,.,\\.,g}[][0-9]*:,make:,'
diff --git a/unit-tests/cmdline.exp b/unit-tests/cmdline.exp
index e5748c5f88cb..5700da3295fb 100644
--- a/unit-tests/cmdline.exp
+++ b/unit-tests/cmdline.exp
@@ -2,4 +2,7 @@ makeobjdir-direct:
show-objdir: <tmpdir>/6a8899d2-d227-4b55-9b6b-f3c8eeb83fd5
makeobjdir-indirect:
show-objdir: <tmpdir>/a7b41170-53f8-4cc2-bc5c-e4c3dd93ec45/
+space-and-comment:
+value # no comment $
+value # no comment $
exit status 0
diff --git a/unit-tests/cmdline.mk b/unit-tests/cmdline.mk
index f82e7f967ef8..a24d46208e52 100644
--- a/unit-tests/cmdline.mk
+++ b/unit-tests/cmdline.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cmdline.mk,v 1.3 2021/02/06 18:26:03 sjg Exp $
+# $NetBSD: cmdline.mk,v 1.4 2022/06/10 18:58:07 rillig Exp $
#
# Tests for command line parsing and related special variables.
@@ -11,6 +11,7 @@ DIR12= ${TMPBASE}/${SUB1}/${SUB2}
all: prepare-dirs
all: makeobjdir-direct makeobjdir-indirect
+all: space-and-comment
prepare-dirs:
@rm -rf ${DIR2} ${DIR12}
@@ -34,3 +35,24 @@ makeobjdir-indirect:
show-objdir:
@echo $@: ${.OBJDIR:Q}
+
+
+# Variable assignments in the command line are handled differently from
+# variable assignments in makefiles. In the command line, trailing whitespace
+# is preserved, and the '#' does not start a comment. This is because the
+# low-level parsing from ParseRawLine does not take place.
+#
+# Preserving '#' and trailing whitespace has the benefit that when passing
+# such values to sub-makes via MAKEFLAGS, no special encoding is needed.
+# Leading whitespace in the variable value is discarded though, which makes
+# the behavior inconsistent.
+space-and-comment: .PHONY
+ @echo $@:
+
+ @env -i \
+ ${MAKE} -r -f /dev/null ' VAR= value # no comment ' -v VAR \
+ | sed 's,$$,$$,'
+
+ @env -i MAKEFLAGS="' VAR= value # no comment '" \
+ ${MAKE} -r -f /dev/null -v VAR \
+ | sed 's,$$,$$,'
diff --git a/unit-tests/comment.mk b/unit-tests/comment.mk
index 2471c8cf659d..792350f6223a 100644
--- a/unit-tests/comment.mk
+++ b/unit-tests/comment.mk
@@ -1,4 +1,4 @@
-# $NetBSD: comment.mk,v 1.4 2022/01/23 18:00:53 rillig Exp $
+# $NetBSD: comment.mk,v 1.5 2022/05/08 06:51:27 rillig Exp $
#
# Demonstrate how comments are written in makefiles.
@@ -23,7 +23,7 @@ on and on.
.endif # And after the closing directive.
VAR= # This comment makes the variable value empty.
- # ParseGetLine removes any whitespace before the
+ # ParseRawLine removes any whitespace before the
# comment.
.if ${VAR} != ""
. error
diff --git a/unit-tests/compat-error.mk b/unit-tests/compat-error.mk
index 4cbc48d4b6bb..bcfeb14ac408 100644
--- a/unit-tests/compat-error.mk
+++ b/unit-tests/compat-error.mk
@@ -1,17 +1,24 @@
-# $NetBSD: compat-error.mk,v 1.3 2020/12/13 19:33:53 rillig Exp $
+# $NetBSD: compat-error.mk,v 1.5 2022/05/08 06:51:27 rillig Exp $
#
# Test detailed error handling in compat mode.
#
-# Until 2020-12-13, .ERROR_TARGET was success3, which was wrong.
-# Since compat.c 1.215 from 2020-12-13, it is 'fail1', which is the first
-# failed top-level target. XXX: Even better would be if .ERROR_TARGET were
-# the smallest target that caused the build to fail, even if it were a
-# sub-sub-sub-dependency of a top-level target.
+# Make several targets that alternately succeed and fail.
#
-# XXX: As of 2020-12-13, .ERROR_CMD is empty, which is wrong.
+# The first failing top-level target is recorded in '.ERROR_TARGET'. While
+# this information may give a hint as to which target failed, it would be more
+# useful at that point to know the actual target that failed, or the complete
+# chain from root cause to top-level target.
+#
+# Historic bugs
+# Before compat.c 1.215 from 2020-12-13, '.ERROR_TARGET' was 'success3',
+# which was obviously wrong.
+#
+# Bugs
+# As of 2020-12-13, '.ERROR_CMD' is empty, which does not provide any
+# insight into the command that actually failed.
#
# See also:
-# Compat_Run
+# Compat_MakeAll
#
# The commit that added the NULL command to gn->commands:
# CVS: 1994.06.06.22.45.??
@@ -20,10 +27,10 @@
# 2020: LstNode_SetNull(cmdNode);
#
# The commit that skipped NULL commands for .ERROR_CMD:
-# CVS: 2016.08.11.19.53.??
+# CVS: 2016.08.11.19.53.17
# Git: 58b23478b7353d46457089e726b07a49197388e4
-.MAKEFLAGS: success1 fail1 success2 fail2 success3
+.MAKEFLAGS: -k success1 fail1 success2 fail2 success3
success1 success2 success3:
: Making ${.TARGET} out of nothing.
diff --git a/unit-tests/cond-cmp-string.mk b/unit-tests/cond-cmp-string.mk
index 305a41099b98..8b504ba0c0d6 100644
--- a/unit-tests/cond-cmp-string.mk
+++ b/unit-tests/cond-cmp-string.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-cmp-string.mk,v 1.15 2021/12/11 09:53:53 rillig Exp $
+# $NetBSD: cond-cmp-string.mk,v 1.16 2022/05/08 06:51:27 rillig Exp $
#
# Tests for string comparisons in .if conditions.
@@ -136,3 +136,11 @@
.else
. error
.endif
+
+# Two variables with different values compare unequal.
+VAR1= value1
+VAR2= value2
+.if ${VAR1} != ${VAR2}
+.else
+. error
+.endif
diff --git a/unit-tests/cond-func-defined.mk b/unit-tests/cond-func-defined.mk
index 43db548a572b..f13e2a9a1f7c 100644
--- a/unit-tests/cond-func-defined.mk
+++ b/unit-tests/cond-func-defined.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-func-defined.mk,v 1.8 2021/12/12 08:55:28 rillig Exp $
+# $NetBSD: cond-func-defined.mk,v 1.9 2022/05/08 06:51:27 rillig Exp $
#
# Tests for the defined() function in .if conditions.
@@ -48,5 +48,10 @@ ${:UA B}= variable name with spaces
. endif
.endfor
-all:
- @:;
+# Neither of the conditions is true. Before July 2020, the right-hand
+# condition was evaluated even though it was irrelevant.
+.if defined(UNDEF) && ${UNDEF:Mx} != ""
+. error
+.endif
+
+all: .PHONY
diff --git a/unit-tests/cond-token-string.exp b/unit-tests/cond-token-string.exp
index 1c0f086b464e..854de02b7310 100644
--- a/unit-tests/cond-token-string.exp
+++ b/unit-tests/cond-token-string.exp
@@ -13,6 +13,9 @@ CondParser_Eval: "${:Uvalue}"
make: "cond-token-string.mk" line 68: A nonempty variable expression evaluates to true.
CondParser_Eval: "${:U}"
make: "cond-token-string.mk" line 76: An empty variable evaluates to false.
+CondParser_Eval: ("${VAR}")
+CondParser_Eval: "quoted" == quoted
+Comparing "quoted" == "quoted"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/cond-token-string.mk b/unit-tests/cond-token-string.mk
index a92d3a896116..4a0f175fc79f 100644
--- a/unit-tests/cond-token-string.mk
+++ b/unit-tests/cond-token-string.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-token-string.mk,v 1.4 2021/01/21 00:38:28 rillig Exp $
+# $NetBSD: cond-token-string.mk,v 1.6 2022/05/08 06:57:00 rillig Exp $
#
# Tests for quoted string literals in .if conditions.
#
@@ -76,7 +76,24 @@
. info An empty variable evaluates to false.
.endif
+# A non-empty string evaluates to true, no matter if it's a literal string or
+# if it contains variable expressions. The parentheses are not necessary for
+# the parser, in this case their only purpose is to make the code harder to
+# read for humans.
+VAR= value
+.if ("${VAR}")
+.else
+. error
+.endif
+
+# In the conditions in .if directives, the left-hand side of a comparison must
+# be enclosed in quotes. The right-hand side does not need to be enclosed in
+# quotes.
+.if "quoted" == quoted
+.else
+. error
+.endif
+
.MAKEFLAGS: -d0
-all:
- @:;
+all: .PHONY
diff --git a/unit-tests/cond1.exp b/unit-tests/cond1.exp
deleted file mode 100644
index 8b65d782524d..000000000000
--- a/unit-tests/cond1.exp
+++ /dev/null
@@ -1,23 +0,0 @@
-make: "cond1.mk" line 80: warning: extra else
-make: "cond1.mk" line 90: warning: extra else
-2 is prime
-A='other' B='unknown' C='clever' o='no,no'
-Passed:
- var
- ("var")
- (var != var)
- var != var
- !((var != var) && defined(name))
- var == quoted
-
-1 is not prime
-2 is prime
-3 is prime
-4 is not prime
-5 is prime
-
-make: String comparison operator must be either == or !=
-make: Bad conditional expression '"0" > 0' in '"0" > 0?OK:No'
-
-OK
-exit status 0
diff --git a/unit-tests/cond1.mk b/unit-tests/cond1.mk
deleted file mode 100644
index 53908c2dacf1..000000000000
--- a/unit-tests/cond1.mk
+++ /dev/null
@@ -1,114 +0,0 @@
-# $NetBSD: cond1.mk,v 1.3 2020/11/15 14:58:14 rillig Exp $
-
-# TODO: Convert these tests into tutorial form.
-# TODO: Split these tests by topic.
-# TODO: Use better variable names and expression values that actually express
-# the intended behavior. uname(1) has nothing to do with conditions.
-
-# hard code these!
-TEST_UNAME_S= NetBSD
-TEST_UNAME_M= sparc
-TEST_MACHINE= i386
-
-.if ${TEST_UNAME_S}
-Ok=var,
-.endif
-.if ("${TEST_UNAME_S}")
-Ok+=(\"var\"),
-.endif
-.if (${TEST_UNAME_M} != ${TEST_MACHINE})
-Ok+=(var != var),
-.endif
-.if ${TEST_UNAME_M} != ${TEST_MACHINE}
-Ok+= var != var,
-.endif
-.if !((${TEST_UNAME_M} != ${TEST_MACHINE}) && defined(X))
-Ok+= !((var != var) && defined(name)),
-.endif
-# from bsd.obj.mk
-MKOBJ?=no
-.if ${MKOBJ} == "no"
-o= no
-Ok+= var == "quoted",
-.else
-.if defined(notMAKEOBJDIRPREFIX) || defined(norMAKEOBJDIR)
-.if defined(notMAKEOBJDIRPREFIX)
-o=${MAKEOBJDIRPREFIX}${__curdir}
-.else
-o= ${MAKEOBJDIR}
-.endif
-.endif
-o= o
-.endif
-
-# repeat the above to check we get the same result
-.if ${MKOBJ} == "no"
-o2= no
-.else
-.if defined(notMAKEOBJDIRPREFIX) || defined(norMAKEOBJDIR)
-.if defined(notMAKEOBJDIRPREFIX)
-o2=${MAKEOBJDIRPREFIX}${__curdir}
-.else
-o2= ${MAKEOBJDIR}
-.endif
-.endif
-o2= o
-.endif
-
-PRIMES=2 3 5 7 11
-NUMBERS=1 2 3 4 5
-
-n=2
-.if ${PRIMES:M$n} == ""
-X=not
-.else
-X=
-.endif
-
-.if ${MACHINE_ARCH} == no-such
-A=one
-.else
-.if ${MACHINE_ARCH} == not-this
-.if ${MACHINE_ARCH} == something-else
-A=unlikely
-.else
-A=no
-.endif
-.endif
-A=other
-# We expect an extra else warning - we're not skipping here
-.else
-A=this should be an error
-.endif
-
-.if $X != ""
-.if $X == not
-B=one
-.else
-B=other
-# We expect an extra else warning - we are skipping here
-.else
-B=this should be an error
-.endif
-.else
-B=unknown
-.endif
-
-.if "quoted" == quoted
-C=clever
-.else
-C=dim
-.endif
-
-.if defined(nosuch) && ${nosuch:Mx} != ""
-# this should not happen
-.info nosuch is x
-.endif
-
-all:
- @echo "$n is $X prime"
- @echo "A='$A' B='$B' C='$C' o='$o,${o2}'"
- @echo "Passed:${.newline} ${Ok:S/,/${.newline}/}"
- @echo "${NUMBERS:@n@$n is ${("${PRIMES:M$n}" == ""):?not:} prime${.newline}@}"
- @echo "${"${DoNotQuoteHere:U0}" > 0:?OK:No}"
- @echo "${${NoSuchNumber:U42} > 0:?OK:No}"
diff --git a/unit-tests/depsrc-wait.exp b/unit-tests/depsrc-wait.exp
index d1a60fbaa6e6..36bcb0678151 100644
--- a/unit-tests/depsrc-wait.exp
+++ b/unit-tests/depsrc-wait.exp
@@ -1,13 +1,18 @@
---- a ---
echo a
a
---- b1 ---
echo b1
b1
---- b ---
echo b
b
---- x ---
echo x
x
+: Making 3a
+: Making 3a
+: Making 3a
+: Making 3b
+: Making 3b
+: Making 3b
+: Making 3c
+: Making 3c
+: Making 3c
exit status 0
diff --git a/unit-tests/depsrc-wait.mk b/unit-tests/depsrc-wait.mk
index 95b0ea96e0a5..ab974d47c29d 100644
--- a/unit-tests/depsrc-wait.mk
+++ b/unit-tests/depsrc-wait.mk
@@ -1,9 +1,15 @@
-# $NetBSD: depsrc-wait.mk,v 1.3 2020/09/07 18:40:32 rillig Exp $
+# $NetBSD: depsrc-wait.mk,v 1.4 2022/05/07 17:49:47 rillig Exp $
#
# Tests for the special source .WAIT in dependency declarations,
# which adds a sequence point between the nodes to its left and the nodes
# to its right.
+all: .PHONY
+ @${MAKE} -r -f ${MAKEFILE} x
+ @${MAKE} -r -f ${MAKEFILE} three-by-three
+
+
+.if make(x)
# Even though the build could run massively parallel, the .WAIT imposes a
# strict ordering in this example, which forces the targets to be made in
# exactly this order.
@@ -19,3 +25,17 @@ b: b1
echo b
b1:
echo b1
+.endif
+
+
+# There are 3 groups of 3 targets, with .WAIT barriers in between. Each of
+# these groups has to be made completely before starting the next group.
+# See Makefile, POSTPROC for the postprocessing that takes place.
+.if make(three-by-three)
+.MAKEFLAGS: -j5
+.MAKE.MODE+= randomize-targets
+
+three-by-three: .WAIT 3a1 3a2 3a3 .WAIT 3b1 3b2 3b3 .WAIT 3c1 3c2 3c3 .WAIT
+3a1 3a2 3a3 3b1 3b2 3b3 3c1 3c2 3c3:
+ : Making ${.TARGET}
+.endif
diff --git a/unit-tests/deptgt-begin.mk b/unit-tests/deptgt-begin.mk
index b71d78f371ed..543e377c05db 100644
--- a/unit-tests/deptgt-begin.mk
+++ b/unit-tests/deptgt-begin.mk
@@ -1,4 +1,4 @@
-# $NetBSD: deptgt-begin.mk,v 1.5 2020/11/15 22:28:08 rillig Exp $
+# $NetBSD: deptgt-begin.mk,v 1.6 2022/05/07 08:01:20 rillig Exp $
#
# Tests for the special target .BEGIN in dependency declarations,
# which is a container for commands that are run before any other
@@ -25,8 +25,8 @@ before-begin: .PHONY .NOTMAIN
# Another way is to define a custom target and make that a .USE dependency.
# For the .BEGIN target, .USE dependencies do not work though, since in
-# Compat_Run, the .USE and .USEBEFORE nodes are expanded right after the
-# .BEGIN target has been run, which is too late.
+# Compat_MakeAll, the .USE and .USEBEFORE nodes are expanded right after the
+# .BEGIN target has been made, which is too late.
.BEGIN: use
use: .USE .NOTMAIN
: Making $@ from a .USE dependency.
@@ -35,8 +35,8 @@ use: .USE .NOTMAIN
# .BEGIN target.
#
# For the .BEGIN target, .USEBEFORE dependencies do not work though, since in
-# Compat_Run, the .USE and .USEBEFORE nodes are expanded right after the
-# .BEGIN target has been run, which is too late.
+# Compat_MakeAll, the .USE and .USEBEFORE nodes are expanded right after the
+# .BEGIN target has been made, which is too late.
.BEGIN: use-before
use-before: .USEBEFORE .NOTMAIN
: Making $@ from a .USEBEFORE dependency.
diff --git a/unit-tests/deptgt-end-fail-indirect.mk b/unit-tests/deptgt-end-fail-indirect.mk
index 29346b8321fe..dc921bcfda2c 100644
--- a/unit-tests/deptgt-end-fail-indirect.mk
+++ b/unit-tests/deptgt-end-fail-indirect.mk
@@ -1,10 +1,10 @@
-# $NetBSD: deptgt-end-fail-indirect.mk,v 1.2 2020/12/06 21:22:04 rillig Exp $
+# $NetBSD: deptgt-end-fail-indirect.mk,v 1.3 2022/05/07 08:01:20 rillig Exp $
#
# Tests for an error in a dependency of the .END node.
#
# Before 2020-11-25, an error in the .END target did not print the "Stop."
# and exited with status 0. The cause for this was a missing condition in
-# Compat_Run in the handling of the .END node.
+# Compat_MakeAll in the handling of the .END node.
all:
: $@
diff --git a/unit-tests/deptgt-end-fail.mk b/unit-tests/deptgt-end-fail.mk
index 57cdc7da8679..c77127f26091 100644
--- a/unit-tests/deptgt-end-fail.mk
+++ b/unit-tests/deptgt-end-fail.mk
@@ -1,11 +1,11 @@
-# $NetBSD: deptgt-end-fail.mk,v 1.6 2020/12/07 01:04:07 rillig Exp $
+# $NetBSD: deptgt-end-fail.mk,v 1.7 2022/05/07 08:01:20 rillig Exp $
#
# Tests for an errors in the main target, its dependencies,
# the .END node and its dependencies.
#
# Before 2020-11-25, an error in the .END target did not print the "Stop.",
# even though this was intended. The cause for this was a missing condition
-# in Compat_Run, in the code handling the .END node.
+# in Compat_MakeAll, in the code handling the .END node.
test: .PHONY
diff --git a/unit-tests/deptgt-posix.mk b/unit-tests/deptgt-posix.mk
index ae41af15ffec..bf29dbfbd627 100644
--- a/unit-tests/deptgt-posix.mk
+++ b/unit-tests/deptgt-posix.mk
@@ -1,16 +1,22 @@
-# $NetBSD: deptgt-posix.mk,v 1.2 2022/04/18 15:59:39 sjg Exp $
+# $NetBSD: deptgt-posix.mk,v 1.4 2022/05/07 21:24:52 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.
+# As of 2022-04-18, when parsing the dependency line '.POSIX', the variable
+# '%POSIX' is defined and <posix.mk> is included, if it exists. Other than
+# that, POSIX support is still incomplete, the exact set of supported features
+# needs to be cross-checked with the POSIX specification.
#
-# 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.
+# At the point of '.POSIX:', <sys.mk> has been loaded already, unless the
+# option '-r' was given. This means that an implementation of <posix.mk> must
+# work both with and without the system rules from <sys.mk> being in effect.
+#
+# Implementation note: this test needs to run isolated from the usual tests
+# directory to prevent unit-tests/posix.mk from interfering with the posix.mk
+# from the system directory that this test uses; since at least 1997, the
+# directive '.include <file>' has been looking in the current directory first
+# before searching the file in the system search path, as described in
+# https://gnats.netbsd.org/15163.
#
# See also:
# https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html
@@ -99,7 +105,8 @@ in-first-line: .PHONY set-up-sysdir check-is-posix run
'.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.
+# POSIX defines comment lines as "blank lines, empty lines, and lines with
+# <number-sign> ('#') as the first character".
all: after-comment-lines
after-comment-lines: .PHONY set-up-sysdir check-is-posix run
printf '%s\n' > ${MAIN_MK} \
diff --git a/unit-tests/directive-for-empty.exp b/unit-tests/directive-for-empty.exp
new file mode 100644
index 000000000000..b9764b3196af
--- /dev/null
+++ b/unit-tests/directive-for-empty.exp
@@ -0,0 +1,27 @@
+make: "directive-for-empty.mk" line 21: 2
+make: "directive-for-empty.mk" line 34: Missing argument for ".error"
+make: "directive-for-empty.mk" line 34: Missing argument for ".error"
+make: "directive-for-empty.mk" line 34: Missing argument for ".error"
+For: end for 1
+For: loop body:
+# The identifier 'empty' can only be used in conditions such as .if, .ifdef or
+# .elif. In other lines the string 'empty(' must be preserved.
+CPPFLAGS+= -Dmessage="empty(i)"
+# There may be whitespace between 'empty' and '('.
+.if ! empty (i)
+. error
+.endif
+# Even in conditions, the string 'empty(' is not always a function call, it
+# can occur in a string literal as well.
+.if "empty\(i)" != "empty(i)"
+. error
+.endif
+# In comments like 'empty(i)', the text must be preserved as well.
+#
+# Conditions, including function calls to 'empty', can not only occur in
+# condition directives, they can also occur in the modifier ':?', see
+# varmod-ifelse.mk.
+CPPFLAGS+= -Dmacro="${empty(i):?empty:not-empty}"
+make: Fatal errors encountered -- cannot continue
+make: stopped in unit-tests
+exit status 1
diff --git a/unit-tests/directive-for-empty.mk b/unit-tests/directive-for-empty.mk
new file mode 100644
index 000000000000..7f22a822ef77
--- /dev/null
+++ b/unit-tests/directive-for-empty.mk
@@ -0,0 +1,120 @@
+# $NetBSD: directive-for-empty.mk,v 1.1 2022/05/23 22:33:56 rillig Exp $
+#
+# Tests for .for loops containing conditions of the form 'empty(var:...)'.
+#
+# When a .for loop is expanded, variable expressions in the body of the loop
+# are replaced with expressions containing the variable values. This
+# replacement is a bit naive but covers most of the practical cases. The one
+# popular exception is the condition 'empty(var:Modifiers)', which does not
+# look like a variable expression and is thus not replaced.
+#
+# See also:
+# https://gnats.netbsd.org/43821
+
+
+# In the body of the .for loop, the expression '${i:M*2*}' is replaced with
+# '${:U11:M*2*}', '${:U12:M*2*}', '${:U13:M*2*}', one after another. This
+# replacement creates the impression that .for variables were real variables,
+# when in fact they aren't.
+.for i in 11 12 13
+. if ${i:M*2*}
+.info 2
+. endif
+.endfor
+
+
+# In conditions, the function call to 'empty' does not look like a variable
+# expression, therefore it is not replaced. Since there is no global variable
+# named 'i', this expression makes for a leaky abstraction. If the .for
+# variables were real variables, calling 'empty' would work on them as well.
+.for i in 11 12 13
+# Asking for an empty iteration variable does not make sense as the .for loop
+# splits the iteration items into words, and such a word cannot be empty.
+. if empty(i)
+. error # due to the leaky abstraction
+. endif
+# The typical way of using 'empty' with variables from .for loops is pattern
+# matching using the modifiers ':M' or ':N'.
+. if !empty(i:M*2*)
+. if ${i} != "12"
+. error
+. endif
+. endif
+.endfor
+
+
+# The idea of replacing every occurrences of 'empty(i' in the body of a .for
+# loop would be naive and require many special cases, as there are many cases
+# that need to be considered when deciding whether the token 'empty' is a
+# function call or not, as demonstrated by the following examples. For
+# variable expressions like '${i:Modifiers}', this is simpler as a single
+# dollar almost always starts a variable expression. For counterexamples and
+# edge cases, see directive-for-escape.mk. Adding another such tricky detail
+# is out of the question.
+.MAKEFLAGS: -df
+.for i in value
+# The identifier 'empty' can only be used in conditions such as .if, .ifdef or
+# .elif. In other lines the string 'empty(' must be preserved.
+CPPFLAGS+= -Dmessage="empty(i)"
+# There may be whitespace between 'empty' and '('.
+.if ! empty (i)
+. error
+.endif
+# Even in conditions, the string 'empty(' is not always a function call, it
+# can occur in a string literal as well.
+.if "empty\(i)" != "empty(i)"
+. error
+.endif
+# In comments like 'empty(i)', the text must be preserved as well.
+#
+# Conditions, including function calls to 'empty', can not only occur in
+# condition directives, they can also occur in the modifier ':?', see
+# varmod-ifelse.mk.
+CPPFLAGS+= -Dmacro="${empty(i):?empty:not-empty}"
+.endfor
+.MAKEFLAGS: -d0
+
+
+# An idea to work around the above problems is to collect the variables from
+# the .for loops in a separate scope. To match the current behavior, there
+# has to be one scope per included file. There may be .for loops using the
+# same variable name in files that include each other:
+#
+# outer.mk: .for i in outer
+# . info $i # outer
+# . include "inner.mk"
+# inner.mk: . info $i # (undefined)
+# . for i in inner
+# . info $i # inner
+# . endfor
+# . info $i # (undefined)
+# outer.mk: . info $i # outer
+# .endfor
+#
+# This might be regarded another leaky abstraction, but it is in fact useful
+# that variables from .for loops can only affect expressions in the current
+# file. If variables from .for loops were implemented as global variables,
+# they might interact between files.
+#
+# To emulate this exact behavior for the function 'empty', each file in the
+# stack of included files needs its own scope that is independent from the
+# other files.
+#
+# Another tricky detail are nested .for loops in a single file that use the
+# same variable name. These are generally avoided by developers, as they
+# would be difficult to understand for humans as well. Technically, they are
+# possible though. Assuming there are two nested .for loops, both using the
+# variable 'i'. When the inner .for loop ends, the inner 'i' needs to be
+# removed from the scope, which would need to make the outer 'i' visible
+# again. This would suggest to use one variable scope per .for loop.
+#
+# Using a separate scope has the benefit that Var_Parse already allows for
+# a custom scope to be passed as parameter. This would have another side
+# effect though. There are several modifiers that actually modify variables,
+# and these modifications happen in the scope that is passed to Var_Parse.
+# This would mean that the combination of a .for variable and the modifiers
+# '::=', '::+=', '::?=', '::!=' and ':_' would lead to different behavior than
+# before.
+
+# TODO: Add code that demonstrates the current interaction between variables
+# from .for loops and the modifiers mentioned above.
diff --git a/unit-tests/directive-for-escape.exp b/unit-tests/directive-for-escape.exp
index 5fa4ae1ed877..d679e0756e33 100644
--- a/unit-tests/directive-for-escape.exp
+++ b/unit-tests/directive-for-escape.exp
@@ -26,30 +26,37 @@ For: loop body:
make: "directive-for-escape.mk" line 43: value-with-modifier
For: end for 1
For: loop body:
+# ${:U\${UNDEF\:U\\$\\$}
+For: loop body:
+# ${:U{{\}\}}
+For: loop body:
+# ${:Uend\}}
+For: end for 1
+For: loop body:
. info ${:U\${UNDEF\:U\\$\\$}
-make: "directive-for-escape.mk" line 72: ${UNDEF:U\backslash$
+make: "directive-for-escape.mk" line 92: ${UNDEF:U\backslash$
For: loop body:
. info ${:U{{\}\}}
-make: "directive-for-escape.mk" line 72: {{}}
+make: "directive-for-escape.mk" line 92: {{}}
For: loop body:
. info ${:Uend\}}
-make: "directive-for-escape.mk" line 72: end}
+make: "directive-for-escape.mk" line 92: end}
For: end for 1
For: loop body:
. info ${:Ubegin<${UNDEF:Ufallback:N{{{}}}}>end}
-make: "directive-for-escape.mk" line 84: begin<fallback>end
+make: "directive-for-escape.mk" line 113: begin<fallback>end
For: end for 1
For: loop body:
. info ${:U\$}
-make: "directive-for-escape.mk" line 92: $
+make: "directive-for-escape.mk" line 121: $
For: end for 1
For: loop body:
. info ${NUMBERS} ${:Ureplaced}
-make: "directive-for-escape.mk" line 100: one two three replaced
+make: "directive-for-escape.mk" line 129: one two three replaced
For: end for 1
For: loop body:
. info ${:Ureplaced}
-make: "directive-for-escape.mk" line 110: replaced
+make: "directive-for-escape.mk" line 139: replaced
For: end for 1
For: loop body:
. info . $$i: ${:Uinner}
@@ -62,46 +69,46 @@ For: loop body:
. info . $${i2}: ${i2}
. info . $${i,}: ${i,}
. info . adjacent: ${:Uinner}${:Uinner}${:Uinner:M*}${:Uinner}
-make: "directive-for-escape.mk" line 118: . $i: inner
-make: "directive-for-escape.mk" line 119: . ${i}: inner
-make: "directive-for-escape.mk" line 120: . ${i:M*}: inner
-make: "directive-for-escape.mk" line 121: . $(i): inner
-make: "directive-for-escape.mk" line 122: . $(i:M*): inner
-make: "directive-for-escape.mk" line 123: . ${i${:U}}: outer
-make: "directive-for-escape.mk" line 124: . ${i\}}: inner}
-make: "directive-for-escape.mk" line 125: . ${i2}: two
-make: "directive-for-escape.mk" line 126: . ${i,}: comma
-make: "directive-for-escape.mk" line 127: . adjacent: innerinnerinnerinner
+make: "directive-for-escape.mk" line 147: . $i: inner
+make: "directive-for-escape.mk" line 148: . ${i}: inner
+make: "directive-for-escape.mk" line 149: . ${i:M*}: inner
+make: "directive-for-escape.mk" line 150: . $(i): inner
+make: "directive-for-escape.mk" line 151: . $(i:M*): inner
+make: "directive-for-escape.mk" line 152: . ${i${:U}}: outer
+make: "directive-for-escape.mk" line 153: . ${i\}}: inner}
+make: "directive-for-escape.mk" line 154: . ${i2}: two
+make: "directive-for-escape.mk" line 155: . ${i,}: comma
+make: "directive-for-escape.mk" line 156: . adjacent: innerinnerinnerinner
For: end for 1
For: loop body:
. info eight $$$$$$$$ and no cents.
. info eight ${:Udollar}${:Udollar}${:Udollar}${:Udollar} and no cents.
-make: "directive-for-escape.mk" line 135: eight $$$$ and no cents.
-make: "directive-for-escape.mk" line 136: eight dollardollardollardollar and no cents.
-make: "directive-for-escape.mk" line 145: eight and no cents.
+make: "directive-for-escape.mk" line 164: eight $$$$ and no cents.
+make: "directive-for-escape.mk" line 165: eight dollardollardollardollar and no cents.
+make: "directive-for-escape.mk" line 174: eight and no cents.
For: end for 1
-make: "directive-for-escape.mk" line 152: newline in .for value
-make: "directive-for-escape.mk" line 152: newline in .for value
+make: "directive-for-escape.mk" line 181: newline in .for value
+make: "directive-for-escape.mk" line 181: newline in .for value
For: loop body:
. info short: ${:U" "}
. info long: ${:U" "}
-make: "directive-for-escape.mk" line 153: short: " "
-make: "directive-for-escape.mk" line 154: long: " "
+make: "directive-for-escape.mk" line 182: short: " "
+make: "directive-for-escape.mk" line 183: long: " "
For: end for 1
For: loop body:
For: end for 1
-Parse_PushInput: .for loop in directive-for-escape.mk, line 167
-make: "directive-for-escape.mk" line 167: newline in .for value
- in .for loop from directive-for-escape.mk:167 with i = "
+Parse_PushInput: .for loop in directive-for-escape.mk, line 196
+make: "directive-for-escape.mk" line 196: newline in .for value
+ in .for loop from directive-for-escape.mk:196 with i = "
"
For: loop body:
: ${:U" "}
SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `directive-for-escape.mk'
-Parsing line 168: : ${:U" "}
+Parsing line 197: : ${:U" "}
ParseDependency(: " ")
-ParseEOF: returning to file directive-for-escape.mk, line 170
+ParseEOF: returning to file directive-for-escape.mk, line 199
SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `directive-for-escape.mk'
-Parsing line 170: .MAKEFLAGS: -d0
+Parsing line 199: .MAKEFLAGS: -d0
ParseDependency(.MAKEFLAGS: -d0)
For: end for 1
For: loop body:
diff --git a/unit-tests/directive-for-escape.mk b/unit-tests/directive-for-escape.mk
index 03a7a16b6a7b..fe704c453046 100644
--- a/unit-tests/directive-for-escape.mk
+++ b/unit-tests/directive-for-escape.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-for-escape.mk,v 1.15 2022/01/27 20:15:14 rillig Exp $
+# $NetBSD: directive-for-escape.mk,v 1.16 2022/06/12 16:09:21 rillig Exp $
#
# Test escaping of special characters in the iteration values of a .for loop.
# These values get expanded later using the :U variable modifier, and this
@@ -43,38 +43,67 @@ VALUES= $$ $${V} $${V:=-with-modifier} $$(V) $$(V:=-with-modifier)
. info $i
.endfor
+
# Try to cover the code for nested '{}' in ExprLen, without success.
#
# The value of the variable VALUES is not meant to be a variable expression.
# Instead, it is meant to represent literal text, the only escaping mechanism
# being that each '$' is written as '$$'.
+VALUES= $${UNDEF:U\$$\$$ {{}} end}
#
# The .for loop splits ${VALUES} into 3 words, at the space characters, since
# the '$$' is an ordinary character and the spaces are not escaped.
# Word 1 is '${UNDEF:U\$\$'
# Word 2 is '{{}}'
# Word 3 is 'end}'
-# The first iteration expands the body of the .for loop to:
-# expect: . info ${:U\${UNDEF\:U\\$\\$}
-# The modifier ':U' unescapes the '\$' to a simple '$'.
-# The modifier ':U' unescapes the '\:' to a simple ':'.
-# The modifier ':U' unescapes the '\\' to a simple '\'.
-# The modifier ':U' resolves the expression '$\' to the word 'backslash', due
-# to the following variable definition.
+#
+# Each of these words is now inserted in the body of the .for loop.
+.for i in ${VALUES}
+# $i
+.endfor
+#
+# When these words are injected into the body of the .for loop, each inside a
+# '${:U...}' expression, the result is:
+#
+# expect: For: loop body:
+# expect: # ${:U\${UNDEF\:U\\$\\$}
+# expect: For: loop body:
+# expect: # ${:U{{\}\}}
+# expect: For: loop body:
+# expect: # ${:Uend\}}
+# expect: For: end for 1
+#
+# The first of these expressions is the most interesting one, due to its many
+# special characters. This expression is properly balanced:
+#
+# Text Meaning Explanation
+# \$ $ escaped
+# { { ordinary text
+# UNDEF UNDEF ordinary text
+# \: : escaped
+# U U ordinary text
+# \\ \ escaped
+# $\ (expr) an expression, the variable name is '\'
+# \$ $ escaped
+#
+# To make the expression '$\' visible, define it to an actual word:
${:U\\}= backslash
-# FIXME: There was no expression '$\' in the original text of the previous
-# line, that's a surprise in the parser.
-# The modifier ':U' unescapes the '\$' to a simple '$'.
-# expect+4: ${UNDEF:U\backslash$
-VALUES= $${UNDEF:U\$$\$$ {{}} end}
-# XXX: Where in the code does the '\$\$' get converted into a single '\$'?
.for i in ${VALUES}
. info $i
.endfor
+#
+# expect-3: ${UNDEF:U\backslash$
+# expect-4: {{}}
+# expect-5: end}
+#
+# FIXME: There was no expression '$\' in the original text of the variable
+# 'VALUES', that's a surprise in the parser.
+
# Second try to cover the code for nested '{}' in ExprLen.
#
-# XXX: It is wrong that ExprLen requires the braces to be balanced.
+# XXX: It is not the job of ExprLen to parse an expression, it is naive to
+# expect ExprLen to get all the details right in just a few lines of code.
# Each variable modifier has its own inconsistent way of parsing nested
# variable expressions, braces and parentheses. (Compare ':M', ':S', and
# ':D' for details.) The only sensible thing to do is therefore to let
diff --git a/unit-tests/directive-for-lines.mk b/unit-tests/directive-for-lines.mk
index 96d659426882..648c6112daff 100644
--- a/unit-tests/directive-for-lines.mk
+++ b/unit-tests/directive-for-lines.mk
@@ -1,9 +1,9 @@
-# $NetBSD: directive-for-lines.mk,v 1.3 2020/12/19 12:40:00 rillig Exp $
+# $NetBSD: directive-for-lines.mk,v 1.4 2022/05/08 06:51:27 rillig Exp $
#
# Tests for the line numbers that are reported in .for loops.
#
-# Between 2007-01-01 (git 4d3c468f96e1080e, parse.c 1.127) and 2020-12-19
-# (parse.c 1.494), the line numbers for the .info directives and error
+# Since parse.c 1.127 from 2007-01-01 and before parse.c 1.494 from
+# 2020-12-19, the line numbers for the .info directives and error
# messages inside .for loops had been wrong since ParseGetLine skipped empty
# lines, even when collecting the lines for the .for loop body.
diff --git a/unit-tests/directive-for-null.mk b/unit-tests/directive-for-null.mk
index a374f508dd55..fb2d440ee1ba 100644
--- a/unit-tests/directive-for-null.mk
+++ b/unit-tests/directive-for-null.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-for-null.mk,v 1.1 2020/12/19 16:00:17 rillig Exp $
+# $NetBSD: directive-for-null.mk,v 1.3 2022/06/12 15:03:27 rillig Exp $
#
# Test for parsing a .for loop that accidentally contains a null byte.
#
@@ -9,11 +9,15 @@
# make: "(stdin)" line 3: Zero byte read from file
#
# The one about "end of file" might be misleading but is due to the
-# implementation. On both errors and EOF, ParseGetLine returns NULL.
+# implementation. On both errors and EOF, ParseRawLine returns NULL.
#
# The one about the "zero byte" in line 3 is surprising since the only
# line that contains a null byte is line 2.
all: .PHONY
- @printf '%s\n' '.for i in 1 2 3' 'VAR=value' '.endfor' | tr 'l' '\0' \
+ @printf '%s\n' \
+ '.for i in 1 2 3' \
+ 'VAR=value' \
+ '.endfor' \
+ | tr 'l' '\0' \
| ${MAKE} -f -
diff --git a/unit-tests/directive-info.mk b/unit-tests/directive-info.mk
index 54f6a0f5aad0..327ff63e7f9b 100644
--- a/unit-tests/directive-info.mk
+++ b/unit-tests/directive-info.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-info.mk,v 1.9 2022/01/08 20:21:34 rillig Exp $
+# $NetBSD: directive-info.mk,v 1.10 2022/05/08 06:51:27 rillig Exp $
#
# Tests for the .info directive.
#
@@ -18,7 +18,7 @@
.info.man: # not a message, but possibly a suffix rule
# Even if lines would have trailing whitespace, this would be trimmed by
-# ParseGetLine.
+# ParseRawLine.
.info
.info # comment
diff --git a/unit-tests/hanoi-include.mk b/unit-tests/hanoi-include.mk
index 3b9438bf2169..ce443c506b9b 100644
--- a/unit-tests/hanoi-include.mk
+++ b/unit-tests/hanoi-include.mk
@@ -1,19 +1,20 @@
-# $NetBSD: hanoi-include.mk,v 1.2 2022/01/08 22:13:43 rillig Exp $
+# $NetBSD: hanoi-include.mk,v 1.3 2022/05/08 07:27:50 rillig Exp $
#
-# Implements the Towers of Hanoi puzzle, thereby demonstrating a bunch of
-# more or less useful programming techniques:
+# Implements the Towers of Hanoi puzzle, demonstrating a bunch of more or less
+# useful programming techniques:
#
-# * default assignment using the ?= assignment operator
-# * including the same file recursively (rather unusual)
-# * extracting the current value of a variable using the .for loop
-# * using shell commands for calculations since make is a text processor
-# * using the :: dependency operator for adding commands to a target
-# * on-the-fly variable assignment expressions using the ::= modifier
+# * default assignment using the ?= assignment operator
+# * including the same file recursively (rather unusual)
+# * extracting the current value of a variable using the .for loop
+# * using shell commands for calculations since make is a text processor
+# * using the :: dependency operator for adding commands to a target
+# * on-the-fly variable assignment expressions using the ::= modifier
#
# usage:
-# env N=3 make -f hanoi-include.mk
-# endless loop:
-# make -f hanoi-include.mk N=3
+# env N=3 make -r -f hanoi-include.mk
+#
+# endless loop, since command line variables cannot be overridden:
+# make -r -f hanoi-include.mk N=3
N?= 5 # Move this number of disks ...
FROM?= A # ... from this stack ...
diff --git a/unit-tests/opt-define.mk b/unit-tests/opt-define.mk
index 7c4bbc179316..f508a9b1592f 100644
--- a/unit-tests/opt-define.mk
+++ b/unit-tests/opt-define.mk
@@ -1,4 +1,4 @@
-# $NetBSD: opt-define.mk,v 1.3 2022/01/23 16:09:38 rillig Exp $
+# $NetBSD: opt-define.mk,v 1.4 2022/06/12 14:27:06 rillig Exp $
#
# Tests for the -D command line option, which defines global variables to the
# value 1, like in the C preprocessor.
@@ -19,10 +19,22 @@ VAR= overwritten
.endif
# The variable can be undefined. If the variable had been defined in the
-# "Internal" scope instead, undefining it would have no effect.
+# "Internal" or in the "Command" scope instead, undefining it would have no
+# effect.
.undef VAR
.if defined(VAR)
. error
.endif
+# The C preprocessor allows to define a macro with a specific value. Make
+# behaves differently, it defines a variable with the name 'VAR=value' and the
+# value 1.
+.MAKEFLAGS: -DVAR=value
+.if defined(VAR)
+. error
+.endif
+.if ${VAR=value} != "1"
+. error
+.endif
+
all: .PHONY
diff --git a/unit-tests/opt-jobs-no-action.mk b/unit-tests/opt-jobs-no-action.mk
index 19d82c5bf4b8..fe720c9e0e61 100644
--- a/unit-tests/opt-jobs-no-action.mk
+++ b/unit-tests/opt-jobs-no-action.mk
@@ -1,4 +1,4 @@
-# $NetBSD: opt-jobs-no-action.mk,v 1.9 2021/04/04 09:58:51 rillig Exp $
+# $NetBSD: opt-jobs-no-action.mk,v 1.10 2022/05/08 06:51:27 rillig Exp $
#
# Tests for the combination of the options -j and -n, which prints the
# commands instead of actually running them.
@@ -21,7 +21,7 @@
# The shell attributes are handled by Job_ParseShell.
# The shell attributes 'quiet' and 'echo' don't need a trailing newline,
# this is handled by the [0] != '\0' checks in Job_ParseShell.
-# The '\#' is handled by ParseGetLine.
+# The '\#' is handled by ParseRawLine.
# The '\n' is handled by Str_Words in Job_ParseShell.
# The '$$' is handled by Var_Subst in ParseDependencyLine.
.SHELL: \
diff --git a/unit-tests/opt-version.mk b/unit-tests/opt-version.mk
index 51a4e8a1a0aa..cdba9180ec01 100644
--- a/unit-tests/opt-version.mk
+++ b/unit-tests/opt-version.mk
@@ -1,8 +1,8 @@
-# $NetBSD: opt-version.mk,v 1.1 2021/12/23 11:05:59 rillig Exp $
+# $NetBSD: opt-version.mk,v 1.2 2022/05/08 07:27:50 rillig Exp $
#
-# Tests for the command line option '--version', which outputs the version
-# number of make. NetBSD's make does not have a version number, but the bmake
-# distribution created from it has.
+# Tests for the command line option '--version', which may be expected to
+# output the version number of make. NetBSD's make does not have a version
+# number, but the bmake distribution created from it has.
# As of 2021-12-23, the output is a single empty line since the '--' does not
# end the command line options. Command line parsing then continues as if
diff --git a/unit-tests/opt-x-reduce-exported.exp b/unit-tests/opt-x-reduce-exported.exp
index 39a9383953dd..99570f2c30cb 100644
--- a/unit-tests/opt-x-reduce-exported.exp
+++ b/unit-tests/opt-x-reduce-exported.exp
@@ -1 +1,5 @@
+ordinary:
+BEFORE=before
+submake:
+BEFORE=before
exit status 0
diff --git a/unit-tests/opt-x-reduce-exported.mk b/unit-tests/opt-x-reduce-exported.mk
index 7ee8e7c7eff0..a42a85d21a53 100644
--- a/unit-tests/opt-x-reduce-exported.mk
+++ b/unit-tests/opt-x-reduce-exported.mk
@@ -1,8 +1,20 @@
-# $NetBSD: opt-x-reduce-exported.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $
+# $NetBSD: opt-x-reduce-exported.mk,v 1.3 2022/05/08 07:27:50 rillig Exp $
#
-# Tests for the -x command line option.
+# Tests for the -X command line option, which prevents variables passed on the
+# command line from being exported to the environment of child commands.
-# TODO: Implementation
+# The variable 'BEFORE' is exported, the variable 'AFTER' isn't.
+.MAKEFLAGS: BEFORE=before -X AFTER=after
-all:
- @:;
+all: .PHONY ordinary submake
+
+ordinary: .PHONY
+ @echo 'ordinary:'
+ @env | sort | grep -e '^BEFORE' -e '^AFTER'
+
+submake: .PHONY
+ @echo 'submake:'
+ @${MAKE} -r -f ${MAKEFILE} show-env
+
+show-env: .PHONY
+ @env | sort | grep -e '^BEFORE' -e '^AFTER'
diff --git a/unit-tests/parse.exp b/unit-tests/parse.exp
index 5807f9c17e2c..a11de0c194ae 100644
--- a/unit-tests/parse.exp
+++ b/unit-tests/parse.exp
@@ -1,5 +1,6 @@
make: "parse.mk" line 7: Makefile appears to contain unresolved CVS/RCS/??? merge conflicts
make: "parse.mk" line 14: Makefile appears to contain unresolved CVS/RCS/??? merge conflicts
+make: "parse.mk" line 24: Invalid line type
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/parse.mk b/unit-tests/parse.mk
index 9dccc7f5b7ce..986c303083bf 100644
--- a/unit-tests/parse.mk
+++ b/unit-tests/parse.mk
@@ -1,4 +1,4 @@
-# $NetBSD: parse.mk,v 1.2 2022/01/22 17:10:51 rillig Exp $
+# $NetBSD: parse.mk,v 1.3 2022/07/24 20:25:23 rillig Exp $
#
# Test those parts of the parsing that do not belong in any of the other
# categories.
@@ -12,3 +12,13 @@
# expect+1: Makefile appears to contain unresolved CVS/RCS/??? merge conflicts
>>>>>> new
+
+
+# Since parse.c 1.578 from 2021-12-14 and before parse.c 1.681 from
+# 2022-07-24, if a line of a makefile could only be a dependency specification
+# but didn't contain any of the dependency operators ':', '!', '::' and its
+# expansion ended with a space, make read a single byte from the memory beyond
+# the expanded line's terminating '\0'.
+#
+# https://bugs.freebsd.org/265119
+one-target ${:U }
diff --git a/unit-tests/varmod-head.exp b/unit-tests/varmod-head.exp
index 651844439f5f..39a9383953dd 100644
--- a/unit-tests/varmod-head.exp
+++ b/unit-tests/varmod-head.exp
@@ -1,11 +1 @@
-head (dirname) of 'a/b/c' is 'a/b'
-head (dirname) of 'def' is '.'
-head (dirname) of 'a.b.c' is '.'
-head (dirname) of 'a.b/c' is 'a.b'
-head (dirname) of 'a' is '.'
-head (dirname) of 'a.a' is '.'
-head (dirname) of '.gitignore' is '.'
-head (dirname) of 'a' is '.'
-head (dirname) of 'a.a' is '.'
-head (dirname) of 'trailing/' is 'trailing'
exit status 0
diff --git a/unit-tests/varmod-head.mk b/unit-tests/varmod-head.mk
index 66347b4bce61..f1a135cb328d 100644
--- a/unit-tests/varmod-head.mk
+++ b/unit-tests/varmod-head.mk
@@ -1,9 +1,64 @@
-# $NetBSD: varmod-head.mk,v 1.4 2020/12/20 22:57:40 rillig Exp $
+# $NetBSD: varmod-head.mk,v 1.5 2022/07/10 21:11:49 rillig Exp $
#
# Tests for the :H variable modifier, which returns the dirname of
# each of the words in the variable value.
-all:
-.for path in a/b/c def a.b.c a.b/c a a.a .gitignore a a.a trailing/
- @echo "head (dirname) of '"${path:Q}"' is '"${path:H:Q}"'"
-.endfor
+.if ${:U a/b/c :H} != "a/b"
+. error
+.endif
+
+.if ${:U def :H} != "."
+. error
+.endif
+
+.if ${:U a.b.c :H} != "."
+. error
+.endif
+
+.if ${:U a.b/c :H} != "a.b"
+. error
+.endif
+
+.if ${:U a :H} != "."
+. error
+.endif
+
+.if ${:U a.a :H} != "."
+. error
+.endif
+
+.if ${:U .gitignore :H} != "."
+. error
+.endif
+
+.if ${:U trailing/ :H} != "trailing"
+. error
+.endif
+
+.if ${:U /abs/dir/file :H} != "/abs/dir"
+. error
+.endif
+
+.if ${:U rel/dir/file :H} != "rel/dir"
+. error
+.endif
+
+# The head of "/" was an empty string before 2020.07.20.14.50.41, leading to
+# the output "before after", with two spaces. Since 2020.07.20.14.50.41, the
+# output is "before after", discarding the empty word.
+.if ${:U before/ / after/ :H} == "before after"
+# OK
+.elif ${:U before/ / after/ :H} == "before after"
+# No '.info' to keep the file compatible with old make versions.
+_!= echo "The modifier ':H' generates an empty word." 1>&2; echo
+.else
+. error
+.endif
+
+# An empty list is split into a single empty word.
+# The dirname of this empty word is ".".
+.if ${:U :H} != "."
+. error
+.endif
+
+all: .PHONY
diff --git a/unit-tests/varmod-ifelse.mk b/unit-tests/varmod-ifelse.mk
index 37e8f620d883..a823ae784935 100644
--- a/unit-tests/varmod-ifelse.mk
+++ b/unit-tests/varmod-ifelse.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-ifelse.mk,v 1.18 2022/01/15 20:16:55 rillig Exp $
+# $NetBSD: varmod-ifelse.mk,v 1.19 2022/05/08 06:51:27 rillig Exp $
#
# Tests for the ${cond:?then:else} variable modifier, which evaluates either
# the then-expression or the else-expression, depending on the condition.
@@ -133,7 +133,7 @@ VAR= value
# When parsing such an expression, the parser used to be strict. It first
# evaluated the left-hand side of the operator '&&' and then started parsing
# the right-hand side 'no >= 10'. The word 'no' is obviously a string
-# literal, not enclosed in quotes, which is ok, even on the left-hand side of
+# literal, not enclosed in quotes, which is OK, even on the left-hand side of
# the comparison operator, but only because this is a condition in the
# modifier ':?'. In an ordinary directive '.if', this would be a parse error.
# For strings, only the comparison operators '==' and '!=' are defined,
@@ -169,3 +169,16 @@ EMPTY= # empty
.info ${${ASTERISK} :?true:false}
# syntax error since the condition is completely blank.
.info ${${EMPTY} :?true:false}
+
+
+# Since the condition of the '?:' modifier is expanded before being parsed and
+# evaluated, it is common practice to enclose expressions in quotes, to avoid
+# producing syntactically invalid conditions such as ' == value'. This only
+# works if the expanded values neither contain quotes nor backslashes. For
+# strings containing quotes or backslashes, the '?:' modifier should not be
+# used.
+PRIMES= 2 3 5 7 11
+.if ${1 2 3 4 5:L:@n@$n:${ ("${PRIMES:M$n}" != "") :?prime:not_prime}@} != \
+ "1:not_prime 2:prime 3:prime 4:not_prime 5:prime"
+. error
+.endif
diff --git a/unit-tests/varmod-match.exp b/unit-tests/varmod-match.exp
index e4ad3ed113f3..5bf3da46e524 100644
--- a/unit-tests/varmod-match.exp
+++ b/unit-tests/varmod-match.exp
@@ -5,12 +5,13 @@ Comparing "five six seven" != "five six seven"
CondParser_Eval: ${NUMBERS:M[^s]*[ex]} != "One Three five"
Comparing "One Three five" != "One Three five"
CondParser_Eval: ${:U****************:M****************b}
+CondParser_Eval: ${:U..................................................b:M*?*?*?*?*?a}
CondParser_Eval: ${:Ua \$ sign:M*$$*} != "\$"
Comparing "$" != "$"
CondParser_Eval: ${:Ua \$ sign any-asterisk:M*\$*} != "any-asterisk"
Comparing "any-asterisk" != "any-asterisk"
-make: "varmod-match.mk" line 146: Unknown modifier "]"
-make: "varmod-match.mk" line 146: Malformed conditional (${ ${:U\:} ${:U\:\:} :L:M[:]} != ":")
+make: "varmod-match.mk" line 157: Unknown modifier "]"
+make: "varmod-match.mk" line 157: Malformed conditional (${ ${:U\:} ${:U\:\:} :L:M[:]} != ":")
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/varmod-match.mk b/unit-tests/varmod-match.mk
index adea273e530a..8435c2a614e0 100644
--- a/unit-tests/varmod-match.mk
+++ b/unit-tests/varmod-match.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-match.mk,v 1.8 2022/03/27 18:39:01 rillig Exp $
+# $NetBSD: varmod-match.mk,v 1.11 2022/06/11 09:15:49 rillig Exp $
#
# Tests for the :M variable modifier, which filters words that match the
# given pattern.
@@ -28,11 +28,16 @@ NUMBERS= One Two Three Four five six seven
. error
.endif
-# Before 2020-06-13, this expression took quite a long time in Str_Match,
-# calling itself 601080390 times for 16 asterisks.
+# Before 2020-06-13, this expression called Str_Match 601,080,390 times.
+# Since 2020-06-13, this expression calls Str_Match 1 time.
.if ${:U****************:M****************b}
.endif
+# As of 2022-06-11, this expression calls Str_Match 5,242,223 times.
+# Adding another '*?' to the pattern calls Str_Match 41,261,143 times.
+.if ${:U..................................................b:M*?*?*?*?*?a}
+.endif
+
# To match a dollar sign in a word, double it.
#
# This is different from the :S and :C variable modifiers, where a '$'
@@ -125,6 +130,12 @@ ${:U*}= asterisk
. error
.endif
+# [\] matches a single backslash
+WORDS= a\b a[\]b ab
+.if ${WORDS:Ma[\]b} != "a\\b"
+. error
+.endif
+
# : terminates the pattern
.if ${ A * :L:M:} != ""
. error
@@ -151,26 +162,95 @@ ${:U*}= asterisk
# [\] matches exactly a backslash; no escaping takes place in
# character ranges
-# Without the 'a' in the below expressions, the backslash would end a word and
-# thus influence how the string is split into words.
-.if ${ ${:U\\a} ${:U\\\\a} :L:M[\]a} != "\\a"
+# Without the 'a' in the below words, the backslash would end a word and thus
+# influence how the string is split into words.
+WORDS= 1\a 2\\a
+.if ${WORDS:M?[\]a} != "1\\a"
+. error
+.endif
+
+# [[-]] May look like it would match a single '[', '\' or ']', but
+# the inner ']' has two roles: it is the upper bound of the
+# character range as well as the closing character of the
+# character list. The outer ']' is just a regular character.
+WORDS= [ ] [] \] ]]
+.if ${WORDS:M[[-]]} != "[] \\] ]]"
+. error
+.endif
+
+# [b[-]a]
+# Same as for '[[-]]': the character list stops at the first
+# ']', and the 'a]' is treated as a literal string.
+WORDS= [a \a ]a []a \]a ]]a [a] \a] ]a] ba]
+.if ${WORDS:M[b[-]a]} != "[a] \\a] ]a] ba]"
+. error
+.endif
+
+# [-] Matches a single '-' since the '-' only becomes part of a
+# character range if it is preceded and followed by another
+# character.
+WORDS= - -]
+.if ${WORDS:M[-]} != "-"
+. error
+.endif
+
+# [ Incomplete empty character list, never matches.
+WORDS= a a[
+.if ${WORDS:Ma[} != ""
+. error
+.endif
+
+# [^ Incomplete negated empty character list, matches any single
+# character.
+WORDS= a a[ aX
+.if ${WORDS:Ma[^} != "a[ aX"
+. error
+.endif
+
+# [-x1-3 Incomplete character list, matches those elements that can be
+# parsed without lookahead.
+WORDS= - + x xx 0 1 2 3 4 [x1-3
+.if ${WORDS:M[-x1-3} != "- x 1 2 3"
+. error
+.endif
+
+# [^-x1-3
+# Incomplete negated character list, matches any character
+# except those elements that can be parsed without lookahead.
+WORDS= - + x xx 0 1 2 3 4 [x1-3
+.if ${WORDS:M[^-x1-3} != "+ 0 4"
. error
.endif
-#.MAKEFLAGS: -dcv
+# [\ Incomplete character list containing a single '\'.
#
-# Incomplete patterns:
-# [ matches TODO
-# [x matches TODO
-# [^ matches TODO
-# [- matches TODO
-# [xy matches TODO
-# [^x matches TODO
-# [\ matches TODO
+# A word can only end with a backslash if the preceding
+# character is a backslash as well; in all other cases the final
+# backslash would escape the following space, making the space
+# part of the word. Only the very last word of a string can be
+# '\', as there is no following space that could be escaped.
+WORDS= \\ \a ${:Ux\\}
+.if ${WORDS:M?[\]} != "\\\\ x\\"
+. error
+.endif
+
+# [x- Incomplete character list containing an incomplete character
+# range, matches only the 'x'.
+WORDS= [x- x x- y
+.if ${WORDS:M[x-} != "x"
+. error
+.endif
+
+# [^x- Incomplete negated character list containing an incomplete
+# character range; matches each word that does not have an 'x'
+# at the position of the character list.
#
-# [x- matches exactly 'x', doesn't match 'x-'
-# [^x- matches TODO
-# \ matches never
+# XXX: Even matches strings that are longer than a single
+# character.
+WORDS= [x- x x- y yyyyy
+.if ${WORDS:M[^x-} != "[x- y yyyyy"
+. error
+.endif
# The modifier ':tW' prevents splitting at whitespace. Even leading and
@@ -184,3 +264,19 @@ ${:U*}= asterisk
.if ${ plain string :L:M*} != "plain string"
. error
.endif
+
+
+# The pattern can come from a variable expression. For single-letter
+# variables, either the short form or the long form can be used, just as
+# everywhere else.
+PRIMES= 2 3 5 7 11
+n= 2
+.if ${PRIMES:M$n} != "2"
+. error
+.endif
+.if ${PRIMES:M${n}} != "2"
+. error
+.endif
+.if ${PRIMES:M${:U2}} != "2"
+. error
+.endif
diff --git a/unit-tests/varmod-quote-dollar.exp b/unit-tests/varmod-quote-dollar.exp
index 4346401c5a9d..f12b0280e6f7 100644
--- a/unit-tests/varmod-quote-dollar.exp
+++ b/unit-tests/varmod-quote-dollar.exp
@@ -1,2 +1,4 @@
!"#$$%&'()*+,-./09:;<=>?@AZ[\]^_`az{|}~
+!"#$$%&'()*+,-./09:;<=>?@AZ[\]^_`az{|}~
+ !"#$$%&'()*+,-./09:;<=>?@AZ[\]^_`az{|}~
exit status 0
diff --git a/unit-tests/varmod-quote-dollar.mk b/unit-tests/varmod-quote-dollar.mk
index 3316b04bed1e..8e68282c536d 100644
--- a/unit-tests/varmod-quote-dollar.mk
+++ b/unit-tests/varmod-quote-dollar.mk
@@ -1,10 +1,17 @@
-# $NetBSD: varmod-quote-dollar.mk,v 1.3 2022/01/22 17:10:51 rillig Exp $
+# $NetBSD: varmod-quote-dollar.mk,v 1.4 2022/05/08 10:14:40 rillig Exp $
#
# Tests for the :q variable modifier, which quotes the string for the shell
# and doubles dollar signs, to prevent them from being interpreted by a
# child process of make.
+# The newline and space characters at the beginning of this string are passed
+# to the child make. When the child make parses the variable assignment, it
+# discards the leading space characters.
ASCII_CHARS= ${.newline} !"\#$$%&'()*+,-./09:;<=>?@AZ[\]^_`az{|}~
all:
- @${MAKE} -r -f /dev/null CHARS=${ASCII_CHARS:q} -V CHARS
+ @${MAKE} -r -f /dev/null \
+ CHARS=${ASCII_CHARS:q} \
+ TWICE=${ASCII_CHARS:q}${ASCII_CHARS:q} \
+ -V CHARS \
+ -V TWICE
diff --git a/unit-tests/varname-dot-make-mode.exp b/unit-tests/varname-dot-make-mode.exp
index 39a9383953dd..fa033e718b0c 100644
--- a/unit-tests/varname-dot-make-mode.exp
+++ b/unit-tests/varname-dot-make-mode.exp
@@ -1 +1,31 @@
+randomize compat mode:
+: Making a
+: Making a
+: Making a
+: Making b
+: Making b
+: Making b
+: Making c
+: Making c
+: Making c
+randomize jobs mode (-j1):
+: Making a
+: Making a
+: Making a
+: Making b
+: Making b
+: Making b
+: Making c
+: Making c
+: Making c
+randomize jobs mode (-j5):
+: Making a
+: Making a
+: Making a
+: Making b
+: Making b
+: Making b
+: Making c
+: Making c
+: Making c
exit status 0
diff --git a/unit-tests/varname-dot-make-mode.mk b/unit-tests/varname-dot-make-mode.mk
index ee75a54ebd74..169aa17cdc36 100644
--- a/unit-tests/varname-dot-make-mode.mk
+++ b/unit-tests/varname-dot-make-mode.mk
@@ -1,8 +1,41 @@
-# $NetBSD: varname-dot-make-mode.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $
+# $NetBSD: varname-dot-make-mode.mk,v 1.3 2022/05/07 17:49:47 rillig Exp $
#
# Tests for the special .MAKE.MODE variable.
-# TODO: Implementation
+# TODO: test .MAKE.MODE "meta", or see meta mode tests.
+# TODO: test .MAKE.MODE "compat"
-all:
- @:;
+
+# See Makefile, POSTPROC for the postprocessing that takes place.
+# See the .rawout file for the raw output before stripping the digits.
+all: .PHONY make-mode-randomize-targets
+
+
+# By adding the word "randomize-targets" to the variable .MAKE.MODE, the
+# targets are not made in declaration order, but rather in random order. This
+# mode helps to find undeclared dependencies between files.
+#
+# History
+# Added on 2022-05-07.
+#
+# See also
+# https://gnats.netbsd.org/45226
+make-mode-randomize-targets: .PHONY
+ @echo "randomize compat mode:"
+ @${MAKE} -r -f ${MAKEFILE} randomize-targets
+
+ @echo "randomize jobs mode (-j1):"
+ @${MAKE} -r -f ${MAKEFILE} -j1 randomize-targets
+
+ @echo "randomize jobs mode (-j5):"
+ @${MAKE} -r -f ${MAKEFILE} -j5 randomize-targets | grep '^:'
+
+.if make(randomize-targets)
+randomize-targets: .WAIT a1 a2 a3 .WAIT b1 b2 b3 .WAIT c1 c2 c3 .WAIT
+a1 a2 a3 b1 b2 b3 c1 c2 c3:
+ : Making ${.TARGET}
+
+# .MAKE.MODE is evaluated after parsing all files, so it suffices to switch
+# the mode after defining the targets.
+.MAKE.MODE+= randomize-targets
+.endif
diff --git a/unit-tests/varquote.exp b/unit-tests/varquote.exp
deleted file mode 100644
index 63107bfd34f5..000000000000
--- a/unit-tests/varquote.exp
+++ /dev/null
@@ -1,3 +0,0 @@
--fdebug-prefix-map=$NETBSDSRCDIR=/usr/src -fdebug-regex-map=/usr/src/(.*)/obj$=/usr/obj/\1
--fdebug-prefix-map=$NETBSDSRCDIR=/usr/src -fdebug-regex-map=/usr/src/(.*)/obj$=/usr/obj/\1
-exit status 0
diff --git a/unit-tests/varquote.mk b/unit-tests/varquote.mk
deleted file mode 100644
index 3d5e8a7f32e9..000000000000
--- a/unit-tests/varquote.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-# $NetBSD: varquote.mk,v 1.5 2021/12/28 10:47:00 rillig Exp $
-#
-# Test VAR:q modifier
-
-.if !defined(REPROFLAGS)
-REPROFLAGS+= -fdebug-prefix-map=\$$NETBSDSRCDIR=/usr/src
-REPROFLAGS+= -fdebug-regex-map='/usr/src/(.*)/obj$$=/usr/obj/\1'
-all:
- @${MAKE} -f ${MAKEFILE} REPROFLAGS=${REPROFLAGS:S/\$/&&/g:Q}
- @${MAKE} -f ${MAKEFILE} REPROFLAGS=${REPROFLAGS:q}
-.else
-all:
- @printf "%s %s\n" ${REPROFLAGS}
-.endif
diff --git a/var.c b/var.c
index 6d015ff2661a..b5a063ed20a2 100644
--- a/var.c
+++ b/var.c
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.1019 2022/03/27 18:39:01 rillig Exp $ */
+/* $NetBSD: var.c,v 1.1025 2022/06/14 19:57:56 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -147,7 +147,7 @@
#include "metachar.h"
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.1019 2022/03/27 18:39:01 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.1025 2022/06/14 19:57:56 rillig Exp $");
/*
* Variables are defined using one of the VAR=value assignments. Their
@@ -460,7 +460,6 @@ VarFindSubstring(Substring name, GNode *scope, bool elsewhere)
return var;
}
-/* TODO: Replace these calls with VarFindSubstring, as far as possible. */
static Var *
VarFind(const char *name, GNode *scope, bool elsewhere)
{
@@ -4147,15 +4146,15 @@ ParseVarname(const char **pp, char startc, char endc,
*pp = p;
}
-static VarParseResult
-ValidShortVarname(char varname, const char *start)
+static bool
+IsShortVarnameValid(char varname, const char *start)
{
if (varname != '$' && varname != ':' && varname != '}' &&
varname != ')' && varname != '\0')
- return VPR_OK;
+ return true;
if (!opts.strict)
- return VPR_ERR; /* XXX: Missing error message */
+ return false; /* XXX: Missing error message */
if (varname == '$')
Parse_Error(PARSE_FATAL,
@@ -4166,7 +4165,7 @@ ValidShortVarname(char varname, const char *start)
Parse_Error(PARSE_FATAL,
"Invalid variable name '%c', at \"%s\"", varname, start);
- return VPR_ERR;
+ return false;
}
/*
@@ -4181,12 +4180,11 @@ ParseVarnameShort(char varname, const char **pp, GNode *scope,
{
char name[2];
Var *v;
- VarParseResult vpr;
+ const char *val;
- vpr = ValidShortVarname(varname, *pp);
- if (vpr != VPR_OK) {
- (*pp)++;
- *out_false_res = vpr;
+ if (!IsShortVarnameValid(varname, *pp)) {
+ (*pp)++; /* only skip the '$' */
+ *out_false_res = VPR_ERR;
*out_false_val = var_Error;
return false;
}
@@ -4194,41 +4192,39 @@ ParseVarnameShort(char varname, const char **pp, GNode *scope,
name[0] = varname;
name[1] = '\0';
v = VarFind(name, scope, true);
- if (v == NULL) {
- const char *val;
- *pp += 2;
+ if (v != NULL) {
+ /* No need to advance *pp, the calling code handles this. */
+ *out_true_var = v;
+ return true;
+ }
- val = UndefinedShortVarValue(varname, scope);
- if (val == NULL)
- val = emode == VARE_UNDEFERR
- ? var_Error : varUndefined;
+ *pp += 2;
- if (opts.strict && val == var_Error) {
- Parse_Error(PARSE_FATAL,
- "Variable \"%s\" is undefined", name);
- *out_false_res = VPR_ERR;
- *out_false_val = val;
- return false;
- }
+ val = UndefinedShortVarValue(varname, scope);
+ if (val == NULL)
+ val = emode == VARE_UNDEFERR ? var_Error : varUndefined;
- /*
- * XXX: This looks completely wrong.
- *
- * If undefined expressions are not allowed, this should
- * rather be VPR_ERR instead of VPR_UNDEF, together with an
- * error message.
- *
- * If undefined expressions are allowed, this should rather
- * be VPR_UNDEF instead of VPR_OK.
- */
- *out_false_res = emode == VARE_UNDEFERR
- ? VPR_UNDEF : VPR_OK;
+ if (opts.strict && val == var_Error) {
+ Parse_Error(PARSE_FATAL,
+ "Variable \"%s\" is undefined", name);
+ *out_false_res = VPR_ERR;
*out_false_val = val;
return false;
}
- *out_true_var = v;
- return true;
+ /*
+ * XXX: This looks completely wrong.
+ *
+ * If undefined expressions are not allowed, this should
+ * rather be VPR_ERR instead of VPR_UNDEF, together with an
+ * error message.
+ *
+ * If undefined expressions are allowed, this should rather
+ * be VPR_UNDEF instead of VPR_OK.
+ */
+ *out_false_res = emode == VARE_UNDEFERR ? VPR_UNDEF : VPR_OK;
+ *out_false_val = val;
+ return false;
}
/* Find variables like @F or <D. */
@@ -4453,9 +4449,8 @@ Var_Parse_FastLane(const char **pp, VarEvalMode emode, FStr *out_value)
*
* Input:
* *pp The string to parse.
- * In CondParser_FuncCallEmpty, it may also point to the
- * "y" of "empty(VARNAME:Modifiers)", which is
- * syntactically the same.
+ * When called from CondParser_FuncCallEmpty, it can
+ * also point to the "y" of "empty(VARNAME:Modifiers)".
* scope The scope for finding variables
* emode Controls the exact details of parsing and evaluation
*
@@ -4486,16 +4481,14 @@ Var_Parse(const char **pp, GNode *scope, VarEvalMode emode, FStr *out_val)
{
const char *p = *pp;
const char *const start = p;
- /* true if have modifiers for the variable. */
- bool haveModifier;
- /* Starting character if variable in parens or braces. */
- char startc;
- /* Ending character if variable in parens or braces. */
- char endc;
+ bool haveModifier; /* true for ${VAR:...}, false for ${VAR} */
+ char startc; /* the actual '{' or '(' or '\0' */
+ char endc; /* the expected '}' or ')' or '\0' */
/*
- * true if the variable is local and we're expanding it in a
- * non-local scope. This is done to support dynamic sources.
- * The result is just the expression, unaltered.
+ * true if the expression is based on one of the 7 predefined
+ * variables that are local to a target, and the expression is
+ * expanded in a non-local scope. The result is the text of the
+ * expression, unaltered. This is needed to support dynamic sources.
*/
bool dynamic;
const char *extramodifiers;
@@ -4512,11 +4505,7 @@ Var_Parse(const char **pp, GNode *scope, VarEvalMode emode, FStr *out_val)
extramodifiers = NULL; /* extra modifiers to apply first */
dynamic = false;
- /*
- * Appease GCC, which thinks that the variable might not be
- * initialized.
- */
- endc = '\0';
+ endc = '\0'; /* Appease GCC. */
startc = p[1];
if (startc != '(' && startc != '{') {
@@ -4539,8 +4528,7 @@ Var_Parse(const char **pp, GNode *scope, VarEvalMode emode, FStr *out_val)
if (v->inUse) {
if (scope->fname != NULL) {
fprintf(stderr, "In a command near ");
- PrintLocation(stderr, false,
- scope->fname, scope->lineno);
+ PrintLocation(stderr, false, scope);
}
Fatal("Variable %s is recursive.", v->name.str);
}
@@ -4549,7 +4537,9 @@ Var_Parse(const char **pp, GNode *scope, VarEvalMode emode, FStr *out_val)
* XXX: This assignment creates an alias to the current value of the
* variable. This means that as long as the value of the expression
* stays the same, the value of the variable must not change.
- * Using the '::=' modifier, it could be possible to do exactly this.
+ * Using the '::=' modifier, it could be possible to trigger exactly
+ * this situation.
+ *
* At the bottom of this function, the resulting value is compared to
* the then-current value of the variable. This might also invoke
* undefined behavior.