Update to bmake-20220724
Merge commit '308a28d6cd2e87028e535eabccb89a9dc2fd9515'
This commit is contained in:
commit
954401e68e
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,2 +1,2 @@
|
||||
# keep this compatible with sh and make
|
||||
_MAKE_VERSION=20220418
|
||||
_MAKE_VERSION=20220724
|
||||
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 85 KiB |
@ -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;
|
||||
@ -466,14 +461,66 @@ 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;
|
||||
|
||||
|
@ -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 *
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
@ -2346,7 +2346,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();
|
||||
}
|
||||
|
@ -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. */
|
||||
|
@ -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.
|
||||
@ -850,7 +860,7 @@ for backwards compatability with
|
||||
and earlier.
|
||||
.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
|
||||
@ -871,17 +881,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.
|
||||
@ -892,7 +903,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
|
||||
@ -900,7 +911,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
|
||||
@ -919,8 +930,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.
|
||||
@ -955,7 +966,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.
|
||||
@ -989,6 +1000,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
|
||||
@ -1018,7 +1033,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.
|
||||
@ -1032,16 +1047,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
|
||||
@ -1079,21 +1094,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
|
||||
@ -1101,7 +1116,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.
|
||||
@ -1113,13 +1128,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}
|
||||
@ -1136,77 +1151,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.
|
||||
@ -1226,7 +1241,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
|
||||
@ -1260,14 +1275,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
|
||||
@ -1279,9 +1294,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
|
||||
@ -1304,7 +1319,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
|
||||
@ -1338,11 +1353,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
|
||||
@ -1352,7 +1367,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
|
||||
@ -1380,14 +1395,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
|
||||
@ -1442,7 +1457,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
|
||||
@ -1487,7 +1502,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
|
||||
@ -1502,7 +1517,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.
|
||||
@ -1555,7 +1570,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.
|
||||
@ -1574,7 +1589,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
|
||||
@ -1595,7 +1610,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.
|
||||
@ -1605,7 +1620,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.
|
||||
@ -1619,7 +1634,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
|
||||
@ -1641,7 +1656,7 @@ preceded with something to keep
|
||||
happy.
|
||||
.Pp
|
||||
The
|
||||
.Ql Cm \&::
|
||||
.Sq Cm \&::
|
||||
helps avoid false matches with the
|
||||
.At V
|
||||
style
|
||||
@ -1674,7 +1689,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
|
||||
@ -1696,7 +1711,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
|
||||
@ -1704,13 +1719,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
|
||||
@ -1721,7 +1736,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
|
||||
@ -1848,14 +1863,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.
|
||||
@ -1871,29 +1886,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
|
||||
@ -1917,11 +1932,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
|
||||
@ -1963,9 +1978,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.
|
||||
@ -1982,17 +1997,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.
|
||||
@ -2001,9 +2016,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.
|
||||
@ -2254,16 +2269,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
|
||||
@ -2274,9 +2290,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.
|
||||
@ -2420,7 +2433,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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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'; \
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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);
|
||||
|
||||
while (!Lst_IsEmpty(&targetNames)) {
|
||||
char *targName = Lst_Dequeue(&targetNames);
|
||||
HandleSingleDependencyTargetMundane(targName);
|
||||
free(targName);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
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.
|
||||
*/
|
||||
if (fullname == NULL && !isSystem)
|
||||
fullname = FindInQuotPath(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 ((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);
|
||||
|
||||
|
@ -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;
|
||||
@ -292,55 +292,57 @@ Str_Words(const char *str, bool expand)
|
||||
return words;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
if (*str == '\0')
|
||||
return false;
|
||||
|
||||
/*
|
||||
* 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 (*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
|
||||
|
@ -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:,'
|
||||
|
@ -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
|
||||
|
@ -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,$$,$$,'
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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}"
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
: $@
|
||||
|
@ -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
|
||||
|
||||
|
@ -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} \
|
||||
|
27
contrib/bmake/unit-tests/directive-for-empty.exp
Normal file
27
contrib/bmake/unit-tests/directive-for-empty.exp
Normal file
@ -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
|
120
contrib/bmake/unit-tests/directive-for-empty.mk
Normal file
120
contrib/bmake/unit-tests/directive-for-empty.mk
Normal file
@ -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.
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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 -
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 ...
|
||||
|
@ -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
|
||||
|
@ -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: \
|
||||
|
@ -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
|
||||
|
@ -1 +1,5 @@
|
||||
ordinary:
|
||||
BEFORE=before
|
||||
submake:
|
||||
BEFORE=before
|
||||
exit status 0
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
#.MAKEFLAGS: -dcv
|
||||
# [[-]] 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
|
||||
|
||||
# [\ 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
|
||||
|
@ -1,2 +1,4 @@
|
||||
!"#$$%&'()*+,-./09:;<=>?@AZ[\]^_`az{|}~
|
||||
!"#$$%&'()*+,-./09:;<=>?@AZ[\]^_`az{|}~
|
||||
!"#$$%&'()*+,-./09:;<=>?@AZ[\]^_`az{|}~
|
||||
exit status 0
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user