mirror of
https://git.FreeBSD.org/src.git
synced 2024-10-18 02:19:39 +00:00
Merge bmake-20230414
Merge commit '51d8a8b4ac1dd7265e891149e470a803906de2a7'
This commit is contained in:
commit
8c973ee23d
@ -1,3 +1,55 @@
|
||||
2023-04-14 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20230414
|
||||
Merge with NetBSD make, pick up
|
||||
o minor cleanup
|
||||
|
||||
2023-03-25 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* main.c: on some systems (eg OS/X) setting RLIMIT_NOFILE to
|
||||
unlimited results in an insane number (0x7fffffffffffffff).
|
||||
If BMAKE_NOFILE_MAX is defined, use that instead.
|
||||
|
||||
2023-03-22 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20230321
|
||||
Merge with NetBSD make, pick up
|
||||
* make.1: document seemingly unexplained Error code 6.
|
||||
|
||||
2023-03-18 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20230317
|
||||
Merge with NetBSD make, pick up
|
||||
o compat.c: CompatDeleteTarget skip .PHONY targets to be
|
||||
consistent with JobDeleteTarget.
|
||||
o job.c: fix memory leak in handling sysv :from=to modifiers
|
||||
|
||||
2023-03-04 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20230303
|
||||
Merge with NetBSD make, pick up
|
||||
o several updated unit-tests
|
||||
|
||||
2023-02-22 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20230222
|
||||
Merge with NetBSD make, pick up
|
||||
o unit tests for .MAKE.META.IGNORE_{FILTER,PATHS,PATTERNS}
|
||||
|
||||
2023-02-20 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20230218
|
||||
Merge with NetBSD make, pick up
|
||||
o var.c: fix parsing of unevaluated subexpressions with
|
||||
unbalanced '{}'
|
||||
|
||||
2023-02-17 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20230215
|
||||
Merge with NetBSD make, pick up
|
||||
o inline macros for some variable names
|
||||
o cond.c: reduce complexity of evaluating expressions
|
||||
|
||||
2023-02-08 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* VERSION (_MAKE_VERSION): 20230208
|
||||
|
@ -428,6 +428,7 @@ unit-tests/make-exported.exp
|
||||
unit-tests/make-exported.mk
|
||||
unit-tests/meta-cmd-cmp.exp
|
||||
unit-tests/meta-cmd-cmp.mk
|
||||
unit-tests/meta-ignore.inc
|
||||
unit-tests/moderrs.exp
|
||||
unit-tests/moderrs.mk
|
||||
unit-tests/modmatch.exp
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: Makefile,v 1.123 2023/01/28 02:49:20 sjg Exp $
|
||||
# $Id: Makefile,v 1.124 2023/02/25 20:27:44 sjg Exp $
|
||||
|
||||
PROG= bmake
|
||||
|
||||
@ -176,9 +176,7 @@ SHAREDIR= ${SHAREDIR.bmake:U${prefix}/share}
|
||||
BINDIR= ${BINDIR.bmake:U${prefix}/bin}
|
||||
MANDIR= ${MANDIR.bmake:U${SHAREDIR}/man}
|
||||
|
||||
.if !exists(.depend)
|
||||
${OBJS}: config.h
|
||||
.endif
|
||||
|
||||
# start-delete2 for bsd.after-import.mk
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
# keep this compatible with sh and make
|
||||
_MAKE_VERSION=20230208
|
||||
_MAKE_VERSION=20230414
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: arch.c,v 1.212 2022/12/07 10:28:48 rillig Exp $ */
|
||||
/* $NetBSD: arch.c,v 1.213 2023/02/14 21:08:00 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -147,7 +147,7 @@ struct ar_hdr {
|
||||
#include "dir.h"
|
||||
|
||||
/* "@(#)arch.c 8.2 (Berkeley) 1/2/94" */
|
||||
MAKE_RCSID("$NetBSD: arch.c,v 1.212 2022/12/07 10:28:48 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: arch.c,v 1.213 2023/02/14 21:08:00 rillig Exp $");
|
||||
|
||||
typedef struct List ArchList;
|
||||
typedef struct ListNode ArchListNode;
|
||||
@ -269,8 +269,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
bool isError;
|
||||
|
||||
/* XXX: is expanded twice: once here and once below */
|
||||
(void)Var_Parse(&nested_p, scope,
|
||||
VARE_UNDEFERR, &result);
|
||||
result = Var_Parse(&nested_p, scope, VARE_UNDEFERR);
|
||||
/* TODO: handle errors */
|
||||
isError = result.str == var_Error;
|
||||
FStr_Done(&result);
|
||||
@ -308,8 +307,8 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
|
||||
bool isError;
|
||||
const char *nested_p = cp;
|
||||
|
||||
(void)Var_Parse(&nested_p, scope,
|
||||
VARE_UNDEFERR, &result);
|
||||
result = Var_Parse(&nested_p, scope,
|
||||
VARE_UNDEFERR);
|
||||
/* TODO: handle errors */
|
||||
isError = result.str == var_Error;
|
||||
FStr_Done(&result);
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: make.1,v 1.360 2023/01/26 20:48:17 sjg Exp $
|
||||
.\" $NetBSD: make.1,v 1.361 2023/03/23 03:29:28 sjg 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 January 26, 2023
|
||||
.Dd March 22, 2023
|
||||
.Dt BMAKE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -267,7 +267,9 @@ cooperate to avoid overloading the system.
|
||||
Specify the maximum number of jobs that
|
||||
.Nm
|
||||
may have running at any one time.
|
||||
The value is saved in
|
||||
The value of
|
||||
.Ar max_jobs
|
||||
is saved in
|
||||
.Va .MAKE.JOBS .
|
||||
Turns compatibility mode off, unless the
|
||||
.Fl B
|
||||
@ -280,6 +282,13 @@ command invocation and then expect to start with a fresh environment
|
||||
on the next line.
|
||||
It is more efficient to correct the scripts rather than turn backwards
|
||||
compatibility on.
|
||||
.Pp
|
||||
A job token pool with
|
||||
.Ar max_jobs
|
||||
tokens is used to control the total number of jobs running.
|
||||
Each instance of
|
||||
.Nm
|
||||
will wait for a token from the pool before running a new job.
|
||||
.It Fl k
|
||||
Continue processing after errors are encountered, but only on those targets
|
||||
that do not depend on the target whose creation caused the error.
|
||||
@ -2716,3 +2725,15 @@ make
|
||||
just counts {} and () in order to find the end of a variable expansion.
|
||||
.Pp
|
||||
There is no way of escaping a space character in a filename.
|
||||
.Pp
|
||||
In jobs mode, when a target fails;
|
||||
make
|
||||
will put an error token into the job token pool.
|
||||
This will cause all other instances of
|
||||
make
|
||||
using that token pool to abort the build and exit with error code 6.
|
||||
Sometimes the attempt to suppress a cascade of unnecessary errors,
|
||||
can result in a seemingly unexplained
|
||||
.Ql *** Error code 6
|
||||
|
||||
|
||||
|
@ -157,15 +157,19 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
|
||||
|
||||
[1m-j [4m[22mmax_jobs[0m
|
||||
Specify the maximum number of jobs that [1mbmake [22mmay have running at
|
||||
any one time. The value is saved in [4m.MAKE.JOBS[24m. Turns compati-
|
||||
bility mode off, unless the [1m-B [22moption is also specified. When
|
||||
compatibility mode is off, all commands associated with a target
|
||||
are executed in a single shell invocation as opposed to the tra-
|
||||
ditional one shell invocation per line. This can break tradi-
|
||||
tional scripts which change directories on each command invoca-
|
||||
tion and then expect to start with a fresh environment on the
|
||||
next line. It is more efficient to correct the scripts rather
|
||||
than turn backwards compatibility on.
|
||||
any one time. The value of [4mmax_jobs[24m is saved in [4m.MAKE.JOBS[24m.
|
||||
Turns compatibility mode off, unless the [1m-B [22moption is also speci-
|
||||
fied. When compatibility mode is off, all commands associated
|
||||
with a target are executed in a single shell invocation as op-
|
||||
posed to the traditional one shell invocation per line. This can
|
||||
break traditional scripts which change directories on each com-
|
||||
mand invocation and then expect to start with a fresh environment
|
||||
on the next line. It is more efficient to correct the scripts
|
||||
rather than turn backwards compatibility on.
|
||||
|
||||
A job token pool with [4mmax_jobs[24m tokens is used to control the to-
|
||||
tal number of jobs running. Each instance of [1mbmake [22mwill wait for
|
||||
a token from the pool before running a new job.
|
||||
|
||||
[1m-k [22mContinue processing after errors are encountered, but only on
|
||||
those targets that do not depend on the target whose creation
|
||||
@ -1740,4 +1744,12 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
|
||||
|
||||
There is no way of escaping a space character in a filename.
|
||||
|
||||
FreeBSD 13.0 January 26, 2023 FreeBSD 13.0
|
||||
In jobs mode, when a target fails; make will put an error token into the
|
||||
job token pool. This will cause all other instances of make using that
|
||||
token pool to abort the build and exit with error code 6. Sometimes the
|
||||
attempt to suppress a cascade of unnecessary errors, can result in a
|
||||
seemingly unexplained `*** Error code 6'
|
||||
|
||||
|
||||
|
||||
FreeBSD 13.0 March 22, 2023 FreeBSD 13.0
|
||||
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 85 KiB |
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: compat.c,v 1.244 2023/01/17 21:35:19 christos Exp $ */
|
||||
/* $NetBSD: compat.c,v 1.246 2023/03/18 22:20:11 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@ -94,7 +94,7 @@
|
||||
#include "pathnames.h"
|
||||
|
||||
/* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */
|
||||
MAKE_RCSID("$NetBSD: compat.c,v 1.244 2023/01/17 21:35:19 christos Exp $");
|
||||
MAKE_RCSID("$NetBSD: compat.c,v 1.246 2023/03/18 22:20:11 sjg Exp $");
|
||||
|
||||
static GNode *curTarg = NULL;
|
||||
static pid_t compatChild;
|
||||
@ -107,7 +107,8 @@ static int compatSigno;
|
||||
static void
|
||||
CompatDeleteTarget(GNode *gn)
|
||||
{
|
||||
if (gn != NULL && !GNode_IsPrecious(gn)) {
|
||||
if (gn != NULL && !GNode_IsPrecious(gn) &&
|
||||
(gn->type & OP_PHONY) == 0) {
|
||||
const char *file = GNode_VarTarget(gn);
|
||||
|
||||
if (!opts.noExecute && unlink_file(file) == 0) {
|
||||
@ -241,7 +242,7 @@ Compat_RunCommand(const char *cmdp, GNode *gn, StringListNode *ln)
|
||||
errCheck = !(gn->type & OP_IGNORE);
|
||||
doIt = false;
|
||||
|
||||
(void)Var_Subst(cmd, gn, VARE_WANTRES, &cmdStart);
|
||||
cmdStart = Var_Subst(cmd, gn, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
|
||||
if (cmdStart[0] == '\0') {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cond.c,v 1.342 2022/09/24 16:13:48 rillig Exp $ */
|
||||
/* $NetBSD: cond.c,v 1.344 2023/02/14 21:08:00 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||
@ -92,7 +92,7 @@
|
||||
#include "dir.h"
|
||||
|
||||
/* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */
|
||||
MAKE_RCSID("$NetBSD: cond.c,v 1.342 2022/09/24 16:13:48 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: cond.c,v 1.344 2023/02/14 21:08:00 rillig Exp $");
|
||||
|
||||
/*
|
||||
* Conditional expressions conform to this grammar:
|
||||
@ -235,8 +235,7 @@ ParseWord(const char **pp, bool doEval)
|
||||
VarEvalMode emode = doEval
|
||||
? VARE_UNDEFERR
|
||||
: VARE_PARSE_ONLY;
|
||||
FStr nestedVal;
|
||||
(void)Var_Parse(&p, SCOPE_CMDLINE, emode, &nestedVal);
|
||||
FStr nestedVal = Var_Parse(&p, SCOPE_CMDLINE, emode);
|
||||
/* TODO: handle errors */
|
||||
Buf_AddStr(&word, nestedVal.str);
|
||||
FStr_Done(&nestedVal);
|
||||
@ -380,7 +379,9 @@ is_separator(char ch)
|
||||
|
||||
/*
|
||||
* In a quoted or unquoted string literal or a number, parse a variable
|
||||
* expression.
|
||||
* expression and add its value to the buffer.
|
||||
*
|
||||
* Return whether to continue parsing the leaf.
|
||||
*
|
||||
* Example: .if x${CENTER}y == "${PREFIX}${SUFFIX}" || 0x${HEX}
|
||||
*/
|
||||
@ -392,7 +393,6 @@ CondParser_StringExpr(CondParser *par, const char *start,
|
||||
VarEvalMode emode;
|
||||
const char *p;
|
||||
bool atStart;
|
||||
VarParseResult parseResult;
|
||||
|
||||
emode = doEval && quoted ? VARE_WANTRES
|
||||
: doEval ? VARE_UNDEFERR
|
||||
@ -400,27 +400,10 @@ CondParser_StringExpr(CondParser *par, const char *start,
|
||||
|
||||
p = par->p;
|
||||
atStart = p == start;
|
||||
parseResult = Var_Parse(&p, SCOPE_CMDLINE, emode, inout_str);
|
||||
*inout_str = Var_Parse(&p, SCOPE_CMDLINE, emode);
|
||||
/* TODO: handle errors */
|
||||
if (inout_str->str == var_Error) {
|
||||
if (parseResult == VPR_ERR) {
|
||||
/*
|
||||
* FIXME: Even if an error occurs, there is no
|
||||
* guarantee that it is reported.
|
||||
*
|
||||
* See cond-token-plain.mk $$$$$$$$.
|
||||
*/
|
||||
par->printedError = true;
|
||||
}
|
||||
/*
|
||||
* XXX: Can there be any situation in which a returned
|
||||
* var_Error needs to be freed?
|
||||
*/
|
||||
FStr_Done(inout_str);
|
||||
/*
|
||||
* Even if !doEval, we still report syntax errors, which is
|
||||
* what getting var_Error back with !doEval means.
|
||||
*/
|
||||
*inout_str = FStr_InitRefer(NULL);
|
||||
return false;
|
||||
}
|
||||
@ -428,8 +411,8 @@ CondParser_StringExpr(CondParser *par, const char *start,
|
||||
|
||||
/*
|
||||
* If the '$' started the string literal (which means no quotes), and
|
||||
* the variable expression is followed by a space, looks like a
|
||||
* comparison operator or is the end of the expression, we are done.
|
||||
* the expression is followed by a space, a comparison operator or
|
||||
* the end of the expression, we are done.
|
||||
*/
|
||||
if (atStart && is_separator(par->p[0]))
|
||||
return false;
|
||||
@ -691,8 +674,8 @@ CondParser_FuncCallEmpty(CondParser *par, bool doEval, Token *out_token)
|
||||
return false;
|
||||
|
||||
cp--; /* Make cp[1] point to the '('. */
|
||||
(void)Var_Parse(&cp, SCOPE_CMDLINE,
|
||||
doEval ? VARE_WANTRES : VARE_PARSE_ONLY, &val);
|
||||
val = Var_Parse(&cp, SCOPE_CMDLINE,
|
||||
doEval ? VARE_WANTRES : VARE_PARSE_ONLY);
|
||||
/* TODO: handle errors */
|
||||
|
||||
if (val.str == var_Error)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: for.c,v 1.170 2022/09/03 00:50:07 rillig Exp $ */
|
||||
/* $NetBSD: for.c,v 1.171 2023/02/14 21:38:31 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.170 2022/09/03 00:50:07 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: for.c,v 1.171 2023/02/14 21:38:31 rillig Exp $");
|
||||
|
||||
|
||||
typedef struct ForLoop {
|
||||
@ -168,7 +168,9 @@ ForLoop_ParseItems(ForLoop *f, const char *p)
|
||||
|
||||
cpp_skip_whitespace(&p);
|
||||
|
||||
if (Var_Subst(p, SCOPE_GLOBAL, VARE_WANTRES, &items) != VPR_OK) {
|
||||
items = Var_Subst(p, SCOPE_GLOBAL, VARE_WANTRES);
|
||||
if (items == var_Error) {
|
||||
/* TODO: Make this part of the code reachable. */
|
||||
Parse_Error(PARSE_FATAL, "Error in .for loop items");
|
||||
return false;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: job.c,v 1.457 2023/01/17 21:35:19 christos Exp $ */
|
||||
/* $NetBSD: job.c,v 1.459 2023/02/15 06:52:58 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.457 2023/01/17 21:35:19 christos Exp $");
|
||||
MAKE_RCSID("$NetBSD: job.c,v 1.459 2023/02/15 06:52:58 rillig Exp $");
|
||||
|
||||
/*
|
||||
* A shell defines how the commands are run. All commands for a target are
|
||||
@ -940,7 +940,7 @@ JobWriteCommand(Job *job, ShellWriter *wr, StringListNode *ln, const char *ucmd)
|
||||
|
||||
run = GNode_ShouldExecute(job->node);
|
||||
|
||||
(void)Var_Subst(ucmd, job->node, VARE_WANTRES, &xcmd);
|
||||
xcmd = Var_Subst(ucmd, job->node, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
xcmdStart = xcmd;
|
||||
|
||||
@ -1069,7 +1069,7 @@ JobSaveCommands(Job *job)
|
||||
* variables such as .TARGET, .IMPSRC. It is not intended to
|
||||
* expand the other variables as well; see deptgt-end.mk.
|
||||
*/
|
||||
(void)Var_Subst(cmd, job->node, VARE_WANTRES, &expanded_cmd);
|
||||
expanded_cmd = Var_Subst(cmd, job->node, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
Lst_Append(&Targ_GetEndNode()->commands, expanded_cmd);
|
||||
}
|
||||
@ -1105,8 +1105,7 @@ DebugFailedJob(const Job *job)
|
||||
debug_printf("\t%s\n", cmd);
|
||||
|
||||
if (strchr(cmd, '$') != NULL) {
|
||||
char *xcmd;
|
||||
(void)Var_Subst(cmd, job->node, VARE_WANTRES, &xcmd);
|
||||
char *xcmd = Var_Subst(cmd, job->node, VARE_WANTRES);
|
||||
debug_printf("\t=> %s\n", xcmd);
|
||||
free(xcmd);
|
||||
}
|
||||
@ -2232,12 +2231,12 @@ Job_SetPrefix(void)
|
||||
{
|
||||
if (targPrefix != NULL) {
|
||||
free(targPrefix);
|
||||
} else if (!Var_Exists(SCOPE_GLOBAL, MAKE_JOB_PREFIX)) {
|
||||
Global_Set(MAKE_JOB_PREFIX, "---");
|
||||
} else if (!Var_Exists(SCOPE_GLOBAL, ".MAKE.JOB.PREFIX")) {
|
||||
Global_Set(".MAKE.JOB.PREFIX", "---");
|
||||
}
|
||||
|
||||
(void)Var_Subst("${" MAKE_JOB_PREFIX "}",
|
||||
SCOPE_GLOBAL, VARE_WANTRES, &targPrefix);
|
||||
targPrefix = Var_Subst("${.MAKE.JOB.PREFIX}",
|
||||
SCOPE_GLOBAL, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: main.c,v 1.589 2023/01/26 20:48:17 sjg Exp $ */
|
||||
/* $NetBSD: main.c,v 1.593 2023/03/28 14:39:31 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.589 2023/01/26 20:48:17 sjg Exp $");
|
||||
MAKE_RCSID("$NetBSD: main.c,v 1.593 2023/03/28 14:39:31 rillig Exp $");
|
||||
#if defined(MAKE_NATIVE) && !defined(lint)
|
||||
__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
|
||||
"The Regents of the University of California. "
|
||||
@ -129,7 +129,7 @@ bool allPrecious; /* .PRECIOUS given on line by itself */
|
||||
bool deleteOnError; /* .DELETE_ON_ERROR: set */
|
||||
|
||||
static int maxJobTokens; /* -j argument */
|
||||
bool enterFlagObj; /* -w and objdir != srcdir */
|
||||
static bool enterFlagObj; /* -w and objdir != srcdir */
|
||||
|
||||
static int jp_0 = -1, jp_1 = -1; /* ends of parent job pipe */
|
||||
bool doing_depend; /* Set while reading .depend */
|
||||
@ -436,7 +436,7 @@ MainParseArgSysInc(const char *argvalue)
|
||||
}
|
||||
|
||||
static bool
|
||||
MainParseArg(char c, const char *argvalue)
|
||||
MainParseOption(char c, const char *argvalue)
|
||||
{
|
||||
switch (c) {
|
||||
case '\0':
|
||||
@ -444,7 +444,7 @@ MainParseArg(char c, const char *argvalue)
|
||||
case 'B':
|
||||
opts.compatMake = true;
|
||||
Global_Append(MAKEFLAGS, "-B");
|
||||
Global_Set(MAKE_MODE, "compat");
|
||||
Global_Set(".MAKE.MODE", "compat");
|
||||
break;
|
||||
case 'C':
|
||||
MainParseArgChdir(argvalue);
|
||||
@ -628,7 +628,7 @@ MainParseArgs(int argc, char **argv)
|
||||
dashDash = true;
|
||||
break;
|
||||
default:
|
||||
if (!MainParseArg(c, argvalue))
|
||||
if (!MainParseOption(c, argvalue))
|
||||
goto noarg;
|
||||
}
|
||||
argv += arginc;
|
||||
@ -806,9 +806,8 @@ siginfo(int signo MAKE_ATTR_UNUSED)
|
||||
static void
|
||||
MakeMode(void)
|
||||
{
|
||||
char *mode;
|
||||
|
||||
(void)Var_Subst("${" MAKE_MODE ":tl}", SCOPE_GLOBAL, VARE_WANTRES, &mode);
|
||||
char *mode = Var_Subst("${.MAKE.MODE:tl}",
|
||||
SCOPE_GLOBAL, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
|
||||
if (mode[0] != '\0') {
|
||||
@ -831,16 +830,14 @@ static void
|
||||
PrintVar(const char *varname, bool expandVars)
|
||||
{
|
||||
if (strchr(varname, '$') != NULL) {
|
||||
char *evalue;
|
||||
(void)Var_Subst(varname, SCOPE_GLOBAL, VARE_WANTRES, &evalue);
|
||||
char *evalue = Var_Subst(varname, SCOPE_GLOBAL, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
printf("%s\n", evalue);
|
||||
free(evalue);
|
||||
|
||||
} else if (expandVars) {
|
||||
char *expr = str_concat3("${", varname, "}");
|
||||
char *evalue;
|
||||
(void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &evalue);
|
||||
char *evalue = Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
free(expr);
|
||||
printf("%s\n", evalue);
|
||||
@ -866,7 +863,7 @@ GetBooleanExpr(const char *expr, bool fallback)
|
||||
char *value;
|
||||
bool res;
|
||||
|
||||
(void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &value);
|
||||
value = Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
res = ParseBoolean(value, fallback);
|
||||
free(value);
|
||||
@ -1098,6 +1095,11 @@ UnlimitFiles(void)
|
||||
struct rlimit rl;
|
||||
if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
|
||||
rl.rlim_cur != rl.rlim_max) {
|
||||
#ifdef BMAKE_NOFILE_MAX
|
||||
if (BMAKE_NOFILE_MAX < rl.rlim_max)
|
||||
rl.rlim_cur = BMAKE_NOFILE_MAX;
|
||||
else
|
||||
#endif
|
||||
rl.rlim_cur = rl.rlim_max;
|
||||
(void)setrlimit(RLIMIT_NOFILE, &rl);
|
||||
}
|
||||
@ -1232,7 +1234,7 @@ InitMaxJobs(void)
|
||||
!Var_Exists(SCOPE_GLOBAL, ".MAKE.JOBS"))
|
||||
return;
|
||||
|
||||
(void)Var_Subst("${.MAKE.JOBS}", SCOPE_GLOBAL, VARE_WANTRES, &value);
|
||||
value = Var_Subst("${.MAKE.JOBS}", SCOPE_GLOBAL, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
n = (int)strtol(value, NULL, 0);
|
||||
if (n < 1) {
|
||||
@ -1267,7 +1269,7 @@ InitVpath(void)
|
||||
if (!Var_Exists(SCOPE_CMDLINE, "VPATH"))
|
||||
return;
|
||||
|
||||
(void)Var_Subst("${VPATH}", SCOPE_CMDLINE, VARE_WANTRES, &vpath);
|
||||
vpath = Var_Subst("${VPATH}", SCOPE_CMDLINE, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
path = vpath;
|
||||
do {
|
||||
@ -1303,10 +1305,8 @@ ReadFirstDefaultMakefile(void)
|
||||
{
|
||||
StringList makefiles = LST_INIT;
|
||||
StringListNode *ln;
|
||||
char *prefs;
|
||||
|
||||
(void)Var_Subst("${" MAKE_MAKEFILE_PREFERENCE "}",
|
||||
SCOPE_CMDLINE, VARE_WANTRES, &prefs);
|
||||
char *prefs = Var_Subst("${.MAKE.MAKEFILE_PREFERENCE}",
|
||||
SCOPE_CMDLINE, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
|
||||
(void)str2Lst_Append(&makefiles, prefs);
|
||||
@ -1384,7 +1384,7 @@ main_Init(int argc, char **argv)
|
||||
/* This is the traditional preference for makefiles. */
|
||||
# define MAKEFILE_PREFERENCE_LIST "makefile Makefile"
|
||||
#endif
|
||||
Global_Set(MAKE_MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST);
|
||||
Global_Set(".MAKE.MAKEFILE_PREFERENCE", MAKEFILE_PREFERENCE_LIST);
|
||||
Global_Set(".MAKE.DEPENDFILE", ".depend");
|
||||
|
||||
CmdOpts_Init();
|
||||
@ -1410,7 +1410,7 @@ main_Init(int argc, char **argv)
|
||||
Parse_Init();
|
||||
InitVarMake(argv[0]);
|
||||
Global_Set(MAKEFLAGS, "");
|
||||
Global_Set(MAKEOVERRIDES, "");
|
||||
Global_Set(".MAKEOVERRIDES", "");
|
||||
Global_Set("MFLAGS", "");
|
||||
Global_Set(".ALLTARGETS", "");
|
||||
Var_Set(SCOPE_CMDLINE, ".MAKE.LEVEL.ENV", MAKE_LEVEL_ENV);
|
||||
@ -1423,7 +1423,7 @@ main_Init(int argc, char **argv)
|
||||
if (makelevel < 0)
|
||||
makelevel = 0;
|
||||
snprintf(buf, sizeof buf, "%d", makelevel);
|
||||
Global_Set(MAKE_LEVEL, buf);
|
||||
Global_Set(".MAKE.LEVEL", buf);
|
||||
snprintf(buf, sizeof buf, "%u", myPid);
|
||||
Global_Set_ReadOnly(".MAKE.PID", buf);
|
||||
snprintf(buf, sizeof buf, "%u", getppid());
|
||||
@ -1525,8 +1525,8 @@ main_PrepareMaking(void)
|
||||
{
|
||||
/* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
|
||||
if (!opts.noBuiltins || opts.printVars == PVM_NONE) {
|
||||
(void)Var_Subst("${.MAKE.DEPENDFILE}",
|
||||
SCOPE_CMDLINE, VARE_WANTRES, &makeDependfile);
|
||||
makeDependfile = Var_Subst("${.MAKE.DEPENDFILE}",
|
||||
SCOPE_CMDLINE, VARE_WANTRES);
|
||||
if (makeDependfile[0] != '\0') {
|
||||
/* TODO: handle errors */
|
||||
doing_depend = true;
|
||||
@ -2088,9 +2088,9 @@ PrintOnError(GNode *gn, const char *msg)
|
||||
SetErrorVars(gn);
|
||||
|
||||
{
|
||||
char *errorVarsValues;
|
||||
(void)Var_Subst("${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
|
||||
SCOPE_GLOBAL, VARE_WANTRES, &errorVarsValues);
|
||||
char *errorVarsValues = Var_Subst(
|
||||
"${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
|
||||
SCOPE_GLOBAL, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
printf("%s", errorVarsValues);
|
||||
free(errorVarsValues);
|
||||
@ -2118,9 +2118,9 @@ Main_ExportMAKEFLAGS(bool first)
|
||||
return;
|
||||
once = false;
|
||||
|
||||
(void)Var_Subst(
|
||||
flags = Var_Subst(
|
||||
"${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}",
|
||||
SCOPE_CMDLINE, VARE_WANTRES, &flags);
|
||||
SCOPE_CMDLINE, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
if (flags[0] != '\0') {
|
||||
#ifdef POSIX
|
||||
@ -2141,8 +2141,8 @@ getTmpdir(void)
|
||||
return tmpdir;
|
||||
|
||||
/* Honor $TMPDIR if it is valid, strip a trailing '/'. */
|
||||
(void)Var_Subst("${TMPDIR:tA:U" _PATH_TMP ":S,/$,,W}/",
|
||||
SCOPE_GLOBAL, VARE_WANTRES, &tmpdir);
|
||||
tmpdir = Var_Subst("${TMPDIR:tA:U" _PATH_TMP ":S,/$,,W}/",
|
||||
SCOPE_GLOBAL, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
|
||||
if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: make.1,v 1.360 2023/01/26 20:48:17 sjg Exp $
|
||||
.\" $NetBSD: make.1,v 1.361 2023/03/23 03:29:28 sjg 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 January 26, 2023
|
||||
.Dd March 22, 2023
|
||||
.Dt MAKE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -267,7 +267,9 @@ cooperate to avoid overloading the system.
|
||||
Specify the maximum number of jobs that
|
||||
.Nm
|
||||
may have running at any one time.
|
||||
The value is saved in
|
||||
The value of
|
||||
.Ar max_jobs
|
||||
is saved in
|
||||
.Va .MAKE.JOBS .
|
||||
Turns compatibility mode off, unless the
|
||||
.Fl B
|
||||
@ -280,6 +282,13 @@ command invocation and then expect to start with a fresh environment
|
||||
on the next line.
|
||||
It is more efficient to correct the scripts rather than turn backwards
|
||||
compatibility on.
|
||||
.Pp
|
||||
A job token pool with
|
||||
.Ar max_jobs
|
||||
tokens is used to control the total number of jobs running.
|
||||
Each instance of
|
||||
.Nm
|
||||
will wait for a token from the pool before running a new job.
|
||||
.It Fl k
|
||||
Continue processing after errors are encountered, but only on those targets
|
||||
that do not depend on the target whose creation caused the error.
|
||||
@ -2723,3 +2732,15 @@ In many places
|
||||
just counts {} and () in order to find the end of a variable expansion.
|
||||
.Pp
|
||||
There is no way of escaping a space character in a filename.
|
||||
.Pp
|
||||
In jobs mode, when a target fails;
|
||||
.Nm
|
||||
will put an error token into the job token pool.
|
||||
This will cause all other instances of
|
||||
.Nm
|
||||
using that token pool to abort the build and exit with error code 6.
|
||||
Sometimes the attempt to suppress a cascade of unnecessary errors,
|
||||
can result in a seemingly unexplained
|
||||
.Ql *** Error code 6
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: make.c,v 1.258 2022/12/05 23:28:08 rillig Exp $ */
|
||||
/* $NetBSD: make.c,v 1.259 2023/02/14 21:38:31 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.258 2022/12/05 23:28:08 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: make.c,v 1.259 2023/02/14 21:38:31 rillig Exp $");
|
||||
|
||||
/* Sequence # to detect recursion. */
|
||||
static unsigned int checked_seqno = 1;
|
||||
@ -445,7 +445,7 @@ Make_HandleUse(GNode *cgn, GNode *pgn)
|
||||
} else {
|
||||
free(gn->name);
|
||||
}
|
||||
(void)Var_Subst(gn->uname, pgn, VARE_WANTRES, &gn->name);
|
||||
gn->name = Var_Subst(gn->uname, pgn, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
if (gn->uname != NULL && strcmp(gn->name, gn->uname) != 0) {
|
||||
/* See if we have a target for this node. */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: make.h,v 1.311 2023/01/26 20:48:17 sjg Exp $ */
|
||||
/* $NetBSD: make.h,v 1.319 2023/03/28 14:39:31 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -625,14 +625,6 @@ extern GNode *mainNode;
|
||||
extern pid_t myPid;
|
||||
|
||||
#define MAKEFLAGS ".MAKEFLAGS"
|
||||
#define MAKEOVERRIDES ".MAKEOVERRIDES"
|
||||
/* prefix when printing the target of a job */
|
||||
#define MAKE_JOB_PREFIX ".MAKE.JOB.PREFIX"
|
||||
#define MAKE_EXPORTED ".MAKE.EXPORTED" /* exported variables */
|
||||
#define MAKE_MAKEFILES ".MAKE.MAKEFILES" /* all loaded makefiles */
|
||||
#define MAKE_LEVEL ".MAKE.LEVEL" /* recursion level */
|
||||
#define MAKE_MAKEFILE_PREFERENCE ".MAKE.MAKEFILE_PREFERENCE"
|
||||
#define MAKE_MODE ".MAKE.MODE"
|
||||
#ifndef MAKE_LEVEL_ENV
|
||||
# define MAKE_LEVEL_ENV "MAKELEVEL"
|
||||
#endif
|
||||
@ -792,6 +784,8 @@ typedef struct CmdOpts {
|
||||
} CmdOpts;
|
||||
|
||||
extern CmdOpts opts;
|
||||
extern bool forceJobs;
|
||||
extern char **environ;
|
||||
|
||||
/* arch.c */
|
||||
void Arch_Init(void);
|
||||
@ -935,6 +929,14 @@ typedef enum VarEvalMode {
|
||||
*/
|
||||
VARE_PARSE_ONLY,
|
||||
|
||||
/*
|
||||
* Parse text in which '${...}' and '$(...)' are not parsed as
|
||||
* subexpressions (with all their individual escaping rules) but
|
||||
* instead simply as text with balanced '${}' or '$()'. Other '$'
|
||||
* are copied verbatim.
|
||||
*/
|
||||
VARE_PARSE_BALANCED,
|
||||
|
||||
/* Parse and evaluate the expression. */
|
||||
VARE_WANTRES,
|
||||
|
||||
@ -984,35 +986,12 @@ typedef enum VarSetFlags {
|
||||
|
||||
/*
|
||||
* Make the variable read-only. No further modification is possible,
|
||||
* except for another call to Var_Set with the same flag.
|
||||
* except for another call to Var_Set with the same flag. See the
|
||||
* special targets '.NOREADONLY' and '.READONLY'.
|
||||
*/
|
||||
VAR_SET_READONLY = 1 << 1
|
||||
} VarSetFlags;
|
||||
|
||||
/* The state of error handling returned by Var_Parse. */
|
||||
typedef enum VarParseResult {
|
||||
|
||||
/* Both parsing and evaluation succeeded. */
|
||||
VPR_OK,
|
||||
|
||||
/* Parsing or evaluating failed, with an error message. */
|
||||
VPR_ERR,
|
||||
|
||||
/*
|
||||
* Parsing succeeded, undefined expressions are allowed and the
|
||||
* expression was still undefined after applying all modifiers.
|
||||
* No error message is printed in this case.
|
||||
*
|
||||
* Some callers handle this case differently, so return this
|
||||
* information to them, for now.
|
||||
*
|
||||
* TODO: Instead of having this special return value, rather ensure
|
||||
* that VARE_EVAL_KEEP_UNDEF is processed properly.
|
||||
*/
|
||||
VPR_UNDEF
|
||||
|
||||
} VarParseResult;
|
||||
|
||||
typedef enum VarExportMode {
|
||||
/* .export-env */
|
||||
VEM_ENV,
|
||||
@ -1033,8 +1012,8 @@ bool Var_Exists(GNode *, const char *) MAKE_ATTR_USE;
|
||||
bool Var_ExistsExpand(GNode *, const char *) MAKE_ATTR_USE;
|
||||
FStr Var_Value(GNode *, const char *) MAKE_ATTR_USE;
|
||||
const char *GNode_ValueDirect(GNode *, const char *) MAKE_ATTR_USE;
|
||||
VarParseResult Var_Parse(const char **, GNode *, VarEvalMode, FStr *);
|
||||
VarParseResult Var_Subst(const char *, GNode *, VarEvalMode, char **);
|
||||
FStr Var_Parse(const char **, GNode *, VarEvalMode);
|
||||
char *Var_Subst(const char *, GNode *, VarEvalMode);
|
||||
void Var_Expand(FStr *, GNode *, VarEvalMode);
|
||||
void Var_Stats(void);
|
||||
void Var_Dump(GNode *);
|
||||
@ -1224,6 +1203,7 @@ pp_skip_hspace(char **pp)
|
||||
}
|
||||
|
||||
#if defined(lint)
|
||||
extern void do_not_define_rcsid(void); /* for lint */
|
||||
# define MAKE_RCSID(id) extern void do_not_define_rcsid(void)
|
||||
#elif defined(MAKE_NATIVE)
|
||||
# include <sys/cdefs.h>
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: meta.c,v 1.201 2022/09/28 16:34:47 sjg Exp $ */
|
||||
/* $NetBSD: meta.c,v 1.205 2023/03/28 14:39:31 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Implement 'meta' mode.
|
||||
@ -87,8 +87,6 @@ static bool metaCmpFilter = false; /* do we have CMP_FILTER ? */
|
||||
static bool metaCurdirOk = false; /* write .meta in .CURDIR Ok? */
|
||||
static bool metaSilent = false; /* if we have a .meta be SILENT */
|
||||
|
||||
extern bool forceJobs;
|
||||
extern char **environ;
|
||||
|
||||
#define MAKE_META_PREFIX ".MAKE.META.PREFIX"
|
||||
|
||||
@ -328,7 +326,7 @@ is_submake(const char *cmd, GNode *gn)
|
||||
p_len = strlen(p_make);
|
||||
}
|
||||
if (strchr(cmd, '$') != NULL) {
|
||||
(void)Var_Subst(cmd, gn, VARE_WANTRES, &mp);
|
||||
mp = Var_Subst(cmd, gn, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
cmd = mp;
|
||||
}
|
||||
@ -482,10 +480,8 @@ meta_create(BuildMon *pbm, GNode *gn)
|
||||
dname.str = objdir_realpath;
|
||||
|
||||
if (metaVerbose) {
|
||||
char *mp;
|
||||
|
||||
/* Describe the target we are building */
|
||||
(void)Var_Subst("${" MAKE_META_PREFIX "}", gn, VARE_WANTRES, &mp);
|
||||
char *mp = Var_Subst("${" MAKE_META_PREFIX "}", gn, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
if (mp[0] != '\0')
|
||||
fprintf(stdout, "%s\n", mp);
|
||||
@ -621,8 +617,8 @@ meta_mode_init(const char *make_mode)
|
||||
/*
|
||||
* We consider ourselves master of all within ${.MAKE.META.BAILIWICK}
|
||||
*/
|
||||
(void)Var_Subst("${.MAKE.META.BAILIWICK:O:u:tA}",
|
||||
SCOPE_GLOBAL, VARE_WANTRES, &metaBailiwickStr);
|
||||
metaBailiwickStr = Var_Subst("${.MAKE.META.BAILIWICK:O:u:tA}",
|
||||
SCOPE_GLOBAL, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
str2Lst_Append(&metaBailiwick, metaBailiwickStr);
|
||||
/*
|
||||
@ -630,8 +626,8 @@ meta_mode_init(const char *make_mode)
|
||||
*/
|
||||
Global_Append(MAKE_META_IGNORE_PATHS,
|
||||
"/dev /etc /proc /tmp /var/run /var/tmp ${TMPDIR}");
|
||||
(void)Var_Subst("${" MAKE_META_IGNORE_PATHS ":O:u:tA}",
|
||||
SCOPE_GLOBAL, VARE_WANTRES, &metaIgnorePathsStr);
|
||||
metaIgnorePathsStr = Var_Subst("${" MAKE_META_IGNORE_PATHS ":O:u:tA}",
|
||||
SCOPE_GLOBAL, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
str2Lst_Append(&metaIgnorePaths, metaIgnorePathsStr);
|
||||
|
||||
@ -643,6 +639,13 @@ meta_mode_init(const char *make_mode)
|
||||
metaCmpFilter = Var_Exists(SCOPE_GLOBAL, MAKE_META_CMP_FILTER);
|
||||
}
|
||||
|
||||
MAKE_INLINE BuildMon *
|
||||
BM(Job *job)
|
||||
{
|
||||
|
||||
return ((job != NULL) ? &job->bm : &Mybm);
|
||||
}
|
||||
|
||||
/*
|
||||
* In each case below we allow for job==NULL
|
||||
*/
|
||||
@ -651,11 +654,7 @@ meta_job_start(Job *job, GNode *gn)
|
||||
{
|
||||
BuildMon *pbm;
|
||||
|
||||
if (job != NULL) {
|
||||
pbm = &job->bm;
|
||||
} else {
|
||||
pbm = &Mybm;
|
||||
}
|
||||
pbm = BM(job);
|
||||
pbm->mfp = meta_create(pbm, gn);
|
||||
#ifdef USE_FILEMON_ONCE
|
||||
/* compat mode we open the filemon dev once per command */
|
||||
@ -682,11 +681,7 @@ meta_job_child(Job *job MAKE_ATTR_UNUSED)
|
||||
#ifdef USE_FILEMON
|
||||
BuildMon *pbm;
|
||||
|
||||
if (job != NULL) {
|
||||
pbm = &job->bm;
|
||||
} else {
|
||||
pbm = &Mybm;
|
||||
}
|
||||
pbm = BM(job);
|
||||
if (pbm->mfp != NULL) {
|
||||
close(fileno(pbm->mfp));
|
||||
if (useFilemon && pbm->filemon != NULL) {
|
||||
@ -707,11 +702,7 @@ meta_job_parent(Job *job MAKE_ATTR_UNUSED, pid_t pid MAKE_ATTR_UNUSED)
|
||||
#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
|
||||
BuildMon *pbm;
|
||||
|
||||
if (job != NULL) {
|
||||
pbm = &job->bm;
|
||||
} else {
|
||||
pbm = &Mybm;
|
||||
}
|
||||
pbm = BM(job);
|
||||
if (useFilemon && pbm->filemon != NULL) {
|
||||
filemon_setpid_parent(pbm->filemon, pid);
|
||||
}
|
||||
@ -724,11 +715,7 @@ meta_job_fd(Job *job MAKE_ATTR_UNUSED)
|
||||
#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
|
||||
BuildMon *pbm;
|
||||
|
||||
if (job != NULL) {
|
||||
pbm = &job->bm;
|
||||
} else {
|
||||
pbm = &Mybm;
|
||||
}
|
||||
pbm = BM(job);
|
||||
if (useFilemon && pbm->filemon != NULL) {
|
||||
return filemon_readfd(pbm->filemon);
|
||||
}
|
||||
@ -742,11 +729,7 @@ meta_job_event(Job *job MAKE_ATTR_UNUSED)
|
||||
#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
|
||||
BuildMon *pbm;
|
||||
|
||||
if (job != NULL) {
|
||||
pbm = &job->bm;
|
||||
} else {
|
||||
pbm = &Mybm;
|
||||
}
|
||||
pbm = BM(job);
|
||||
if (useFilemon && pbm->filemon != NULL) {
|
||||
return filemon_process(pbm->filemon);
|
||||
}
|
||||
@ -760,13 +743,9 @@ meta_job_error(Job *job, GNode *gn, bool ignerr, int status)
|
||||
char cwd[MAXPATHLEN];
|
||||
BuildMon *pbm;
|
||||
|
||||
if (job != NULL) {
|
||||
pbm = &job->bm;
|
||||
if (gn == NULL)
|
||||
pbm = BM(job);
|
||||
if (job != NULL && gn == NULL)
|
||||
gn = job->node;
|
||||
} else {
|
||||
pbm = &Mybm;
|
||||
}
|
||||
if (pbm->mfp != NULL) {
|
||||
fprintf(pbm->mfp, "\n*** Error code %d%s\n",
|
||||
status, ignerr ? "(ignored)" : "");
|
||||
@ -788,11 +767,7 @@ meta_job_output(Job *job, char *cp, const char *nl)
|
||||
{
|
||||
BuildMon *pbm;
|
||||
|
||||
if (job != NULL) {
|
||||
pbm = &job->bm;
|
||||
} else {
|
||||
pbm = &Mybm;
|
||||
}
|
||||
pbm = BM(job);
|
||||
if (pbm->mfp != NULL) {
|
||||
if (metaVerbose) {
|
||||
static char *meta_prefix = NULL;
|
||||
@ -801,8 +776,8 @@ meta_job_output(Job *job, char *cp, const char *nl)
|
||||
if (meta_prefix == NULL) {
|
||||
char *cp2;
|
||||
|
||||
(void)Var_Subst("${" MAKE_META_PREFIX "}",
|
||||
SCOPE_GLOBAL, VARE_WANTRES, &meta_prefix);
|
||||
meta_prefix = Var_Subst("${" MAKE_META_PREFIX "}",
|
||||
SCOPE_GLOBAL, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
if ((cp2 = strchr(meta_prefix, '$')) != NULL)
|
||||
meta_prefix_len = (size_t)(cp2 - meta_prefix);
|
||||
@ -860,11 +835,7 @@ meta_job_finish(Job *job)
|
||||
int error = 0;
|
||||
int x;
|
||||
|
||||
if (job != NULL) {
|
||||
pbm = &job->bm;
|
||||
} else {
|
||||
pbm = &Mybm;
|
||||
}
|
||||
pbm = BM(job);
|
||||
if (pbm->mfp != NULL) {
|
||||
error = meta_cmd_finish(pbm);
|
||||
x = fclose(pbm->mfp);
|
||||
@ -989,7 +960,7 @@ meta_ignore(GNode *gn, const char *p)
|
||||
*/
|
||||
Var_Set(gn, ".p.", p);
|
||||
expr = "${" MAKE_META_IGNORE_PATTERNS ":@m@${.p.:M$m}@}";
|
||||
(void)Var_Subst(expr, gn, VARE_WANTRES, &pm);
|
||||
pm = Var_Subst(expr, gn, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
if (pm[0] != '\0') {
|
||||
#ifdef DEBUG_META_MODE
|
||||
@ -1008,7 +979,7 @@ meta_ignore(GNode *gn, const char *p)
|
||||
snprintf(fname, sizeof fname,
|
||||
"${%s:L:${%s:ts:}}",
|
||||
p, MAKE_META_IGNORE_FILTER);
|
||||
(void)Var_Subst(fname, gn, VARE_WANTRES, &fm);
|
||||
fm = Var_Subst(fname, gn, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
if (*fm == '\0') {
|
||||
#ifdef DEBUG_META_MODE
|
||||
@ -1066,7 +1037,9 @@ static char *
|
||||
meta_filter_cmd(GNode *gn, char *s)
|
||||
{
|
||||
Var_Set(gn, META_CMD_FILTER_VAR, s);
|
||||
Var_Subst("${" META_CMD_FILTER_VAR ":${" MAKE_META_CMP_FILTER ":ts:}}", gn, VARE_WANTRES, &s);
|
||||
s = Var_Subst(
|
||||
"${" META_CMD_FILTER_VAR ":${" MAKE_META_CMP_FILTER ":ts:}}",
|
||||
gn, VARE_WANTRES);
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -1534,7 +1507,7 @@ meta_oodate(GNode *gn, bool oodate)
|
||||
DEBUG2(META, "%s: %u: cannot compare command using .OODATE\n",
|
||||
fname, lineno);
|
||||
}
|
||||
(void)Var_Subst(cmd, gn, VARE_UNDEFERR, &cmd);
|
||||
cmd = Var_Subst(cmd, gn, VARE_UNDEFERR);
|
||||
/* TODO: handle errors */
|
||||
|
||||
if ((cp = strchr(cmd, '\n')) != NULL) {
|
||||
|
@ -1,3 +1,62 @@
|
||||
2023-04-20 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* install-mk (MK_VERSION): 20230420
|
||||
|
||||
* lib.mk: include LDFLAGS and LDADD when linking shared libs
|
||||
|
||||
* gendirdeps.mk: document setting GENDIRDEPS_FILTER_VARS etc
|
||||
via local.meta.sys.mk rather than local.gendirdeps.mk
|
||||
so DEP_* variables can be set at level 1+ to avoid syntax errors
|
||||
when used in conditionals in manually maintained Makefile.depend
|
||||
files.
|
||||
|
||||
* dirdeps.mk: ensure M_dep_qual_fixes is applied to all _machines
|
||||
|
||||
2023-04-18 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* dirdeps.mk: check we were not included by
|
||||
Makefile.depend.options as the result is bad.
|
||||
|
||||
2023-04-14 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* install-mk (MK_VERSION): 20230414
|
||||
|
||||
* meta.sys.mk: since we have :range we can put the logic for
|
||||
processing TARGET_SPEC from env here.
|
||||
|
||||
* dirdeps.mk: reset DIRDEPS and DEP_RELDIR before including
|
||||
local.dirdeps-missing.mk, also improve debug output.
|
||||
|
||||
* dirdeps.mk: to allow make -f dirdeps.mk include.$TARGET_SPEC
|
||||
we need to use :M*[/.]* same as for when actually setting DIRDEPS
|
||||
from the targets on command line.
|
||||
|
||||
2023-04-12 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* Add jobs.mk
|
||||
|
||||
2023-03-21 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* install-mk (MK_VERSION): 20230321
|
||||
|
||||
* meta.stage.mk: allow STAGE_SHLIB_LINKS_FILTER to filter
|
||||
STAGE_LIBS for SHLIB_LINKS.
|
||||
|
||||
* autoconf.mk: add .WAIT after config.status
|
||||
|
||||
2023-02-17 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* sys.vars.mk: add M_Index to report the index of a word in a list.
|
||||
|
||||
2023-02-15 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* install-mk (MK_VERSION): 20230215
|
||||
|
||||
* warnings.mk: allow better control of -Werror
|
||||
allow -Wno-error or similar to be added if
|
||||
WARNINGS_SET < WERROR_SET
|
||||
account for COMPILER_TYPE
|
||||
|
||||
2023-01-29 Simon J Gerraty <sjg@beast.crufty.net>
|
||||
|
||||
* autoconf.mk: hook config.status to beforebuild.
|
||||
|
@ -20,6 +20,7 @@ inc.mk
|
||||
init.mk
|
||||
install-mk
|
||||
java.mk
|
||||
jobs.mk
|
||||
ldorder.mk
|
||||
lib.mk
|
||||
libnames.mk
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: autoconf.mk,v 1.17 2023/01/29 17:31:16 sjg Exp $
|
||||
# $Id: autoconf.mk,v 1.18 2023/03/22 15:37:19 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 1996-2009, Simon J. Gerraty
|
||||
#
|
||||
@ -34,7 +34,7 @@ config.status: config.recheck
|
||||
config.status: config.gen
|
||||
.endif
|
||||
|
||||
beforebuild: .NOTMAIN config.status
|
||||
beforebuild: .NOTMAIN config.status .WAIT
|
||||
|
||||
config.recheck: .NOTMAIN ${CONFIGURE_DEPS} config.gen
|
||||
./config.status --recheck
|
||||
|
@ -1,6 +1,8 @@
|
||||
# $Id: dirdeps.mk,v 1.152 2022/08/01 23:09:19 sjg Exp $
|
||||
# $Id: dirdeps.mk,v 1.157 2023/04/22 21:07:51 sjg Exp $
|
||||
|
||||
# Copyright (c) 2010-2022, Simon J. Gerraty
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
# Copyright (c) 2010-2023, Simon J. Gerraty
|
||||
# Copyright (c) 2010-2018, Juniper Networks, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
@ -179,7 +181,7 @@ _DIRDEP_USE_LEVEL?= 0
|
||||
_CURDIR ?= ${.CURDIR}
|
||||
_OBJDIR ?= ${.OBJDIR}
|
||||
|
||||
.if ${MAKEFILE:T} == ${.PARSEFILE} && empty(DIRDEPS) && ${.TARGETS:Uall:M*/*} != ""
|
||||
.if ${MAKEFILE:T} == ${.PARSEFILE} && empty(DIRDEPS) && ${.TARGETS:Uall:M*[/.]*} != ""
|
||||
# This little trick let's us do
|
||||
#
|
||||
# mk -f dirdeps.mk some/dir.${TARGET_SPEC}
|
||||
@ -347,6 +349,10 @@ BUILD_DIRDEPS ?= yes
|
||||
DIRDEPS_CACHE ?= ${_OBJDIR:tA}/dirdeps.cache${_TARGETS:U${.TARGETS}:Nall:O:u:ts-:S,/,_,g:S,^,.,:N.}
|
||||
.endif
|
||||
|
||||
# sanity check: Makefile.depend.options should *not* include us
|
||||
.if ${.INCLUDEDFROMFILE:U:M${.MAKE.DEPENDFILE_PREFIX}.options} != ""
|
||||
.error ${DEP_RELDIR}/${.MAKE.DEPENDFILE_PREFIX}.options: should include dirdeps-options.mk
|
||||
.endif
|
||||
|
||||
# pickup customizations
|
||||
# as below you can use !target(_DIRDEP_USE) to protect things
|
||||
@ -577,7 +583,7 @@ ${DIRDEPS_CACHE}: .META .NOMETA_CMP
|
||||
${"${DEBUG_DIRDEPS:Nno}":?DEBUG_DIRDEPS='${DEBUG_DIRDEPS}':} \
|
||||
${.MAKEFLAGS:tW:S,-D ,-D,g:tw:M*WITH*} \
|
||||
${.MAKEFLAGS:tW:S,-d ,-d,g:tw:M-d*} \
|
||||
3>&1 1>&2 | sed 's,${SRCTOP},_{SRCTOP},g;s,_{,$${,g' >> ${.TARGET}.new && \
|
||||
3>&1 1>&2 | sed 's,${SRCTOP},_{SRCTOP},g;s,_{SRCTOP}/_{SRCTOP},_{SRCTOP},g;s,_{,$${,g' >> ${.TARGET}.new && \
|
||||
mv ${.TARGET}.new ${.TARGET}
|
||||
|
||||
.endif
|
||||
@ -639,9 +645,9 @@ _dm := ${DEP_MACHINE}
|
||||
# apply the same filtering that we do when qualifying DIRDEPS.
|
||||
# M_dep_qual_fixes expects .${MACHINE}* so add (and remove) '.'
|
||||
# Again we expect that any already qualified machines are fully qualified.
|
||||
_machines := ${_machines:M*,*} ${_machines:N*,*:@DEP_MACHINE@${DEP_TARGET_SPEC}@:S,^,.,:${M_dep_qual_fixes:ts:}:O:u:S,^.,,}
|
||||
_machines := ${_machines:M*,*} ${_machines:N*,*:@DEP_MACHINE@${DEP_TARGET_SPEC}@:S,^,.,:S,^.,,}
|
||||
DEP_MACHINE := ${_dm}
|
||||
_machines := ${_machines:O:u}
|
||||
_machines := ${_machines:${M_dep_qual_fixes:ts:}:O:u}
|
||||
.endif
|
||||
|
||||
# reset each time through
|
||||
@ -788,8 +794,9 @@ ${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m}
|
||||
.if !target(_dirdeps_checked.$d)
|
||||
# once only
|
||||
_dirdeps_checked.$d:
|
||||
_dr := ${d:S,^${SRCTOP}/,,}
|
||||
.if ${_debug_search}
|
||||
.info checking ${d:S,^${SRCTOP}/,,}
|
||||
.info checking ${_dr}
|
||||
.endif
|
||||
# Note: _build_all_dirs is fully qualifed so d:R is always the directory
|
||||
.if exists(${d:R})
|
||||
@ -822,10 +829,16 @@ DEP_RELDIR := ${_m:H:S,^${SRCTOP}/,,}
|
||||
# and reset this
|
||||
DIRDEPS =
|
||||
.if ${_debug_reldir} && ${_qm} != ${_m}
|
||||
.info loading ${_m} for ${d:E}
|
||||
.info loading ${_m:S,${SRCTOP}/,,} for ${_dr}
|
||||
.endif
|
||||
.include <${_m}>
|
||||
.else
|
||||
# set these as if we found Makefile.depend*
|
||||
DEP_RELDIR := ${_dr:R}
|
||||
DIRDEPS =
|
||||
.if ${_debug_reldir}
|
||||
.info loading local.dirdeps-missing.mk for ${_dr}
|
||||
.endif
|
||||
.-include <local.dirdeps-missing.mk>
|
||||
.endif
|
||||
.endif
|
||||
|
@ -1,5 +1,7 @@
|
||||
# $Id: gendirdeps.mk,v 1.48 2022/09/09 17:44:29 sjg Exp $
|
||||
# $Id: gendirdeps.mk,v 1.49 2023/04/20 17:45:03 sjg Exp $
|
||||
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
# Copyright (c) 2011-2020, Simon J. Gerraty
|
||||
# Copyright (c) 2010-2018, Juniper Networks, Inc.
|
||||
# All rights reserved.
|
||||
@ -41,6 +43,37 @@
|
||||
# symlink to another filesystem.
|
||||
# _objroot must be a prefix match for _objtop
|
||||
|
||||
# If any of GENDIRDEPS_FILTER, GENDIRDEPS_FILTER_DIR_VARS
|
||||
# or GENDIRDEPS_FILTER_VARS are set, we use them to filter the
|
||||
# output from filemon(4).
|
||||
# Any references to variables that dirdeps.mk will set
|
||||
# such as DEP_MACHINE, DEP_RELDIR etc, should use that form.
|
||||
# Thus we want ${DEP_MACHINE} not ${MACHINE} used in DIRDEPS.
|
||||
#
|
||||
# If any manually maintained Makefile.depend files will use any
|
||||
# DEP_* variables in conditionals, precautions are needed to avoid
|
||||
# errors when Makefile.depend is read at level 1+ (ie not via
|
||||
# dirdeps.mk)
|
||||
# Using MACHINE as an example; such makefiles can do:
|
||||
#
|
||||
# DEP_MACHINE ?= ${MACHINE}
|
||||
# .if ${DEP_MACHINE} == "xyz"
|
||||
#
|
||||
# or:
|
||||
#
|
||||
# .if ${DEP_MACHINE:U${MACHINE}} == "xyz"
|
||||
#
|
||||
# but it might be safer to set GENDIRDEPS_FILTER_DIR_VARS and
|
||||
# GENDIRDEPS_FILTER_VARS via local.meta.sys.mk rather than
|
||||
# local.gendirdeps.mk and then:
|
||||
#
|
||||
# .if ${.MAKE.LEVEL} > 0
|
||||
# .for V in ${GENDIRDEPS_FILTER_DIR_VARS:MDEP_*} \
|
||||
# ${GENDIRDEPS_FILTER_VARS:MDEP_*}
|
||||
# $V ?= ${${V:S,DEP_,,}}
|
||||
# .endfor
|
||||
# .endif
|
||||
#
|
||||
.MAIN: all
|
||||
|
||||
# keep this simple
|
||||
|
@ -59,7 +59,7 @@
|
||||
# Simon J. Gerraty <sjg@crufty.net>
|
||||
|
||||
# RCSid:
|
||||
# $Id: install-mk,v 1.226 2023/01/28 16:52:12 sjg Exp $
|
||||
# $Id: install-mk,v 1.231 2023/04/20 17:45:03 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 1994-2023 Simon J. Gerraty
|
||||
#
|
||||
@ -74,7 +74,7 @@
|
||||
# sjg@crufty.net
|
||||
#
|
||||
|
||||
MK_VERSION=20230127
|
||||
MK_VERSION=20230420
|
||||
OWNER=
|
||||
GROUP=
|
||||
MODE=444
|
||||
|
88
contrib/bmake/mk/jobs.mk
Normal file
88
contrib/bmake/mk/jobs.mk
Normal file
@ -0,0 +1,88 @@
|
||||
# $Id: jobs.mk,v 1.7 2023/04/18 23:32:28 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 2012-2023, Simon J. Gerraty
|
||||
#
|
||||
# This file is provided in the hope that it will
|
||||
# be of use. There is absolutely NO WARRANTY.
|
||||
# Permission to copy, redistribute or otherwise
|
||||
# use this file is hereby granted provided that
|
||||
# the above copyright notice and this notice are
|
||||
# left intact.
|
||||
#
|
||||
# Please send copies of changes and bug-fixes to:
|
||||
# sjg@crufty.net
|
||||
#
|
||||
|
||||
# This makefile is used by top-level makefile.
|
||||
# With the following:
|
||||
#
|
||||
# .if make(*-jobs)
|
||||
# .include <jobs.mk>
|
||||
# .endif
|
||||
#
|
||||
#
|
||||
# Then if you do:
|
||||
#
|
||||
# mk target-jobs
|
||||
#
|
||||
# We will run:
|
||||
#
|
||||
# ${MAKE} -j${JOB_MAX} target > ${JOB_LOGDIR}/target.log 2>&1
|
||||
#
|
||||
# JOB_MAX defaults to 8 but should normally be derrived based on the
|
||||
# number of cpus available. The wrapper script 'mk' makes that easy.
|
||||
#
|
||||
|
||||
now_utc ?= ${%s:L:gmtime}
|
||||
.if !defined(start_utc)
|
||||
start_utc := ${now_utc}
|
||||
.endif
|
||||
|
||||
.info ${.newline}${TIME_STAMP} Start ${.TARGETS}
|
||||
|
||||
.if make(*-jobs)
|
||||
|
||||
JOB_LOGDIR ?= ${SRCTOP:H}
|
||||
JOB_LOG = ${JOB_LOGDIR}/${.TARGET:S,-jobs,,:S,/,_,g}.log
|
||||
JOB_LOG_GENS ?= 4
|
||||
# we like to rotate logs
|
||||
.if empty(NEWLOG_SH)
|
||||
.ifdef M_whence
|
||||
NEWLOG_SH := ${newlog.sh:L:${M_whence}}
|
||||
.else
|
||||
NEWLOG_SH := ${(type newlog.sh) 2> /dev/null:L:sh:M/*}
|
||||
.endif
|
||||
.endif
|
||||
.if !empty(NEWLOG_SH) && exists(${NEWLOG_SH})
|
||||
NEWLOG := sh ${NEWLOG_SH}
|
||||
JOB_NEWLOG_ARGS ?= -S -n ${JOB_LOG_GENS}
|
||||
.else
|
||||
NEWLOG = :
|
||||
.endif
|
||||
|
||||
.if ${.MAKE.JOBS:U0} > 0
|
||||
JOB_MAX= ${.MAKE.JOBS}
|
||||
.else
|
||||
# This should be derrived from number of cpu's
|
||||
JOB_MAX?= 8
|
||||
JOB_ARGS+= -j${JOB_MAX}
|
||||
.endif
|
||||
|
||||
# we need to reset .MAKE.LEVEL to 0 do that
|
||||
# build orchestration works as expected (DIRDEPS_BUILD)
|
||||
${.TARGETS:M*-jobs}:
|
||||
@${NEWLOG} ${JOB_NEWLOG_ARGS} ${JOB_LOG}
|
||||
@echo Logging to ${JOB_LOG}
|
||||
@cd ${.CURDIR} && env MAKELEVEL=0 \
|
||||
${.MAKE} ${JOB_ARGS} _TARGETS=${.TARGET:S,-jobs,,} ${.TARGET:S,-jobs,,} >> ${JOB_LOG} 2>&1
|
||||
|
||||
.endif
|
||||
|
||||
.END: _build_finish
|
||||
.ERROR: _build_failed
|
||||
|
||||
_build_finish: .NOMETA
|
||||
@echo "${TIME_STAMP} Finished ${.TARGETS} seconds=`expr ${now_utc} - ${start_utc}`"
|
||||
|
||||
_build_failed: .NOMETA
|
||||
@echo "${TIME_STAMP} Failed ${.TARGETS} seconds=`expr ${now_utc} - ${start_utc}`"
|
@ -1,4 +1,4 @@
|
||||
# $Id: lib.mk,v 1.73 2021/12/08 05:56:50 sjg Exp $
|
||||
# $Id: lib.mk,v 1.74 2023/04/20 23:45:56 sjg Exp $
|
||||
|
||||
.if !target(__${.PARSEFILE}__)
|
||||
__${.PARSEFILE}__: .NOTMAIN
|
||||
@ -448,18 +448,19 @@ lib${LIB}_pic.a: ${SOBJS}
|
||||
lib${LIB}.${LD_so}: ${SOLIB} ${DPADD}
|
||||
@${META_NOECHO} building shared ${LIB} library \(version ${SHLIB_FULLVERSION}\)
|
||||
@rm -f ${.TARGET}
|
||||
.if ${TARGET_OSNAME} == "NetBSD" || ${TARGET_OSNAME} == "FreeBSD"
|
||||
.if ${TARGET_OSNAME:NFreeBSD:NNetBSD} == ""
|
||||
.if ${OBJECT_FMT} == "ELF"
|
||||
${SHLIB_LD} -x -shared ${SHLIB_SHFLAGS} -o ${.TARGET} \
|
||||
${SHLIB_LD} -x -shared ${SHLIB_SHFLAGS} ${LDFLAGS} -o ${.TARGET} \
|
||||
${SHLIB_LDSTARTFILE} \
|
||||
--whole-archive ${SOLIB} --no-whole-archive ${SHLIB_LDADD} \
|
||||
${SHLIB_LDENDFILE}
|
||||
--whole-archive ${SOLIB} --no-whole-archive \
|
||||
${LDADD} ${SHLIB_LDADD} ${SHLIB_LDENDFILE}
|
||||
.else
|
||||
${SHLIB_LD} ${LD_x} ${LD_shared} \
|
||||
-o ${.TARGET} ${SOLIB} ${SHLIB_LDADD}
|
||||
${SHLIB_LD} ${LD_x} ${LD_shared} ${LDFLAGS} \
|
||||
-o ${.TARGET} ${SOLIB} ${LDADD} ${SHLIB_LDADD}
|
||||
.endif
|
||||
.else
|
||||
${SHLIB_LD} -o ${.TARGET} ${LD_shared} ${LD_solib} ${DLLIB} ${SHLIB_LDADD}
|
||||
${SHLIB_LD} ${LDFLAGS} -o ${.TARGET} \
|
||||
${LD_shared} ${LD_solib} ${DLLIB} ${LDADD} ${SHLIB_LDADD}
|
||||
.endif
|
||||
.endif
|
||||
.if !empty(SHLIB_LINKS)
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: meta.stage.mk,v 1.65 2022/09/09 17:44:29 sjg Exp $
|
||||
# $Id: meta.stage.mk,v 1.67 2023/04/17 01:22:10 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 2011-2017, Simon J. Gerraty
|
||||
#
|
||||
@ -54,7 +54,7 @@ _objroot ?= ${_OBJROOT:tA}
|
||||
# make sure this is global
|
||||
_STAGED_DIRS ?=
|
||||
.export _STAGED_DIRS
|
||||
# add each dir we stage to to _STAGED_DIRS
|
||||
# add each dir we stage to _STAGED_DIRS
|
||||
# and make sure we have absolute paths so that bmake
|
||||
# will match against .MAKE.META.BAILIWICK
|
||||
STAGE_DIR_FILTER = tA:@d@$${_STAGED_DIRS::+=$$d}$$d@
|
||||
@ -173,7 +173,7 @@ stage_libs: .dirdep
|
||||
.if !defined(NO_SHLIB_LINKS)
|
||||
.if !empty(SHLIB_LINKS)
|
||||
@${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} \
|
||||
${SHLIB_LINKS:@t@${STAGE_LIBS:T:M$t.*} $t@}
|
||||
${SHLIB_LINKS:@t@${STAGE_LIBS:T:M$t.*:${STAGE_SHLIB_LINKS_FILTER:U}} $t@}
|
||||
.elif !empty(SHLIB_LINK) && !empty(SHLIB_NAME)
|
||||
@${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${SHLIB_NAME} ${SHLIB_LINK}
|
||||
.endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: meta.sys.mk,v 1.42 2021/12/13 05:50:55 sjg Exp $
|
||||
# $Id: meta.sys.mk,v 1.46 2023/04/18 18:43:00 sjg Exp $
|
||||
|
||||
#
|
||||
# @(#) Copyright (c) 2010-2021, Simon J. Gerraty
|
||||
@ -20,7 +20,44 @@
|
||||
.if ${MAKE_VERSION:U0} > 20100901
|
||||
.if !target(.ERROR)
|
||||
|
||||
.-include <local.meta.sys.mk>
|
||||
.-include <local.meta.sys.env.mk>
|
||||
|
||||
# If TARGET_SPEC_VARS is other than just MACHINE
|
||||
# it should be set by now.
|
||||
# TARGET_SPEC must not contain any '.'s.
|
||||
TARGET_SPEC_VARS ?= MACHINE
|
||||
|
||||
.if !target(_meta_tspec_env_done_)
|
||||
_meta_tspec_env_done_: .NOTMAIN
|
||||
# Allow for local.meta.sys.env.mk to have done this
|
||||
|
||||
.if ${TARGET_SPEC:Uno:M*,*} != ""
|
||||
# deal with TARGET_SPEC from env
|
||||
_tspec := ${TARGET_SPEC:S/,/ /g}
|
||||
.for i in ${TARGET_SPEC_VARS:${M_RANGE:Urange}}
|
||||
${TARGET_SPEC_VARS:[$i]} := ${_tspec:[$i]}
|
||||
.endfor
|
||||
# We need to stop that TARGET_SPEC affecting any submakes
|
||||
TARGET_SPEC=
|
||||
# so export but do not track
|
||||
.export-env TARGET_SPEC
|
||||
.export ${TARGET_SPEC_VARS}
|
||||
.for v in ${TARGET_SPEC_VARS:O:u}
|
||||
.if empty($v)
|
||||
.undef $v
|
||||
.endif
|
||||
.endfor
|
||||
.endif
|
||||
.endif
|
||||
|
||||
# Now make sure we know what TARGET_SPEC is
|
||||
# as we may need it to find Makefile.depend*
|
||||
.if ${MACHINE:Mhost*} != ""
|
||||
# host is special
|
||||
TARGET_SPEC = ${MACHINE}
|
||||
.else
|
||||
TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,}
|
||||
.endif
|
||||
|
||||
# absolute path to what we are reading.
|
||||
_PARSEDIR = ${.PARSEDIR:tA}
|
||||
@ -177,3 +214,5 @@ META_NOPHONY= .PHONY
|
||||
META_NOECHO= echo
|
||||
.endif
|
||||
.endif
|
||||
|
||||
.-include <local.meta.sys.mk>
|
||||
|
@ -76,7 +76,8 @@ When bmake starts, it looks for ``sys.mk`` and reads it before doing
|
||||
anything else. Thus, this is the place to setup the environment for
|
||||
everyone else.
|
||||
|
||||
In this distribution, ``sys.mk`` avoids doing anything platform dependent.
|
||||
In this distribution, ``sys.mk`` avoids doing anything platform or
|
||||
site dependent.
|
||||
It is quite short, and includes a number of other files (which may or
|
||||
may not exists)
|
||||
|
||||
@ -315,7 +316,7 @@ obj.mk
|
||||
|
||||
One of the cool aspects of BSD make, is its support for separating
|
||||
object files from the src tree. This is also the source of much
|
||||
confusion to some.
|
||||
confusion for people unfamiliar with it.
|
||||
|
||||
Traditionally one had to do a separate ``make obj`` pass through the
|
||||
tree. If ``MK_AUTO_OBJ`` is set we include auto.obj.mk_.
|
||||
@ -326,8 +327,9 @@ In fact if ``MKOBJDIRS`` is set to "auto", `sys.mk`_ will set
|
||||
auto.obj.mk
|
||||
-----------
|
||||
|
||||
This leverages the ``.OBJDIR`` target introduced some years ago to
|
||||
NetBSD make, to automatically create and use the desired object dir.
|
||||
Creates object dirs and leverages the ``.OBJDIR`` target introduced
|
||||
some years ago to NetBSD make, to use them.
|
||||
|
||||
|
||||
subdir.mk
|
||||
---------
|
||||
@ -461,7 +463,7 @@ would add all the warnings in ``${HIGH_WARNINGS}`` to CFLAGS, but
|
||||
on sparc, ``-Wno-unused`` would replace ``-Wunused``.
|
||||
|
||||
You should never need to edit ``warnings.mk``, it will include
|
||||
``warnings-sets.mk`` if it exists and you use that to make any local
|
||||
``warnings-sets.mk`` and/or ``local.warnings.mk`` to pick up
|
||||
customizations.
|
||||
|
||||
rst2htm.mk
|
||||
@ -492,6 +494,21 @@ In the past, making use of compiler wrappers like ``ccache``,
|
||||
``distcc`` or the newer ``icecc`` could get quite ugly.
|
||||
Using ``cc-wrap.mk`` it could not be simpler.
|
||||
|
||||
jobs.mk
|
||||
-------
|
||||
|
||||
This should be included by the top-level makefile.
|
||||
If you do::
|
||||
|
||||
make something-jobs
|
||||
|
||||
then ``jobs.mk`` will run::
|
||||
|
||||
make -j${JOB_MAX} someting > ${JOB_LOGDIR}/something.log 2>&1
|
||||
|
||||
this ensures you get a build log and JOB_MAX is assumed to be set
|
||||
optimally for the host.
|
||||
|
||||
Meta mode
|
||||
=========
|
||||
|
||||
@ -525,5 +542,5 @@ where you unpacked the tar file, you can::
|
||||
.. _mk.tar.gz: http://www.crufty.net/ftp/pub/sjg/mk.tar.gz
|
||||
|
||||
:Author: sjg@crufty.net
|
||||
:Revision: $Id: mk-files.txt,v 1.21 2022/02/04 19:01:05 sjg Exp $
|
||||
:Revision: $Id: mk-files.txt,v 1.22 2023/04/16 23:43:33 sjg Exp $
|
||||
:Copyright: Crufty.NET
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: prog.mk,v 1.38 2022/07/22 20:08:56 sjg Exp $
|
||||
# $Id: prog.mk,v 1.39 2023/04/20 23:45:56 sjg Exp $
|
||||
|
||||
.if !target(__${.PARSEFILE}__)
|
||||
__${.PARSEFILE}__: .NOTMAIN
|
||||
@ -97,7 +97,7 @@ LOBJS+= ${LSRCS:.c=.ln} ${SRCS:M*.c:.c=.ln}
|
||||
.NOPATH: ${OBJS} ${PROG} ${SRCS:M*.[ly]:C/\..$/.c/} ${YHEADER:D${SRCS:M*.y:.y=.h}}
|
||||
|
||||
# this is known to work for NetBSD 1.6 and FreeBSD 4.2
|
||||
.if ${TARGET_OSNAME} == "NetBSD" || ${TARGET_OSNAME} == "FreeBSD"
|
||||
.if ${TARGET_OSNAME:NFreeBSD:NNetBSD} == ""
|
||||
_PROGLDOPTS=
|
||||
.if ${SHLINKDIR} != "/usr/libexec" # XXX: change or remove if ld.so moves
|
||||
_PROGLDOPTS+= -Wl,-dynamic-linker=${_SHLINKER}
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: sys.vars.mk,v 1.12 2023/01/20 17:34:06 sjg Exp $
|
||||
# $Id: sys.vars.mk,v 1.14 2023/02/17 22:32:47 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 2003-2023, Simon J. Gerraty
|
||||
#
|
||||
@ -121,3 +121,11 @@ M_Onr = O
|
||||
M_On = On
|
||||
M_Onr = Onr
|
||||
.endif
|
||||
|
||||
# Index of a word in a list.
|
||||
# eg. ${LIST:${M_Index:S,K,key,}} is the index of
|
||||
# the word "key" in ${LIST}, of course any pattern can be used.
|
||||
# If "key" appears more than once, there will be multiple
|
||||
# index values use ${M_Index:S,K,key,}:[1] to select only the first.
|
||||
M_Index = _:${M_RANGE}:@i@$${"$${_:[$$i]:MK}":?$$i:}@
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# RCSid:
|
||||
# $Id: warnings.mk,v 1.15 2020/08/19 17:51:53 sjg Exp $
|
||||
# $Id: warnings.mk,v 1.17 2023/02/16 17:55:52 sjg Exp $
|
||||
#
|
||||
# @(#) Copyright (c) 2002, Simon J. Gerraty
|
||||
# @(#) Copyright (c) 2002-2023, Simon J. Gerraty
|
||||
#
|
||||
# This file is provided in the hope that it will
|
||||
# be of use. There is absolutely NO WARRANTY.
|
||||
@ -20,21 +20,23 @@
|
||||
|
||||
# Any number of warnings sets can be added.
|
||||
.-include <warnings-sets.mk>
|
||||
# This is more in keeping with our current practice
|
||||
.-include <local.warnings.mk>
|
||||
|
||||
# Modest defaults - put more elaborate sets in warnings-sets.mk
|
||||
# -Wunused etc are here so you can set
|
||||
# W_unused=-Wno-unused etc.
|
||||
MIN_WARNINGS?= -Wall \
|
||||
MIN_WARNINGS ?= -Wall \
|
||||
-Wformat \
|
||||
-Wimplicit \
|
||||
-Wunused \
|
||||
-Wuninitialized
|
||||
|
||||
LOW_WARNINGS?= ${MIN_WARNINGS} -W -Wstrict-prototypes -Wmissing-prototypes
|
||||
LOW_WARNINGS ?= ${MIN_WARNINGS} -W -Wstrict-prototypes -Wmissing-prototypes
|
||||
|
||||
MEDIUM_WARNINGS?= ${LOW_WARNINGS} -Werror
|
||||
MEDIUM_WARNINGS ?= ${LOW_WARNINGS}
|
||||
|
||||
HIGH_WARNINGS?= ${MEDIUM_WARNINGS} \
|
||||
HIGH_WARNINGS ?= ${MEDIUM_WARNINGS} \
|
||||
-Wcast-align \
|
||||
-Wcast-qual \
|
||||
-Wparentheses \
|
||||
@ -44,19 +46,46 @@ HIGH_WARNINGS?= ${MEDIUM_WARNINGS} \
|
||||
-Wswitch \
|
||||
-Wwrite-strings
|
||||
|
||||
EXTRA_WARNINGS?= ${HIGH_WARNINGS} -Wextra
|
||||
EXTRA_WARNINGS ?= ${HIGH_WARNINGS} -Wextra
|
||||
|
||||
# The two step default makes it easier to test build with different defaults.
|
||||
DEFAULT_WARNINGS_SET?= MIN
|
||||
WARNINGS_SET?= ${DEFAULT_WARNINGS_SET}
|
||||
DEFAULT_WARNINGS_SET ?= MIN
|
||||
WARNINGS_SET ?= ${DEFAULT_WARNINGS_SET}
|
||||
|
||||
# There is always someone who wants more...
|
||||
.if !empty(WARNINGS_XTRAS)
|
||||
${WARNINGS_SET}_WARNINGS += ${WARNINGS_XTRAS}
|
||||
.endif
|
||||
|
||||
# If you add sets, besure to list them (you don't have to touch this list).
|
||||
ALL_WARNINGS_SETS+= MIN LOW MEDIUM HIGH EXTRA
|
||||
# Keep this list ordered!
|
||||
WARNINGS_SET_LIST ?= MIN LOW MEDIUM HIGH EXTRA
|
||||
|
||||
# We assume WARNINGS_SET_LIST is an ordered list.
|
||||
# if WARNINGS_SET is < WERROR_SET we add WARNINGS_NO_ERROR
|
||||
# otherwise we add WARNINGS_ERROR
|
||||
DEFAULT_WERROR_SET ?= MEDIUM
|
||||
WERROR_SET ?= ${DEFAULT_WERROR_SET}
|
||||
WARNINGS_ERROR ?= -Werror
|
||||
WARNINGS_NO_ERROR ?=
|
||||
|
||||
.if ${MAKE_VERSION} >= 20170130
|
||||
.for i in ${WARNINGS_SET_LIST:range}
|
||||
.if ${WARNINGS_SET_LIST:[$i]} == ${WARNINGS_SET}
|
||||
WARNINGS_SETx = $i
|
||||
.endif
|
||||
.if ${WARNINGS_SET_LIST:[$i]} == ${WERROR_SET}
|
||||
WERROR_SETx = $i
|
||||
.if ${MAKE_VERSION} >= 20220924
|
||||
.break
|
||||
.endif
|
||||
.endif
|
||||
.endfor
|
||||
.if ${WARNINGS_SETx:U${WERROR_SETx:U0}} < ${WERROR_SETx:U0}
|
||||
${WARNINGS_SET}_WARNINGS += ${WARNINGS_NO_ERROR:U}
|
||||
.else
|
||||
${WARNINGS_SET}_WARNINGS += ${WARNINGS_ERROR}
|
||||
.endif
|
||||
.endif
|
||||
|
||||
.if !empty(WARNINGS_SET)
|
||||
.for ws in ${WARNINGS_SET}
|
||||
@ -68,7 +97,7 @@ _empty_warnings: .PHONY
|
||||
.BEGIN:
|
||||
.endif
|
||||
@echo "ERROR: Invalid: WARNINGS_SET=${ws}"
|
||||
@echo "ERROR: Try one of: ${ALL_WARNINGS_SETS:O:u}"; exit 1
|
||||
@echo "ERROR: Try one of: ${WARNINGS_SET_LIST}"; exit 1
|
||||
|
||||
.endif
|
||||
.endfor
|
||||
@ -96,15 +125,19 @@ W_uninitialized=
|
||||
# which makes it easy to turn off override individual flags
|
||||
# (see W_uninitialized above).
|
||||
#
|
||||
# The last bit expands to ${W_foo_${.TARGET:T}:U${W_foo}}
|
||||
# The last bit expands to
|
||||
# ${W_foo_${.TARGET:T:${TARGET_PREFIX_FILTER:ts:}}:U${W_foo}}
|
||||
# which is the bit we ultimately want. It allows W_* to be set on a
|
||||
# per target basis.
|
||||
#
|
||||
# NOTE: that we force the target extension to be .o
|
||||
# TARGET_PREFIX_FILTER defaults to R
|
||||
#
|
||||
|
||||
TARGET_PREFIX_FILTER ?= R
|
||||
|
||||
# define this once, we use it a couple of times below (hence the doubled $$).
|
||||
M_warnings_list = @s@$${$$s_WARNINGS}@:O:u:@w@$${$${w:C/-(.)/\1_/}::?=$$w} $${$${w:C/-(.)/\1_/}_${MACHINE_ARCH}_${.TARGET:T:R}.o:U$${$${w:C/-(.)/\1_/}_${.TARGET:T:R}.o:U$${$${w:C/-(.)/\1_/}_${MACHINE_ARCH}:U$${$${w:C/-(.)/\1_/}}}}}@
|
||||
M_warnings_list = @s@$${$$s_WARNINGS} $${$$s_WARNINGS.${COMPILER_TYPE}:U}@:O:u:@w@$${$${w:C/-(.)/\1_/}::?=$$w} $${$${w:C/-(.)/\1_/}_${MACHINE_ARCH}_${.TARGET:T:${TARGET_PREFIX_FILTER:ts:}}.o:U$${$${w:C/-(.)/\1_/}_${.TARGET:T:${TARGET_PREFIX_FILTER:ts:}}.o:U$${$${w:C/-(.)/\1_/}_${MACHINE_ARCH}:U$${$${w:C/-(.)/\1_/}}}}}@
|
||||
|
||||
# first a list of warnings from the chosen set
|
||||
_warnings = ${WARNINGS_SET_${MACHINE_ARCH}:U${WARNINGS_SET}:${M_warnings_list}}
|
||||
@ -112,13 +145,13 @@ _warnings = ${WARNINGS_SET_${MACHINE_ARCH}:U${WARNINGS_SET}:${M_warnings_list}}
|
||||
# since things like -Wall imply lots of others.
|
||||
# this should be a super-set of the -Wno-* in _warnings, but
|
||||
# just in case...
|
||||
_no_warnings = ${_warnings:M-Wno-*} ${ALL_WARNINGS_SETS:${M_warnings_list}:M-Wno-*}
|
||||
_no_warnings = ${_warnings:M-Wno-*} ${WARNINGS_SET_LIST:${M_warnings_list}:M-Wno-*}
|
||||
# -Wno-* must follow any others
|
||||
WARNINGS += ${_warnings:N-Wno-*} ${_no_warnings:O:u}
|
||||
|
||||
.ifndef NO_CFLAGS_WARNINGS
|
||||
# Just ${WARNINGS} should do, but this is more flexible?
|
||||
CFLAGS+= ${WARNINGS_${.TARGET:T:R}.o:U${WARNINGS}}
|
||||
CFLAGS+= ${WARNINGS_${.TARGET:T:${TARGET_PREFIX_FILTER:ts:}}.o:U${WARNINGS}}
|
||||
.endif
|
||||
|
||||
# it is rather silly that g++ blows up on some warning flags
|
||||
@ -130,9 +163,10 @@ NO_CXX_WARNINGS+= \
|
||||
shadow \
|
||||
strict-prototypes
|
||||
|
||||
.for s in ${SRCS:M*.c*:N*.c:N*h}
|
||||
WARNINGS_CXX_SRCS += ${SRCS:M*.c*:N*.c:N*h}
|
||||
.for s in ${WARNINGS_CXX_SRCS:O:u}
|
||||
.for w in ${NO_CXX_WARNINGS}
|
||||
W_$w_${s:T:R}.o=
|
||||
W_$w_${s:T:${TARGET_PREFIX_FILTER:ts:}}.o=
|
||||
.endfor
|
||||
.endfor
|
||||
|
||||
|
0
contrib/bmake/os.sh
Normal file → Executable file
0
contrib/bmake/os.sh
Normal file → Executable file
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: parse.c,v 1.692 2023/01/24 00:24:02 sjg Exp $ */
|
||||
/* $NetBSD: parse.c,v 1.696 2023/02/15 06:52:58 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.692 2023/01/24 00:24:02 sjg Exp $");
|
||||
MAKE_RCSID("$NetBSD: parse.c,v 1.696 2023/02/15 06:52:58 rillig Exp $");
|
||||
|
||||
/*
|
||||
* A file being read.
|
||||
@ -594,7 +594,7 @@ HandleMessage(ParseErrorLevel level, const char *levelName, const char *umsg)
|
||||
return;
|
||||
}
|
||||
|
||||
(void)Var_Subst(umsg, SCOPE_CMDLINE, VARE_WANTRES, &xmsg);
|
||||
xmsg = Var_Subst(umsg, SCOPE_CMDLINE, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
|
||||
Parse_Error(level, "%s", xmsg);
|
||||
@ -913,10 +913,8 @@ ParseDependencyTargetWord(char **pp, const char *lstart)
|
||||
* have been discovered in the initial Var_Subst and
|
||||
* we wouldn't be here.
|
||||
*/
|
||||
FStr val;
|
||||
|
||||
(void)Var_Parse(&cp, SCOPE_CMDLINE,
|
||||
VARE_PARSE_ONLY, &val);
|
||||
FStr val = Var_Parse(&cp, SCOPE_CMDLINE,
|
||||
VARE_PARSE_ONLY);
|
||||
FStr_Done(&val);
|
||||
} else
|
||||
cp++;
|
||||
@ -1792,10 +1790,8 @@ VarCheckSyntax(VarAssignOp type, const char *uvalue, GNode *scope)
|
||||
{
|
||||
if (opts.strict) {
|
||||
if (type != VAR_SUBST && strchr(uvalue, '$') != NULL) {
|
||||
char *expandedValue;
|
||||
|
||||
(void)Var_Subst(uvalue, scope, VARE_PARSE_ONLY,
|
||||
&expandedValue);
|
||||
char *expandedValue = Var_Subst(uvalue,
|
||||
scope, VARE_PARSE_ONLY);
|
||||
/* TODO: handle errors */
|
||||
free(expandedValue);
|
||||
}
|
||||
@ -1821,7 +1817,7 @@ VarAssign_EvalSubst(GNode *scope, const char *name, const char *uvalue,
|
||||
if (!Var_ExistsExpand(scope, name))
|
||||
Var_SetExpand(scope, name, "");
|
||||
|
||||
(void)Var_Subst(uvalue, scope, VARE_KEEP_DOLLAR_UNDEF, &evalue);
|
||||
evalue = Var_Subst(uvalue, scope, VARE_KEEP_DOLLAR_UNDEF);
|
||||
/* TODO: handle errors */
|
||||
|
||||
Var_SetExpand(scope, name, evalue);
|
||||
@ -1890,7 +1886,7 @@ VarAssign_Eval(const char *name, VarAssignOp op, const char *uvalue,
|
||||
static void
|
||||
VarAssignSpecial(const char *name, const char *avalue)
|
||||
{
|
||||
if (strcmp(name, MAKEOVERRIDES) == 0)
|
||||
if (strcmp(name, ".MAKEOVERRIDES") == 0)
|
||||
Main_ExportMAKEFLAGS(false); /* re-export MAKEFLAGS */
|
||||
else if (strcmp(name, ".CURDIR") == 0) {
|
||||
/*
|
||||
@ -1900,9 +1896,9 @@ VarAssignSpecial(const char *name, const char *avalue)
|
||||
*/
|
||||
Dir_InitCur(avalue);
|
||||
Dir_SetPATH();
|
||||
} else if (strcmp(name, MAKE_JOB_PREFIX) == 0)
|
||||
} else if (strcmp(name, ".MAKE.JOB.PREFIX") == 0)
|
||||
Job_SetPrefix();
|
||||
else if (strcmp(name, MAKE_EXPORTED) == 0)
|
||||
else if (strcmp(name, ".MAKE.EXPORTED") == 0)
|
||||
Var_ExportVars(avalue);
|
||||
}
|
||||
|
||||
@ -2166,8 +2162,8 @@ VarContainsWord(const char *varname, const char *word)
|
||||
static void
|
||||
TrackInput(const char *name)
|
||||
{
|
||||
if (!VarContainsWord(MAKE_MAKEFILES, name))
|
||||
Global_Append(MAKE_MAKEFILES, name);
|
||||
if (!VarContainsWord(".MAKE.MAKEFILES", name))
|
||||
Global_Append(".MAKE.MAKEFILES", name);
|
||||
}
|
||||
|
||||
|
||||
@ -2258,7 +2254,7 @@ ParseTraditionalInclude(char *line)
|
||||
|
||||
pp_skip_whitespace(&file);
|
||||
|
||||
(void)Var_Subst(file, SCOPE_CMDLINE, VARE_WANTRES, &all_files);
|
||||
all_files = Var_Subst(file, SCOPE_CMDLINE, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
|
||||
for (file = all_files; !done; file = cp + 1) {
|
||||
@ -2303,7 +2299,7 @@ ParseGmakeExport(char *line)
|
||||
/*
|
||||
* Expand the value before putting it in the environment.
|
||||
*/
|
||||
(void)Var_Subst(value, SCOPE_CMDLINE, VARE_WANTRES, &value);
|
||||
value = Var_Subst(value, SCOPE_CMDLINE, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
|
||||
setenv(variable, value, 1);
|
||||
@ -2880,7 +2876,7 @@ ParseDependencyLine(char *line)
|
||||
* Var_Subst.
|
||||
*/
|
||||
emode = opts.strict ? VARE_WANTRES : VARE_UNDEFERR;
|
||||
(void)Var_Subst(line, SCOPE_CMDLINE, emode, &expanded_line);
|
||||
expanded_line = Var_Subst(line, SCOPE_CMDLINE, emode);
|
||||
/* TODO: handle errors */
|
||||
|
||||
/* Need a fresh list for the target nodes */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: suff.c,v 1.366 2022/03/04 23:17:16 sjg Exp $ */
|
||||
/* $NetBSD: suff.c,v 1.368 2023/02/14 21:38:31 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
@ -115,7 +115,7 @@
|
||||
#include "dir.h"
|
||||
|
||||
/* "@(#)suff.c 8.4 (Berkeley) 3/21/94" */
|
||||
MAKE_RCSID("$NetBSD: suff.c,v 1.366 2022/03/04 23:17:16 sjg Exp $");
|
||||
MAKE_RCSID("$NetBSD: suff.c,v 1.368 2023/02/14 21:38:31 rillig Exp $");
|
||||
|
||||
typedef List SuffixList;
|
||||
typedef ListNode SuffixListNode;
|
||||
@ -1312,9 +1312,7 @@ ExpandChildrenRegular(char *cp, GNode *pgn, GNodeList *members)
|
||||
} else if (*cp == '$') {
|
||||
/* Skip over the variable expression. */
|
||||
const char *nested_p = cp;
|
||||
FStr junk;
|
||||
|
||||
(void)Var_Parse(&nested_p, pgn, VARE_PARSE_ONLY, &junk);
|
||||
FStr junk = Var_Parse(&nested_p, pgn, VARE_PARSE_ONLY);
|
||||
/* TODO: handle errors */
|
||||
if (junk.str == var_Error) {
|
||||
Parse_Error(PARSE_FATAL,
|
||||
@ -1385,7 +1383,7 @@ ExpandChildren(GNodeListNode *cln, GNode *pgn)
|
||||
}
|
||||
|
||||
DEBUG1(SUFF, "Expanding \"%s\"...", cgn->name);
|
||||
(void)Var_Subst(cgn->name, pgn, VARE_UNDEFERR, &cp);
|
||||
cp = Var_Subst(cgn->name, pgn, VARE_UNDEFERR);
|
||||
/* TODO: handle errors */
|
||||
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: trace.c,v 1.32 2022/03/26 14:02:40 rillig Exp $ */
|
||||
/* $NetBSD: trace.c,v 1.33 2023/03/28 14:39:31 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
@ -48,11 +48,11 @@
|
||||
#include "job.h"
|
||||
#include "trace.h"
|
||||
|
||||
MAKE_RCSID("$NetBSD: trace.c,v 1.32 2022/03/26 14:02:40 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: trace.c,v 1.33 2023/03/28 14:39:31 rillig Exp $");
|
||||
|
||||
static FILE *trfile;
|
||||
static pid_t trpid;
|
||||
const char *trwd;
|
||||
static const char *trwd;
|
||||
|
||||
static const char evname[][4] = {
|
||||
"BEG",
|
||||
|
@ -1,6 +1,6 @@
|
||||
# $Id: Makefile,v 1.191 2023/01/24 06:09:49 sjg Exp $
|
||||
# $Id: Makefile,v 1.193 2023/02/25 20:03:25 sjg Exp $
|
||||
#
|
||||
# $NetBSD: Makefile,v 1.331 2023/01/24 00:24:02 sjg Exp $
|
||||
# $NetBSD: Makefile,v 1.333 2023/02/25 19:30:32 sjg Exp $
|
||||
#
|
||||
# Unit tests for make(1)
|
||||
#
|
||||
@ -32,6 +32,21 @@
|
||||
.MAKE.OS?= ${uname -s:L:sh}
|
||||
.MAKE.UID?= ${id -u:L:sh}
|
||||
|
||||
# for many tests we need a TMPDIR that will not collide
|
||||
# with other users.
|
||||
.if ${.OBJDIR} != ${.CURDIR}
|
||||
# easy
|
||||
TMPDIR:= ${.OBJDIR}/tmp
|
||||
.elif defined(TMPDIR)
|
||||
TMPDIR:= ${TMPDIR}/uid${.MAKE.UID}
|
||||
.else
|
||||
TMPDIR:= /tmp/uid${.MAKE.UID}
|
||||
.endif
|
||||
# make sure it exists
|
||||
.if !exist(${TMPDIR})
|
||||
_!= mkdir -p ${TMPDIR}
|
||||
.endif
|
||||
|
||||
# Each test is in a sub-makefile.
|
||||
# Keep the list sorted.
|
||||
# Any test that is commented out must be ignored in
|
||||
@ -406,12 +421,16 @@ TESTS+= varname-dot-make-makefiles
|
||||
TESTS+= varname-dot-make-meta-bailiwick
|
||||
TESTS+= varname-dot-make-meta-created
|
||||
TESTS+= varname-dot-make-meta-files
|
||||
.if ${.MAKE.PATH_FILEMON:Uno:Nktrace:N/dev*} == "" && ${TMPDIR:N/tmp*:N/var/tmp*} != ""
|
||||
# these tests will not work if TMPDIR is or is a subdir of
|
||||
# /tmp or /var/tmp
|
||||
TESTS+= varname-dot-make-meta-ignore_filter
|
||||
TESTS+= varname-dot-make-meta-ignore_paths
|
||||
TESTS+= varname-dot-make-meta-ignore_patterns
|
||||
TESTS+= varname-dot-make-path_filemon
|
||||
.endif
|
||||
TESTS+= varname-dot-make-meta-prefix
|
||||
TESTS+= varname-dot-make-mode
|
||||
TESTS+= varname-dot-make-path_filemon
|
||||
TESTS+= varname-dot-make-pid
|
||||
TESTS+= varname-dot-make-ppid
|
||||
TESTS+= varname-dot-make-save_dollars
|
||||
@ -538,6 +557,9 @@ SED_CMDS.opt-chdir= -e 's,\(nonexistent\).[1-9][0-9]*,\1,' \
|
||||
-e '/name/s,file,File,' \
|
||||
-e 's,no such,No such,' \
|
||||
-e 's,Filename,File name,'
|
||||
|
||||
# meta line numbers can vary based on filemon implementation
|
||||
SED_CMDS.meta-ignore= -e 's,\(\.meta:\) [1-9][0-9]*:,\1 <line>:,'
|
||||
SED_CMDS.opt-debug-graph1= ${STD_SED_CMDS.dg1}
|
||||
SED_CMDS.opt-debug-graph2= ${STD_SED_CMDS.dg2}
|
||||
SED_CMDS.opt-debug-graph3= ${STD_SED_CMDS.dg3}
|
||||
@ -571,6 +593,9 @@ SED_CMDS.var-op-shell+= ${STD_SED_CMDS.white-space}
|
||||
SED_CMDS.vardebug+= -e 's,${.SHELL},</path/to/shell>,'
|
||||
SED_CMDS.varmod-subst-regex+= ${STD_SED_CMDS.regex}
|
||||
SED_CMDS.varparse-errors+= ${STD_SED_CMDS.timestamp}
|
||||
SED_CMDS.varname-dot-make-meta-ignore_filter+= ${SED_CMDS.meta-ignore}
|
||||
SED_CMDS.varname-dot-make-meta-ignore_paths+= ${SED_CMDS.meta-ignore}
|
||||
SED_CMDS.varname-dot-make-meta-ignore_patterns+= ${SED_CMDS.meta-ignore}
|
||||
SED_CMDS.varname-dot-parsedir= -e '/in some cases/ s,^make: "[^"]*,make: "<normalized>,'
|
||||
SED_CMDS.varname-dot-parsefile= -e '/in some cases/ s,^make: "[^"]*,make: "<normalized>,'
|
||||
SED_CMDS.varname-dot-shell= -e 's, = /[^ ]*, = (details omitted),g'
|
||||
@ -713,22 +738,6 @@ LANG= C
|
||||
_MKMSG_TEST= :
|
||||
.endif
|
||||
|
||||
|
||||
# for many tests we need a TMPDIR that will not collide
|
||||
# with other users.
|
||||
.if ${.OBJDIR} != ${.CURDIR}
|
||||
# easy
|
||||
TMPDIR:= ${.OBJDIR}/tmp
|
||||
.elif defined(TMPDIR)
|
||||
TMPDIR:= ${TMPDIR}/uid${.MAKE.UID}
|
||||
.else
|
||||
TMPDIR:= /tmp/uid${.MAKE.UID}
|
||||
.endif
|
||||
# make sure it exists
|
||||
.if !exist(${TMPDIR})
|
||||
_!= mkdir -p ${TMPDIR}
|
||||
.endif
|
||||
|
||||
# Some Linux systems such as Fedora have deprecated egrep in favor of grep -E.
|
||||
.if ${.MAKE.OS:NLinux} == ""
|
||||
EGREP= grep -E
|
||||
@ -768,23 +777,23 @@ LIMIT_RESOURCES?= :
|
||||
|
||||
# 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:,'
|
||||
_SED_CMDS+= -e 's,${TEST_MAKE:S,.,\\.,g},make,'
|
||||
_SED_CMDS+= -e 's,^usage: ${TEST_MAKE:T:S,.,\\.,g} ,usage: make ,'
|
||||
# replace anything after 'stopped in' with unit-tests
|
||||
# Replace anything after 'stopped in' with unit-tests
|
||||
_SED_CMDS+= -e '/stopped/s, /.*, unit-tests,'
|
||||
# Allow the test files to be placed anywhere.
|
||||
_SED_CMDS+= -e 's,\(\.PARSEDIR}\) = `'"/[^']*'"',\1 = <some-dir>,'
|
||||
_SED_CMDS+= -e 's,\(\.INCLUDEDFROMDIR}\) = `'"/[^']*'"',\1 = <some-dir>,'
|
||||
_SED_CMDS+= -e 's,${TMPDIR},<tmpdir>,g'
|
||||
_SED_CMDS+= -e 's,${TMPDIR},<tmpdir>,g' -e 's,${TMPDIR:tA},<tmpdir>,g'
|
||||
# canonicalize ${.OBJDIR} and ${.CURDIR}
|
||||
_SED_CMDS+= -e 's,${.CURDIR},<curdir>,g'
|
||||
.if ${.OBJDIR} != ${.CURDIR}
|
||||
# yes this is inaccurate but none of the tests expect <objdir> anywhere
|
||||
# which we get depending on how MAKEOBJDIR is set.
|
||||
_SED_CMDS+= -e 's,${.OBJDIR},<curdir>,g'
|
||||
_SED_CMDS+= -e 's,${.OBJDIR},<curdir>,g' -e 's,${.OBJDIR:tA},<curdir>,g'
|
||||
.endif
|
||||
_SED_CMDS+= -e 's,${.CURDIR},<curdir>,g'
|
||||
# always pretend .MAKE was called 'make'
|
||||
_SED_CMDS+= -e 's,^${TEST_MAKE:T:S,.,\\.,g}[][0-9]*:,make:,'
|
||||
_SED_CMDS+= -e 's,${TEST_MAKE:S,.,\\.,g},make,'
|
||||
_SED_CMDS+= -e 's,^usage: ${TEST_MAKE:T:S,.,\\.,g} ,usage: make ,'
|
||||
_SED_CMDS+= -e 's,<curdir>/,,g'
|
||||
_SED_CMDS+= -e 's,${UNIT_TESTS:S,.,\\.,g}/,,g'
|
||||
_SED_CMDS+= -e '/MAKE_VERSION/d'
|
||||
|
@ -2,7 +2,6 @@
|
||||
make: *** cmd-interrupt-ordinary removed
|
||||
interrupt-ordinary: ok
|
||||
> cmd-interrupt-phony
|
||||
make: *** cmd-interrupt-phony removed
|
||||
interrupt-phony: ok
|
||||
> cmd-interrupt-precious
|
||||
interrupt-precious: ok
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: cmd-interrupt.mk,v 1.3 2020/11/15 14:07:53 rillig Exp $
|
||||
# $NetBSD: cmd-interrupt.mk,v 1.4 2023/03/18 22:20:12 sjg Exp $
|
||||
#
|
||||
# Tests for interrupting a command.
|
||||
#
|
||||
@ -30,7 +30,7 @@ interrupt-ordinary:
|
||||
interrupt-phony: .PHONY
|
||||
@${.MAKE} ${MAKEFLAGS} -f ${MAKEFILE} cmd-interrupt-phony || true
|
||||
# The ././ is necessary to work around the file cache.
|
||||
@echo ${.TARGET}: ${exists(././cmd-interrupt-phony) :? error : ok }
|
||||
@echo ${.TARGET}: ${exists(././cmd-interrupt-phony) :? ok : error }
|
||||
|
||||
interrupt-precious: .PRECIOUS
|
||||
@${.MAKE} ${MAKEFLAGS} -f ${MAKEFILE} cmd-interrupt-precious || true
|
||||
|
@ -1,15 +1,15 @@
|
||||
CondParser_Eval: !(${:UINF} > 1e100)
|
||||
make: "cond-cmp-numeric.mk" line 11: Comparison with '>' requires both operands 'INF' and '1e100' to be numeric
|
||||
make: "cond-cmp-numeric.mk" line 15: Comparison with '>' requires both operands 'INF' and '1e100' to be numeric
|
||||
CondParser_Eval: ${:UNaN} > NaN
|
||||
make: "cond-cmp-numeric.mk" line 16: Comparison with '>' requires both operands 'NaN' and 'NaN' to be numeric
|
||||
make: "cond-cmp-numeric.mk" line 21: Comparison with '>' requires both operands 'NaN' and 'NaN' to be numeric
|
||||
CondParser_Eval: !(${:UNaN} == NaN)
|
||||
Comparing "NaN" == "NaN"
|
||||
CondParser_Eval: 123 ! 123
|
||||
make: "cond-cmp-numeric.mk" line 34: Malformed conditional (123 ! 123)
|
||||
make: "cond-cmp-numeric.mk" line 38: Malformed conditional (123 ! 123)
|
||||
CondParser_Eval: ${:U 123} < 124
|
||||
Comparing 123.000000 < 124.000000
|
||||
CondParser_Eval: ${:U123 } < 124
|
||||
make: "cond-cmp-numeric.mk" line 50: Comparison with '<' requires both operands '123 ' and '124' to be numeric
|
||||
make: "cond-cmp-numeric.mk" line 54: Comparison with '<' requires both operands '123 ' and '124' to be numeric
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
||||
|
@ -1,6 +1,9 @@
|
||||
# $NetBSD: cond-cmp-numeric.mk,v 1.6 2022/09/04 22:55:00 rillig Exp $
|
||||
# $NetBSD: cond-cmp-numeric.mk,v 1.7 2023/03/04 08:07:29 rillig Exp $
|
||||
#
|
||||
# Tests for numeric comparisons in .if conditions.
|
||||
#
|
||||
# See also:
|
||||
# cond-token-number.mk
|
||||
|
||||
.MAKEFLAGS: -dc
|
||||
|
||||
@ -8,11 +11,13 @@
|
||||
|
||||
# Even if strtod(3) parses "INF" as +Infinity, make does not accept this
|
||||
# since it is not really a number; see TryParseNumber.
|
||||
# expect+1: Comparison with '>' requires both operands 'INF' and '1e100' to be numeric
|
||||
.if !(${:UINF} > 1e100)
|
||||
. error
|
||||
.endif
|
||||
|
||||
# Neither is NaN a number; see TryParseNumber.
|
||||
# expect+1: Comparison with '>' requires both operands 'NaN' and 'NaN' to be numeric
|
||||
.if ${:UNaN} > NaN
|
||||
. error
|
||||
.endif
|
||||
@ -29,8 +34,7 @@
|
||||
# whether the operator is valid, leaving the rest of the work to the
|
||||
# evaluation functions EvalCompareNum and EvalCompareStr. Ensure that this
|
||||
# parse error is properly reported.
|
||||
#
|
||||
# XXX: The warning message does not mention the actual operator.
|
||||
# expect+1: Malformed conditional (123 ! 123)
|
||||
.if 123 ! 123
|
||||
. error
|
||||
.else
|
||||
@ -54,4 +58,3 @@
|
||||
.endif
|
||||
|
||||
all:
|
||||
@:;
|
||||
|
@ -1,11 +1,11 @@
|
||||
make: "cond-cmp-string.mk" line 18: Malformed conditional (str != str)
|
||||
make: "cond-cmp-string.mk" line 42: Malformed conditional ("string" != "str""ing")
|
||||
make: "cond-cmp-string.mk" line 49: Malformed conditional (!("value" = "value"))
|
||||
make: "cond-cmp-string.mk" line 56: Malformed conditional (!("value" === "value"))
|
||||
make: "cond-cmp-string.mk" line 113: Comparison with '<' requires both operands 'string' and 'string' to be numeric
|
||||
make: "cond-cmp-string.mk" line 120: Comparison with '<=' requires both operands 'string' and 'string' to be numeric
|
||||
make: "cond-cmp-string.mk" line 127: Comparison with '>' requires both operands 'string' and 'string' to be numeric
|
||||
make: "cond-cmp-string.mk" line 134: Comparison with '>=' requires both operands 'string' and 'string' to be numeric
|
||||
make: "cond-cmp-string.mk" line 19: Malformed conditional (str != str)
|
||||
make: "cond-cmp-string.mk" line 44: Malformed conditional ("string" != "str""ing")
|
||||
make: "cond-cmp-string.mk" line 52: Malformed conditional (!("value" = "value"))
|
||||
make: "cond-cmp-string.mk" line 60: Malformed conditional (!("value" === "value"))
|
||||
make: "cond-cmp-string.mk" line 118: Comparison with '<' requires both operands 'string' and 'string' to be numeric
|
||||
make: "cond-cmp-string.mk" line 126: Comparison with '<=' requires both operands 'string' and 'string' to be numeric
|
||||
make: "cond-cmp-string.mk" line 134: Comparison with '>' requires both operands 'string' and 'string' to be numeric
|
||||
make: "cond-cmp-string.mk" line 142: Comparison with '>=' requires both operands 'string' and 'string' to be numeric
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: cond-cmp-string.mk,v 1.16 2022/05/08 06:51:27 rillig Exp $
|
||||
# $NetBSD: cond-cmp-string.mk,v 1.17 2023/03/28 14:38:29 rillig Exp $
|
||||
#
|
||||
# Tests for string comparisons in .if conditions.
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
|
||||
# The left-hand side of the comparison must be enclosed in quotes.
|
||||
# This one is not enclosed in quotes and thus generates an error message.
|
||||
# expect+1: Malformed conditional (str != str)
|
||||
.if str != str
|
||||
. error
|
||||
.endif
|
||||
@ -39,6 +40,7 @@
|
||||
|
||||
# It is not possible to concatenate two string literals to form a single
|
||||
# string. In C, Python and the shell this is possible, but not in make.
|
||||
# expect+1: Malformed conditional ("string" != "str""ing")
|
||||
.if "string" != "str""ing"
|
||||
. error
|
||||
.else
|
||||
@ -46,6 +48,7 @@
|
||||
.endif
|
||||
|
||||
# There is no = operator for strings.
|
||||
# expect+1: Malformed conditional (!("value" = "value"))
|
||||
.if !("value" = "value")
|
||||
. error
|
||||
.else
|
||||
@ -53,6 +56,7 @@
|
||||
.endif
|
||||
|
||||
# There is no === operator for strings either.
|
||||
# expect+1: Malformed conditional (!("value" === "value"))
|
||||
.if !("value" === "value")
|
||||
. error
|
||||
.else
|
||||
@ -110,6 +114,7 @@
|
||||
.endif
|
||||
|
||||
# Strings cannot be compared relationally, only for equality.
|
||||
# expect+1: Comparison with '<' requires both operands 'string' and 'string' to be numeric
|
||||
.if "string" < "string"
|
||||
. error
|
||||
.else
|
||||
@ -117,6 +122,7 @@
|
||||
.endif
|
||||
|
||||
# Strings cannot be compared relationally, only for equality.
|
||||
# expect+1: Comparison with '<=' requires both operands 'string' and 'string' to be numeric
|
||||
.if "string" <= "string"
|
||||
. error
|
||||
.else
|
||||
@ -124,6 +130,7 @@
|
||||
.endif
|
||||
|
||||
# Strings cannot be compared relationally, only for equality.
|
||||
# expect+1: Comparison with '>' requires both operands 'string' and 'string' to be numeric
|
||||
.if "string" > "string"
|
||||
. error
|
||||
.else
|
||||
@ -131,6 +138,7 @@
|
||||
.endif
|
||||
|
||||
# Strings cannot be compared relationally, only for equality.
|
||||
# expect+1: Comparison with '>=' requires both operands 'string' and 'string' to be numeric
|
||||
.if "string" >= "string"
|
||||
. error
|
||||
.else
|
||||
|
@ -1,5 +1,5 @@
|
||||
make: "cond-func-empty.mk" line 149: Unclosed variable "WORD"
|
||||
make: "cond-func-empty.mk" line 149: Malformed conditional (empty(WORD)
|
||||
make: "cond-func-empty.mk" line 153: Unclosed variable "WORD"
|
||||
make: "cond-func-empty.mk" line 153: Malformed conditional (empty(WORD)
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: cond-func-empty.mk,v 1.17 2021/12/28 22:13:56 rillig Exp $
|
||||
# $NetBSD: cond-func-empty.mk,v 1.18 2023/03/04 21:15:30 rillig Exp $
|
||||
#
|
||||
# Tests for the empty() function in .if conditions, which tests a variable
|
||||
# expression for emptiness.
|
||||
@ -24,11 +24,13 @@ WORD= word
|
||||
. error
|
||||
.endif
|
||||
|
||||
# The :S modifier replaces the empty value with an actual word. The
|
||||
# expression is now no longer empty, but it is still based on an undefined
|
||||
# variable (DEF_UNDEF). There are a few variable modifiers that turn an
|
||||
# undefined expression into a defined expression, among them :U and :D, but
|
||||
# not :S.
|
||||
# The :S modifier replaces the empty value with an actual word. After
|
||||
# applying the :S modifier to the expression, it value is 'empty', so it is
|
||||
# no longer empty, but it is still based on an undefined variable. There are
|
||||
# a few modifiers that turn an undefined expression into a defined expression,
|
||||
# among them :U and :D, but not :S. Therefore, at the end of evaluating the
|
||||
# expression, the expression is still undefined, so its final value becomes an
|
||||
# empty string.
|
||||
#
|
||||
# XXX: This is hard to explain to someone who doesn't know these
|
||||
# implementation details.
|
||||
@ -45,15 +47,17 @@ WORD= word
|
||||
. error
|
||||
.endif
|
||||
|
||||
# And now to the surprising part. Applying the following :S modifier to the
|
||||
# undefined expression makes it non-empty, but the expression is still in
|
||||
# state DEF_UNDEF. The :U modifier that follows only looks at the state
|
||||
# DEF_UNDEF to decide whether the variable is defined or not. This kind of
|
||||
# makes sense since the :U modifier tests the _variable_, not the
|
||||
# When an expression is based on an undefined variable, its modifiers interact
|
||||
# in sometimes surprising ways. Applying the :S modifier to the undefined
|
||||
# expression makes its value non-empty, but doesn't change that the expression
|
||||
# is based on an undefined variable. The :U modifier that follows only looks
|
||||
# at the definedness state to decide whether the variable is defined or not.
|
||||
# This kind of makes sense since the :U modifier tests the _variable_, not the
|
||||
# _expression_.
|
||||
#
|
||||
# But since the variable was undefined to begin with, the fallback value from
|
||||
# the :U modifier is used in this expression.
|
||||
# Since the variable was undefined to begin with, the fallback value from the
|
||||
# :U modifier is used in this expression, instead of keeping the 'value' from
|
||||
# the :S modifier.
|
||||
#
|
||||
.if ${UNDEF:S,^$,value,W:Ufallback} != "fallback"
|
||||
. error
|
||||
@ -90,8 +94,8 @@ WORD= word
|
||||
# neither leading nor trailing spaces are trimmed in the argument of the
|
||||
# function. If the spaces were trimmed, the variable name would be "" and
|
||||
# that variable is indeed undefined. Since CondParser_FuncCallEmpty calls
|
||||
# Var_Parse without VARE_UNDEFERR, the value of the undefined variable is
|
||||
# returned as an empty string.
|
||||
# Var_Parse without VARE_UNDEFERR, the value of the undefined variable ""
|
||||
# would be returned as an empty string.
|
||||
${:U }= space
|
||||
.if empty( )
|
||||
. error
|
||||
@ -120,9 +124,9 @@ ${:U }= space
|
||||
. error
|
||||
.endif
|
||||
|
||||
# Ensure that variable expressions that appear as part of the argument are
|
||||
# properly parsed. Typical use cases for this are .for loops, which are
|
||||
# expanded to exactly these ${:U} expressions.
|
||||
# Ensure that variable expressions that appear as part of the function call
|
||||
# argument are properly parsed. Typical use cases for this are .for loops,
|
||||
# which are expanded to exactly these ${:U} expressions.
|
||||
#
|
||||
# If everything goes well, the argument expands to "WORD", and that variable
|
||||
# is defined at the beginning of this file. The surrounding 'W' and 'D'
|
||||
@ -159,10 +163,9 @@ ${:U WORD }= variable name with spaces
|
||||
# Since at least 1993, the manual page claimed that irrelevant parts of
|
||||
# conditions were not evaluated, but that was wrong for a long time. The
|
||||
# expressions in irrelevant parts of the condition were actually evaluated,
|
||||
# they just allowed undefined variables to be used in the conditions, and the
|
||||
# result of evaluating them was not used further. These unnecessary
|
||||
# evaluations were fixed in several commits, starting with var.c 1.226 from
|
||||
# 2020-07-02.
|
||||
# they just allowed undefined variables to be used in the conditions. These
|
||||
# unnecessary evaluations were fixed in several commits, starting with var.c
|
||||
# 1.226 from 2020-07-02.
|
||||
#
|
||||
# In this example, the variable "VARNAME2" is not defined, so evaluation of
|
||||
# the condition should have stopped at this point, and the rest of the
|
||||
|
@ -7,10 +7,7 @@ expected M pattern
|
||||
expected or
|
||||
expected or exists
|
||||
expected or empty
|
||||
defined(V42) && ${V42} > 0: Ok
|
||||
defined(V66) && ( "${iV2}" < ${V42} ): Ok
|
||||
1 || ${iV1} < ${V42}: Ok
|
||||
1 || ${iV2:U2} < ${V42}: Ok
|
||||
0 || ${iV1} <= ${V42}: Ok
|
||||
0 || ${iV2:U2} < ${V42}: Ok
|
||||
exit status 0
|
||||
make: "cond-short.mk" line 214: Comparison with '<' requires both operands '' and '42' to be numeric
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: cond-short.mk,v 1.19 2021/12/27 18:54:19 rillig Exp $
|
||||
# $NetBSD: cond-short.mk,v 1.20 2023/03/04 13:42:36 rillig Exp $
|
||||
#
|
||||
# Demonstrates that in conditions, the right-hand side of an && or ||
|
||||
# is only evaluated if it can actually influence the result.
|
||||
@ -135,28 +135,32 @@ VAR= # empty again, for the following tests
|
||||
.elif ${echo "unexpected nested or" 1>&2 :L:sh}
|
||||
.endif
|
||||
|
||||
# make sure these do not cause complaint
|
||||
#.MAKEFLAGS: -dc
|
||||
|
||||
# TODO: Rewrite this whole section and check all the conditions and variables.
|
||||
# Several of the assumptions are probably wrong here.
|
||||
# TODO: replace 'x=' with '.info' or '.error'.
|
||||
V42= 42
|
||||
iV1= ${V42}
|
||||
iV2= ${V66}
|
||||
NUMBER= 42
|
||||
INDIR_NUMBER= ${NUMBER}
|
||||
INDIR_UNDEF= ${UNDEF}
|
||||
|
||||
.if defined(V42) && ${V42} > 0
|
||||
x= Ok
|
||||
.if defined(NUMBER) && ${NUMBER} > 0
|
||||
.else
|
||||
x= Fail
|
||||
. error
|
||||
.endif
|
||||
x!= echo 'defined(V42) && $${V42} > 0: $x' >&2; echo
|
||||
|
||||
# With cond.c 1.76 from 2020-07-03, the following condition triggered a
|
||||
# warning: "String comparison operator should be either == or !=".
|
||||
# This was because the variable expression ${iV2} was defined, but the
|
||||
# contained variable V66 was undefined. The left-hand side of the comparison
|
||||
# therefore evaluated to the string "${V66}", which is obviously not a number.
|
||||
# Starting with var.c 1.226 from from 2020-07-02, the following condition
|
||||
# triggered a warning: "String comparison operator should be either == or !=".
|
||||
#
|
||||
# The left-hand side of the '&&' evaluated to false, which should have made
|
||||
# the right-hand side irrelevant.
|
||||
#
|
||||
# On the right-hand side of the '&&', the expression ${INDIR_UNDEF} was
|
||||
# defined and had the value '${UNDEF}', but the nested variable UNDEF was
|
||||
# undefined. The right hand side "${INDIR_UNDEF}" still needed to be parsed,
|
||||
# and in parse-only mode, the "value" of the parsed expression was the
|
||||
# uninterpreted variable value, in this case '${UNDEF}'. And even though the
|
||||
# right hand side of the '&&' should have been irrelevant, the two sides of
|
||||
# the comparison were still parsed and evaluated. Comparing these two values
|
||||
# numerically was not possible since the string '${UNDEF}' is not a number,
|
||||
# so the comparison fell back to string comparison, which then complained
|
||||
# about the '>' operator.
|
||||
#
|
||||
# This was fixed in cond.c 1.79 from 2020-07-09 by not evaluating irrelevant
|
||||
# comparisons. Instead, they are only parsed and then discarded.
|
||||
@ -164,59 +168,77 @@ x!= echo 'defined(V42) && $${V42} > 0: $x' >&2; echo
|
||||
# At that time, there was not enough debug logging to see the details in the
|
||||
# -dA log. To actually see it, add debug logging at the beginning and end of
|
||||
# Var_Parse.
|
||||
.if defined(V66) && ( ${iV2} < ${V42} )
|
||||
x= Fail
|
||||
.else
|
||||
x= Ok
|
||||
.if defined(UNDEF) && ${INDIR_UNDEF} < ${NUMBER}
|
||||
. error
|
||||
.endif
|
||||
# XXX: This condition doesn't match the one above. The quotes are missing
|
||||
# above. This is a crucial detail since without quotes, the variable
|
||||
# expression ${iV2} evaluates to "${V66}", and with quotes, it evaluates to ""
|
||||
# since undefined variables are allowed and expand to an empty string.
|
||||
x!= echo 'defined(V66) && ( "$${iV2}" < $${V42} ): $x' >&2; echo
|
||||
|
||||
.if 1 || ${iV1} < ${V42}
|
||||
x= Ok
|
||||
.else
|
||||
x= Fail
|
||||
# Adding a ':U' modifier to the irrelevant expression didn't help, as that
|
||||
# expression was only parsed, not evaluated. The resulting literal string
|
||||
# '${INDIR_UNDEF:U2}' was not numeric either, for the same reason as above.
|
||||
.if defined(UNDEF) && ${INDIR_UNDEF:U2} < ${NUMBER}
|
||||
. error
|
||||
.endif
|
||||
x!= echo '1 || $${iV1} < $${V42}: $x' >&2; echo
|
||||
|
||||
# With cond.c 1.76 from 2020-07-03, the following condition triggered a
|
||||
# warning: "String comparison operator should be either == or !=".
|
||||
# This was because the variable expression ${iV2} was defined, but the
|
||||
# contained variable V66 was undefined. The left-hand side of the comparison
|
||||
# therefore evaluated to the string "${V66}", which is obviously not a number.
|
||||
# Enclosing the expression in double quotes changes how that expression is
|
||||
# evaluated. In irrelevant expressions that are enclosed in double quotes,
|
||||
# expressions based on undefined variables are allowed and evaluate to an
|
||||
# empty string.
|
||||
#
|
||||
# This was fixed in cond.c 1.79 from 2020-07-09 by not evaluating irrelevant
|
||||
# comparisons. Instead, they are only parsed and then discarded.
|
||||
# The manual page stated from at least 1993 on that irrelevant conditions were
|
||||
# not evaluated, but that was wrong. These conditions were evaluated, the
|
||||
# only difference was that undefined variables in them didn't trigger an
|
||||
# error. Since numeric conditions are quite rare, this subtle difference
|
||||
# didn't catch much attention, as most other conditions such as pattern
|
||||
# matches or equality comparisons worked fine and never produced error
|
||||
# messages.
|
||||
.if defined(UNDEF) && "${INDIR_UNDEF}" < ${NUMBER}
|
||||
. error
|
||||
.endif
|
||||
|
||||
# Since the condition is relevant, the indirect undefined variable is
|
||||
# evaluated as usual, resolving nested undefined expressions to an empty
|
||||
# string.
|
||||
#
|
||||
# At that time, there was not enough debug logging to see the details in the
|
||||
# -dA log. To actually see it, add debug logging at the beginning and end of
|
||||
# Var_Parse.
|
||||
.if 1 || ${iV2:U2} < ${V42}
|
||||
x= Ok
|
||||
# Comparing an empty string numerically is not possible, however, make has an
|
||||
# ugly hack in TryParseNumber that treats an empty string as a valid numerical
|
||||
# value, thus hiding bugs in the makefile.
|
||||
.if ${INDIR_UNDEF} < ${NUMBER}
|
||||
# only due to the ugly hack
|
||||
.else
|
||||
x= Fail
|
||||
. error
|
||||
.endif
|
||||
x!= echo '1 || $${iV2:U2} < $${V42}: $x' >&2; echo
|
||||
|
||||
# the same expressions are fine when the lhs is expanded
|
||||
# ${iV1} expands to 42
|
||||
.if 0 || ${iV1} <= ${V42}
|
||||
x= Ok
|
||||
# Due to the quotes around the left-hand side of the '<', the operand is
|
||||
# marked as a string, thus preventing a numerical comparison.
|
||||
#
|
||||
# expect+1: Comparison with '<' requires both operands '' and '42' to be numeric
|
||||
.if "${INDIR_UNDEF}" < ${NUMBER}
|
||||
. info yes
|
||||
.else
|
||||
x= Fail
|
||||
. info no
|
||||
.endif
|
||||
x!= echo '0 || $${iV1} <= $${V42}: $x' >&2; echo
|
||||
|
||||
# ${iV2:U2} expands to 2
|
||||
.if 0 || ${iV2:U2} < ${V42}
|
||||
x= Ok
|
||||
# The right-hand side of '||' is irrelevant and thus not evaluated.
|
||||
.if 1 || ${INDIR_NUMBER} < ${NUMBER}
|
||||
.else
|
||||
x= Fail
|
||||
. error
|
||||
.endif
|
||||
x!= echo '0 || $${iV2:U2} < $${V42}: $x' >&2; echo
|
||||
|
||||
# The right-hand side of '||' is relevant and thus evaluated normally.
|
||||
.if 0 || ${INDIR_NUMBER} < ${NUMBER}
|
||||
. error
|
||||
.endif
|
||||
|
||||
# The right-hand side of '||' evaluates to an empty string, as the variable
|
||||
# 'INDIR_UNDEF' is defined, therefore the modifier ':U2' has no effect.
|
||||
# Comparing an empty string numerically is not possible, however, make has an
|
||||
# ugly hack in TryParseNumber that treats an empty string as a valid numerical
|
||||
# value, thus hiding bugs in the makefile.
|
||||
.if 0 || ${INDIR_UNDEF:U2} < ${NUMBER}
|
||||
# only due to the ugly hack
|
||||
.else
|
||||
. error
|
||||
.endif
|
||||
|
||||
|
||||
# The right-hand side of the '&&' is irrelevant since the left-hand side
|
||||
# already evaluates to false. Before cond.c 1.79 from 2020-07-09, it was
|
||||
@ -229,8 +251,8 @@ x!= echo '0 || $${iV2:U2} < $${V42}: $x' >&2; echo
|
||||
|
||||
# Ensure that irrelevant conditions do not influence the result of the whole
|
||||
# condition. As of cond.c 1.302 from 2021-12-11, an irrelevant function call
|
||||
# evaluates to true (see CondParser_FuncCall and CondParser_FuncCallEmpty), an
|
||||
# irrelevant comparison evaluates to false (see CondParser_Comparison).
|
||||
# evaluated to true (see CondParser_FuncCall and CondParser_FuncCallEmpty), an
|
||||
# irrelevant comparison evaluated to false (see CondParser_Comparison).
|
||||
#
|
||||
# An irrelevant true bubbles up to the outermost CondParser_And, where it is
|
||||
# ignored. An irrelevant false bubbles up to the outermost CondParser_Or,
|
||||
|
@ -2,7 +2,6 @@ make: "cond-token-number.mk" line 15: Malformed conditional (-0)
|
||||
make: "cond-token-number.mk" line 25: Malformed conditional (+0)
|
||||
make: "cond-token-number.mk" line 35: Malformed conditional (!-1)
|
||||
make: "cond-token-number.mk" line 45: Malformed conditional (!+1)
|
||||
make: "cond-token-number.mk" line 89: End of the tests.
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: cond-token-number.mk,v 1.7 2022/01/02 02:57:39 rillig Exp $
|
||||
# $NetBSD: cond-token-number.mk,v 1.8 2023/03/04 08:07:29 rillig Exp $
|
||||
#
|
||||
# Tests for number tokens in .if conditions.
|
||||
#
|
||||
@ -85,7 +85,21 @@ HEX= dead
|
||||
. error
|
||||
.endif
|
||||
|
||||
# Ensure that parsing continues until here.
|
||||
.info End of the tests.
|
||||
# Very small numbers round to 0.
|
||||
.if 12345e-400
|
||||
. error
|
||||
.endif
|
||||
.if 12345e-200
|
||||
.else
|
||||
. error
|
||||
.endif
|
||||
|
||||
all: # nothing
|
||||
# Very large numbers round up to infinity on IEEE 754 implementations, or to
|
||||
# the largest representable number (VAX); in particular, make does not fall
|
||||
# back to checking whether a variable of that name is defined.
|
||||
.if 12345e400
|
||||
.else
|
||||
. error
|
||||
.endif
|
||||
|
||||
all:
|
||||
|
@ -49,6 +49,7 @@ make: "cond-token-plain.mk" line 172: Now the variable '\\' is defined.
|
||||
CondParser_Eval: "unquoted\"quoted" != unquoted"quoted
|
||||
Comparing "unquoted"quoted" != "unquoted"quoted"
|
||||
CondParser_Eval: $$$$$$$$ != ""
|
||||
make: "cond-token-plain.mk" line 186: Malformed conditional ($$$$$$$$ != "")
|
||||
CondParser_Eval: left == right
|
||||
make: "cond-token-plain.mk" line 195: Malformed conditional (left == right)
|
||||
CondParser_Eval: ${0:?:} || left == right
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: cond-token-plain.mk,v 1.16 2022/09/25 12:51:37 rillig Exp $
|
||||
# $NetBSD: cond-token-plain.mk,v 1.17 2023/02/14 20:49:09 rillig Exp $
|
||||
#
|
||||
# Tests for plain tokens (that is, string literals without quotes)
|
||||
# in .if conditions. These are also called bare words.
|
||||
@ -89,7 +89,7 @@
|
||||
# a coincidence that the '!' is both used in the '!=' comparison operator
|
||||
# as well as for negating a comparison result.
|
||||
#
|
||||
# The boolean operators '&' and '|' don't terminate a comparison operand.
|
||||
# The characters '&' and '|' are part of the comparison operand.
|
||||
.if ${:Uvar}&&name != "var&&name"
|
||||
. error
|
||||
.endif
|
||||
@ -97,8 +97,8 @@
|
||||
. error
|
||||
.endif
|
||||
|
||||
# A bare word may appear alone in a condition, without any comparison
|
||||
# operator. It is implicitly converted into defined(bare).
|
||||
# A bare word may occur alone in a condition, without any comparison
|
||||
# operator. It is interpreted as the function call 'defined(bare)'.
|
||||
.if bare
|
||||
. error
|
||||
.else
|
||||
|
@ -1,7 +1,10 @@
|
||||
make: "cond-undef-lint.mk" line 23: Variable "UNDEF" is undefined
|
||||
make: "cond-undef-lint.mk" line 23: Malformed conditional (${UNDEF})
|
||||
make: "cond-undef-lint.mk" line 38: Variable "UNDEF" is undefined
|
||||
make: "cond-undef-lint.mk" line 38: Variable "VAR." is undefined
|
||||
make: "cond-undef-lint.mk" line 38: Malformed conditional (${VAR.${UNDEF}})
|
||||
make: "cond-undef-lint.mk" line 49: Variable "VAR.defined" is undefined
|
||||
make: "cond-undef-lint.mk" line 49: Malformed conditional (${VAR.${DEF}})
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
||||
|
@ -1,3 +1,27 @@
|
||||
Var_Parse: ${UNDEF1} (eval-defined)
|
||||
Global: .ALLTARGETS = all
|
||||
Global: .ALLTARGETS = all ${DEF2}
|
||||
Global: .ALLTARGETS = all ${DEF2} a-${DEF2}-b
|
||||
Global: .ALLTARGETS = all ${DEF2} a-${DEF2}-b ${UNDEF3}
|
||||
Global: .ALLTARGETS = all ${DEF2} a-${DEF2}-b ${UNDEF3} 1-${INDIRECT_1}-1
|
||||
Global: INDIRECT_1 = 2-$${INDIRECT_2}-2
|
||||
Global: INDIRECT_2 = 3-$${INDIRECT_3}-3
|
||||
Global: INDIRECT_3 = indirect
|
||||
Global: UNDEF1 = undef1
|
||||
Global: DEF2 = def2
|
||||
Global: .ALLTARGETS = all ${DEF2} a-${DEF2}-b ${UNDEF3} 1-${INDIRECT_1}-1 $$)
|
||||
Var_Parse: ${:U\$)}: (eval-defined)
|
||||
Evaluating modifier ${:U...} on value "" (eval-defined, undefined)
|
||||
Result of ${:U\$)} is "$)" (eval-defined, defined)
|
||||
Global: .ALLTARGETS = all ${DEF2} a-${DEF2}-b ${UNDEF3} 1-${INDIRECT_1}-1 $$) undef1
|
||||
Global: .ALLTARGETS = all ${DEF2} a-${DEF2}-b ${UNDEF3} 1-${INDIRECT_1}-1 $$) undef1 def2
|
||||
Global: .ALLTARGETS = all ${DEF2} a-${DEF2}-b ${UNDEF3} 1-${INDIRECT_1}-1 $$) undef1 def2 a-def2-b
|
||||
Var_Parse: $INDIRECT_2-2-1 $): (parse-only)
|
||||
Global: .ALLTARGETS = all ${DEF2} a-${DEF2}-b ${UNDEF3} 1-${INDIRECT_1}-1 $$) undef1 def2 a-def2-b 1-2-$INDIRECT_2-2-1
|
||||
Var_Parse: $): (parse-only)
|
||||
Global: .ALLTARGETS = all ${DEF2} a-${DEF2}-b ${UNDEF3} 1-${INDIRECT_1}-1 $$) undef1 def2 a-def2-b 1-2-$INDIRECT_2-2-1 $)
|
||||
Global: .MAKEFLAGS = -r -k -d v -d
|
||||
Global: .MAKEFLAGS = -r -k -d v -d 0
|
||||
make: Malformed variable expression at "$)"
|
||||
def2
|
||||
a-def2-b
|
||||
|
@ -1,14 +1,16 @@
|
||||
# $NetBSD: dep-var.mk,v 1.6 2021/04/04 10:13:09 rillig Exp $
|
||||
# $NetBSD: dep-var.mk,v 1.7 2023/02/13 21:01:46 rillig Exp $
|
||||
#
|
||||
# Tests for variable references in dependency declarations.
|
||||
#
|
||||
# Uh oh, this feels so strange that probably nobody uses it. But it seems to
|
||||
# be the only way to reach the lower half of SuffExpandChildren.
|
||||
|
||||
# XXX: The -dv log says:
|
||||
# Var_Parse: ${UNDEF1} with VARE_UNDEFERR|VARE_WANTRES
|
||||
# but no error message is generated for this line.
|
||||
# The variable expression ${UNDEF1} simply expands to an empty string.
|
||||
.MAKEFLAGS: -dv
|
||||
|
||||
# expect: Var_Parse: ${UNDEF1} (eval-defined)
|
||||
# Even though undefined expressions should lead to errors, no error message is
|
||||
# generated for this line. The variable expression ${UNDEF1} simply expands
|
||||
# to an empty string.
|
||||
all: ${UNDEF1}
|
||||
|
||||
# Using a double dollar in order to circumvent immediate variable expansion
|
||||
@ -20,8 +22,8 @@ all: ${UNDEF1}
|
||||
all: $${DEF2} a-$${DEF2}-b
|
||||
|
||||
# This variable is not defined at all.
|
||||
# XXX: The -dv log says:
|
||||
# Var_Parse: ${UNDEF3} with VARE_UNDEFERR|VARE_WANTRES
|
||||
# XXX: The -dv log says later when expanding the sources of 'all':
|
||||
# Var_Parse: ${UNDEF3} (eval-defined)
|
||||
# but no error message is generated for this line, just like for UNDEF1.
|
||||
# The variable expression ${UNDEF3} simply expands to an empty string.
|
||||
all: $${UNDEF3}
|
||||
@ -81,8 +83,13 @@ all: $$$$)
|
||||
# Since 2020-09-13, this generates a parse error in lint mode (-dL), but not
|
||||
# in normal mode since ParseDependency does not handle any errors after
|
||||
# calling Var_Parse.
|
||||
# expect: Var_Parse: ${:U\$)}: (eval-defined)
|
||||
# expect: Var_Parse: $INDIRECT_2-2-1 $): (parse-only)
|
||||
# expect: Var_Parse: $): (parse-only)
|
||||
undef1 def2 a-def2-b 1-2-$$INDIRECT_2-2-1 ${:U\$)}:
|
||||
@echo ${.TARGET:Q}
|
||||
|
||||
.MAKEFLAGS: -d0
|
||||
|
||||
# XXX: Why is the exit status still 0, even though Parse_Error is called
|
||||
# with PARSE_FATAL in SuffExpandChildren?
|
||||
|
@ -7,10 +7,8 @@ make: *** deptgt-delete_on_error-regular removed
|
||||
make: *** deptgt-delete_on_error-regular-delete removed
|
||||
> deptgt-delete_on_error-phony; false
|
||||
*** Error code 1 (continuing)
|
||||
make: *** deptgt-delete_on_error-phony removed
|
||||
> deptgt-delete_on_error-phony-delete; false
|
||||
*** Error code 1 (continuing)
|
||||
make: *** deptgt-delete_on_error-phony-delete removed
|
||||
> deptgt-delete_on_error-precious; false
|
||||
*** Error code 1 (continuing)
|
||||
> deptgt-delete_on_error-precious-delete; false
|
||||
|
63
contrib/bmake/unit-tests/meta-ignore.inc
Normal file
63
contrib/bmake/unit-tests/meta-ignore.inc
Normal file
@ -0,0 +1,63 @@
|
||||
# $NetBSD: meta-ignore.inc,v 1.2 2023/02/25 19:30:32 sjg Exp $
|
||||
|
||||
# common logic for testing .MAKE.META.IGNORE_*
|
||||
|
||||
# we want a directory outside of .OBJDIR to drop a file
|
||||
# that our meta file refers to.
|
||||
# Note: these tests will not work if TMPDIR is /tmp or /var/tmp
|
||||
# or a subdir thereof
|
||||
IGNORE:= ${TMPDIR}/ignore
|
||||
OBJ:= ${TMPDIR}/obj
|
||||
|
||||
# this is always ignored so make sure it isn't used above
|
||||
TMPDIR= /tmp/nothanks
|
||||
|
||||
all: one two three
|
||||
|
||||
setup:
|
||||
@mkdir -p ${IGNORE} ${OBJ}
|
||||
@echo > ${IGNORE}/check
|
||||
@rm -f ${OBJ}/check-ignore
|
||||
|
||||
makefile:= ${.INCLUDEDFROMDIR}/${.INCLUDEDFROMFILE}
|
||||
TEST:= ${.INCLUDEDFROMFILE:R:C,.*meta-,,:S,-,_,g:tu}
|
||||
|
||||
DESC.one= Initialize check-ignore.meta
|
||||
DESC.two= Use .MAKE.META.${TEST} - check-ignore is up to date
|
||||
DESC.three= Skip .MAKE.META.${TEST} - check-ignore is out of date
|
||||
|
||||
# just in case someone runs us with -jN
|
||||
.ORDER: one two three
|
||||
one two three: .MAKE setup
|
||||
@echo "${DESC.${.TARGET}}"; \
|
||||
${MAKE} -C ${.CURDIR} -f ${makefile} check-ignore parent=${.TARGET}
|
||||
|
||||
.if make(check-ignore)
|
||||
.MAKEFLAGS: -dM
|
||||
.MAKE.MODE = meta verbose silent=yes
|
||||
.OBJDIR: ${OBJ}
|
||||
.if ${parent} == "two"
|
||||
.if ${TEST} == "IGNORE_PATHS"
|
||||
# this is a prefix list - any path that matches
|
||||
# one of these prefixes will be ignored
|
||||
.MAKE.META.IGNORE_PATHS = ${IGNORE}
|
||||
.elif ${TEST} == "IGNORE_PATTERNS"
|
||||
# more flexible but more expensive
|
||||
# this example is equivalent to M*/ignore/*
|
||||
# a match means ignore
|
||||
.MAKE.META.IGNORE_PATTERNS = */ignore/*
|
||||
.elif ${TEST} == "IGNORE_FILTER"
|
||||
# this is the most flexible, but also most expensive
|
||||
# if this expands to nothing - ignore the path
|
||||
.MAKE.META.IGNORE_FILTER = N${IGNORE}/*
|
||||
.endif
|
||||
.endif
|
||||
|
||||
# : < just reads from ${IGNORE}/check
|
||||
# so that our filemon trace will have a reference to it
|
||||
# we ensure it is always newer than the target.
|
||||
check-ignore: .META .NOPATH
|
||||
@: < ${IGNORE}/check > ${.TARGET}
|
||||
@sleep 1; echo ${.TARGET} > ${IGNORE}/check
|
||||
|
||||
.endif
|
@ -1,5 +1,7 @@
|
||||
make: "opt-debug-lint.mk" line 19: Variable "X" is undefined
|
||||
make: "opt-debug-lint.mk" line 19: Malformed conditional ($X)
|
||||
make: "opt-debug-lint.mk" line 41: Variable "UNDEF" is undefined
|
||||
make: "opt-debug-lint.mk" line 41: Malformed conditional (${UNDEF})
|
||||
make: "opt-debug-lint.mk" line 61: Missing delimiter ':' after modifier "L"
|
||||
make: "opt-debug-lint.mk" line 61: Missing delimiter ':' after modifier "P"
|
||||
make: "opt-debug-lint.mk" line 69: Unknown modifier "${"
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: opt.mk,v 1.6 2020/11/18 01:06:59 sjg Exp $
|
||||
# $NetBSD: opt.mk,v 1.7 2023/02/25 00:07:08 rillig Exp $
|
||||
#
|
||||
# Tests for the command line options.
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
all: .IGNORE
|
||||
# The options from the top-level make are passed to the sub-makes via
|
||||
# the environment variable MAKEFLAGS. This is where the " -r -k -d 0"
|
||||
# comes from. See MainParseArg.
|
||||
# comes from. See MainParseOption.
|
||||
${MAKE} -r -f /dev/null -V MAKEFLAGS
|
||||
@echo
|
||||
|
||||
|
@ -1,5 +1 @@
|
||||
make: Unfinished modifier for "BRACE_GROUP" (',' missing)
|
||||
make: "parse-var.mk" line 130: Malformed conditional (0 && ${BRACE_GROUP:S,${BRACE_PAIR:S,{,{{,},<lbraces>,})
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
||||
exit status 0
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: parse-var.mk,v 1.6 2022/09/25 21:26:23 rillig Exp $
|
||||
# $NetBSD: parse-var.mk,v 1.8 2023/02/18 11:16:09 rillig Exp $
|
||||
#
|
||||
# Tests for parsing variable expressions.
|
||||
#
|
||||
@ -68,8 +68,7 @@
|
||||
#
|
||||
# Effects:
|
||||
# How much does the parsing position advance (pp)?
|
||||
# What's the value of the expression (out_val)?
|
||||
# What's the status after parsing the expression (VarParseResult)?
|
||||
# What's the value of the expression (return value)?
|
||||
# What error messages are printed (Parse_Error)?
|
||||
# What no-effect error messages are printed (Error)?
|
||||
# What error messages should be printed but aren't?
|
||||
@ -86,12 +85,9 @@ VAR.${:U param }= value
|
||||
. error
|
||||
.endif
|
||||
|
||||
# XXX: The following paragraph already uses past tense, in the hope that the
|
||||
# parsing behavior can be cleaned up soon.
|
||||
|
||||
# Since var.c 1.323 from 2020-07-26 18:11 and except for var.c 1.1028 from
|
||||
# 2022-08-08, the exact way of parsing an expression depended on whether the
|
||||
# expression was actually evaluated or merely parsed.
|
||||
# Since var.c 1.323 from 2020-07-26 18:11 and until var.c 1.1047 from
|
||||
# 2023-02-18, the exact way of parsing an expression with subexpressions
|
||||
# depended on whether the expression was actually evaluated or merely parsed.
|
||||
#
|
||||
# If it was evaluated, nested expressions were parsed correctly, parsing each
|
||||
# modifier according to its exact definition (see varmod.mk).
|
||||
@ -103,30 +99,28 @@ VAR.${:U param }= value
|
||||
# expression was not parsed correctly. Instead, make only counted the opening
|
||||
# and closing delimiters, which failed for nested modifiers with unbalanced
|
||||
# braces.
|
||||
#
|
||||
# This naive brace counting was implemented in ParseModifierPartDollar. As of
|
||||
# var.c 1.1029, there are still several other places that merely count braces
|
||||
# instead of properly parsing subexpressions.
|
||||
|
||||
#.MAKEFLAGS: -dcpv
|
||||
# Keep these braces outside the conditions below, to keep them simple to
|
||||
# understand. If the BRACE_PAIR had been replaced with ':U{}', the '}' would
|
||||
# have to be escaped, but not the '{'. This asymmetry would have made the
|
||||
# example even more complicated to understand.
|
||||
# understand. If the expression ${BRACE_PAIR:...} had been replaced with the
|
||||
# literal ${:U{}}, the '}' would have to be escaped, but not the '{'. This
|
||||
# asymmetry would have made the example even more complicated to understand.
|
||||
BRACE_PAIR= {}
|
||||
# In this test word, the '{{}' in the middle will be replaced.
|
||||
# In this test word, the below conditions will replace the '{{}' in the middle
|
||||
# with the string '<lbraces>'.
|
||||
BRACE_GROUP= {{{{}}}}
|
||||
|
||||
# The inner ':S' modifier turns the word '{}' into '{{}'.
|
||||
# The outer ':S' modifier then replaces '{{}' with '<lbraces>'.
|
||||
# In the first case, the outer expression is relevant and is parsed correctly.
|
||||
# Due to the always-true condition '1', the outer expression is relevant and
|
||||
# is parsed correctly.
|
||||
.if 1 && ${BRACE_GROUP:S,${BRACE_PAIR:S,{,{{,},<lbraces>,}
|
||||
.endif
|
||||
# In the second case, the outer expression was irrelevant. In this case, in
|
||||
# the parts of the outer ':S' modifier, make only counted the braces, and since
|
||||
# the inner expression '${BRACE_PAIR:...}' contains more '{' than '}', parsing
|
||||
# failed with the error message 'Unfinished modifier for "BRACE_GROUP"'. Fixed
|
||||
# in var.c 1.1028 from 2022-08-08, reverted in var.c 1.1029 from 2022-08-23.
|
||||
# Due to the always-false condition '0', the outer expression is irrelevant.
|
||||
# In this case, in the parts of the outer ':S' modifier, the expression parser
|
||||
# only counted the braces, and since the inner expression '${BRACE_PAIR:...}'
|
||||
# contains more '{' than '}', parsing failed with the error message 'Unfinished
|
||||
# modifier for "BRACE_GROUP"'. Fixed in var.c 1.1047 from 2023-02-18.
|
||||
.if 0 && ${BRACE_GROUP:S,${BRACE_PAIR:S,{,{{,},<lbraces>,}
|
||||
.endif
|
||||
#.MAKEFLAGS: -d0
|
||||
|
@ -7,7 +7,9 @@ make: "var-eval-short.mk" line 98: Malformed conditional (0 && ${:Uword:localtim
|
||||
CondParser_Eval: 0 && ${0:?${FAIL}then:${FAIL}else}
|
||||
Var_Parse: ${0:?${FAIL}then:${FAIL}else} (parse-only)
|
||||
Parsing modifier ${0:?...}
|
||||
Var_Parse: ${FAIL}then:${FAIL}else} (parse-only)
|
||||
Modifier part: "${FAIL}then"
|
||||
Var_Parse: ${FAIL}else} (parse-only)
|
||||
Modifier part: "${FAIL}else"
|
||||
Result of ${0:?${FAIL}then:${FAIL}else} is "" (parse-only, defined)
|
||||
Parsing line 163: DEFINED= defined
|
||||
@ -17,7 +19,9 @@ Var_Parse: ${DEFINED:L:?${FAIL}then:${FAIL}else} (parse-only)
|
||||
Parsing modifier ${DEFINED:L}
|
||||
Result of ${DEFINED:L} is "defined" (parse-only, regular)
|
||||
Parsing modifier ${DEFINED:?...}
|
||||
Var_Parse: ${FAIL}then:${FAIL}else} (parse-only)
|
||||
Modifier part: "${FAIL}then"
|
||||
Var_Parse: ${FAIL}else} (parse-only)
|
||||
Modifier part: "${FAIL}else"
|
||||
Result of ${DEFINED:?${FAIL}then:${FAIL}else} is "defined" (parse-only, regular)
|
||||
Parsing line 166: .MAKEFLAGS: -d0
|
||||
|
@ -1,4 +1,4 @@
|
||||
make: "var-scope-cmdline.mk" line 67: global
|
||||
make: "var-scope-cmdline.mk" line 76: makeflags
|
||||
make: "var-scope-cmdline.mk" line 71: global
|
||||
make: "var-scope-cmdline.mk" line 80: makeflags
|
||||
makeflags
|
||||
exit status 0
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: var-scope-cmdline.mk,v 1.1 2022/01/23 16:25:54 rillig Exp $
|
||||
# $NetBSD: var-scope-cmdline.mk,v 1.2 2023/04/07 05:54:16 rillig Exp $
|
||||
#
|
||||
# Tests for variables specified on the command line.
|
||||
#
|
||||
@ -61,6 +61,10 @@
|
||||
# Most cmdline variables are set at the very beginning, when parsing the
|
||||
# command line arguments. Using the special target '.MAKEFLAGS', it is
|
||||
# possible to set cmdline variables at any later time.
|
||||
#
|
||||
# See also:
|
||||
# varcmd.mk
|
||||
# varname-makeflags.mk
|
||||
|
||||
# A normal global variable, without any cmdline variable nearby.
|
||||
VAR= global
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: varcmd.mk,v 1.6 2021/02/16 19:43:09 rillig Exp $
|
||||
# $NetBSD: varcmd.mk,v 1.7 2023/04/07 05:54:16 rillig Exp $
|
||||
#
|
||||
# Test behaviour of recursive make and vars set on command line.
|
||||
#
|
||||
@ -12,6 +12,10 @@
|
||||
# be rewritten to make it clear why there is a difference and why this is
|
||||
# actually intended. Removing that large block of code makes only this test
|
||||
# and vardebug.mk fail, which is not enough.
|
||||
#
|
||||
# See also:
|
||||
# var-scope-cmdline.mk
|
||||
# varname-makeflags.mk
|
||||
|
||||
FU= fu
|
||||
FOO?= foo
|
||||
|
@ -27,6 +27,13 @@ make: "varmod-ifelse.mk" line 167: true
|
||||
make: "varmod-ifelse.mk" line 169: false
|
||||
make: Bad conditional expression ' ' in ' ?true:false'
|
||||
make: "varmod-ifelse.mk" line 171:
|
||||
CondParser_Eval: 0 && ${1:?${:Uthen0:S,}},,}:${:Uelse0:S,}},,}} != "not evaluated"
|
||||
CondParser_Eval: 1 && ${0:?${:Uthen1:S,}},,}:${:Uelse1:S,}},,}} != "else1"
|
||||
CondParser_Eval: 0
|
||||
Comparing "else1" != "else1"
|
||||
CondParser_Eval: 2 && ${1:?${:Uthen2:S,}},,}:${:Uelse2:S,}},,}} != "then2"
|
||||
CondParser_Eval: 1
|
||||
Comparing "then2" != "then2"
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: varmod-ifelse.mk,v 1.20 2022/09/25 12:51:37 rillig Exp $
|
||||
# $NetBSD: varmod-ifelse.mk,v 1.21 2023/02/18 18:23:58 rillig Exp $
|
||||
#
|
||||
# Tests for the ${cond:?then:else} variable modifier, which evaluates either
|
||||
# the then-expression or the else-expression, depending on the condition.
|
||||
@ -182,3 +182,67 @@ PRIMES= 2 3 5 7 11
|
||||
"1:not_prime 2:prime 3:prime 4:not_prime 5:prime"
|
||||
. error
|
||||
.endif
|
||||
|
||||
# When parsing the modifier ':?', there are 3 possible cases:
|
||||
#
|
||||
# 1. The whole expression is only parsed.
|
||||
# 2. The expression is parsed and the 'then' branch is evaluated.
|
||||
# 3. The expression is parsed and the 'else' branch is evaluated.
|
||||
#
|
||||
# In all of these cases, the expression must be parsed in the same way,
|
||||
# especially when one of the branches contains unbalanced '{}' braces.
|
||||
#
|
||||
# At 2020-01-01, the expressions from the 'then' and 'else' branches were
|
||||
# parsed differently, depending on whether the branch was taken or not. When
|
||||
# the branch was taken, the parser recognized that in the modifier ':S,}},,',
|
||||
# the '}}' were ordinary characters. When the branch was not taken, the
|
||||
# parser only counted balanced '{' and '}', ignoring any escaping or other
|
||||
# changes in the interpretation.
|
||||
#
|
||||
# In var.c 1.285 from 2020-07-20, the parsing of the expressions changed so
|
||||
# that in both cases the expression is parsed in the same way, taking the
|
||||
# unbalanced braces in the ':S' modifiers into account. This change was not
|
||||
# on purpose, the commit message mentioned 'has the same effect', which was a
|
||||
# wrong assumption.
|
||||
#
|
||||
# In var.c 1.323 from 2020-07-26, the unintended fix from var.c 1.285 was
|
||||
# reverted, still not knowing about the difference between regular parsing and
|
||||
# balanced-mode parsing.
|
||||
#
|
||||
# In var.c 1.1028 from 2022-08-08, there was another attempt at fixing this
|
||||
# inconsistency in parsing, but since that broke parsing of the modifier ':@',
|
||||
# it was reverted in var.c 1.1029 from 2022-08-23.
|
||||
#
|
||||
# In var.c 1.1047 from 2023-02-18, the inconsistency in parsing was finally
|
||||
# fixed. The modifier ':@' now parses the body in balanced mode, while
|
||||
# everywhere else the modifier parts have their subexpressions parsed in the
|
||||
# same way, no matter whether they are evaluated or not.
|
||||
#
|
||||
# The modifiers ':@' and ':?' are similar in that they conceptually contain
|
||||
# text to be evaluated later or conditionally, still they parse that text
|
||||
# differently. The crucial difference is that the body of the modifier ':@'
|
||||
# is always parsed using balanced mode. The modifier ':?', on the other hand,
|
||||
# must parse both of its branches in the same way, no matter whether they are
|
||||
# evaluated or not. Since balanced mode and standard mode are incompatible,
|
||||
# it's impossible to use balanced mode in the modifier ':?'.
|
||||
.MAKEFLAGS: -dc
|
||||
.if 0 && ${1:?${:Uthen0:S,}},,}:${:Uelse0:S,}},,}} != "not evaluated"
|
||||
# At 2020-01-07, the expression evaluated to 'then0,,}}', even though it was
|
||||
# irrelevant as the '0' had already been evaluated to 'false'.
|
||||
. error
|
||||
.endif
|
||||
.if 1 && ${0:?${:Uthen1:S,}},,}:${:Uelse1:S,}},,}} != "else1"
|
||||
. error
|
||||
.endif
|
||||
.if 2 && ${1:?${:Uthen2:S,}},,}:${:Uelse2:S,}},,}} != "then2"
|
||||
# At 2020-01-07, the whole expression evaluated to 'then2,,}}' instead of the
|
||||
# expected 'then2'. The 'then' branch of the ':?' modifier was parsed
|
||||
# normally, parsing and evaluating the ':S' modifier, thereby treating the
|
||||
# '}}' as ordinary characters and resulting in 'then2'. The 'else' branch was
|
||||
# parsed in balanced mode, ignoring that the inner '}}' were ordinary
|
||||
# characters. The '}}' were thus interpreted as the end of the 'else' branch
|
||||
# and the whole expression. This left the trailing ',,}}', which together
|
||||
# with the 'then2' formed the result 'then2,,}}'.
|
||||
. error
|
||||
.endif
|
||||
.MAKEFLAGS: -d0
|
||||
|
@ -1,10 +1,10 @@
|
||||
Parsing line 78: USE_8_DOLLARS= ${:U1:@var@${8_DOLLARS}@} ${8_DOLLARS} $$$$$$$$
|
||||
Parsing line 91: USE_8_DOLLARS= ${:U1:@var@${8_DOLLARS}@} ${8_DOLLARS} $$$$$$$$
|
||||
CondParser_Eval: ${USE_8_DOLLARS} != "\$\$\$\$ \$\$\$\$ \$\$\$\$"
|
||||
Comparing "$$$$ $$$$ $$$$" != "$$$$ $$$$ $$$$"
|
||||
Parsing line 83: SUBST_CONTAINING_LOOP:= ${USE_8_DOLLARS}
|
||||
Parsing line 96: SUBST_CONTAINING_LOOP:= ${USE_8_DOLLARS}
|
||||
CondParser_Eval: ${SUBST_CONTAINING_LOOP} != "\$\$ \$\$\$\$ \$\$\$\$"
|
||||
Comparing "$$ $$$$ $$$$" != "$$ $$$$ $$$$"
|
||||
Parsing line 108: .MAKEFLAGS: -d0
|
||||
Parsing line 121: .MAKEFLAGS: -d0
|
||||
ParseDependency(.MAKEFLAGS: -d0)
|
||||
:varname-overwriting-target: :x1y x2y x3y: ::
|
||||
mod-loop-dollar:1:
|
||||
|
@ -1,6 +1,20 @@
|
||||
# $NetBSD: varmod-loop.mk,v 1.21 2022/08/23 21:13:46 rillig Exp $
|
||||
# $NetBSD: varmod-loop.mk,v 1.23 2023/02/18 11:55:20 rillig Exp $
|
||||
#
|
||||
# Tests for the :@var@...${var}...@ variable modifier.
|
||||
# Tests for the expression modifier ':@var@body@', which replaces each word of
|
||||
# the expression with the expanded body, which may contain references to the
|
||||
# variable 'var'. For example, '${1 2 3:L:@word@<${word}>@}' encloses each
|
||||
# word in angle quotes, resulting in '<1> <2> <3>'.
|
||||
#
|
||||
# The variable name can be chosen freely, except that it must not contain a
|
||||
# '$'. For simplicity and readability, variable names should only use the
|
||||
# characters 'A-Za-z0-9'.
|
||||
#
|
||||
# The body may contain subexpressions in the form '${...}' or '$(...)'. These
|
||||
# subexpressions differ from everywhere else in makefiles in that the parser
|
||||
# only scans '${...}' for balanced '{' and '}', likewise for '$(...)'. Any
|
||||
# other '$' is left as-is during parsing. Later, when the body is expanded
|
||||
# for each word, each '$$' is interpreted as a single '$', and the remaining
|
||||
# '$' are interpreted as expressions, like when evaluating a regular variable.
|
||||
|
||||
# Force the test results to be independent of the default value of this
|
||||
# setting, which is 'yes' for NetBSD's usr.bin/make but 'no' for the bmake
|
||||
@ -19,7 +33,6 @@ varname-overwriting-target:
|
||||
@echo :$@: :${:U1 2 3:@\@@x${@}y@}: :$@:
|
||||
|
||||
|
||||
|
||||
# Demonstrate that it is possible to generate dollar signs using the
|
||||
# :@ modifier.
|
||||
#
|
||||
@ -192,15 +205,14 @@ CMDLINE= global # needed for deleting the environment
|
||||
# except for '$i', which is replaced with the then-current value '1' of the
|
||||
# iteration variable.
|
||||
#
|
||||
# XXX: was broken in var.c 1.1028 from 2022-08-08, reverted in var.c 1.1029
|
||||
# from 2022-08-23; see parse-var.mk, keyword 'BRACE_GROUP'.
|
||||
# See parse-var.mk, keyword 'BRACE_GROUP'.
|
||||
all: varmod-loop-literal-dollar
|
||||
varmod-loop-literal-dollar: .PHONY
|
||||
: ${:U1:@i@ t=$$(( $${t:-0} + $i ))@}
|
||||
|
||||
|
||||
# When parsing the loop body, each '\$', '\@' and '\\' is unescaped to '$',
|
||||
# '@' and '\'; all other backslashes are retained.
|
||||
# '@' and '\', respectively; all other backslashes are retained.
|
||||
#
|
||||
# In practice, the '$' is not escaped as '\$', as there is a second round of
|
||||
# unescaping '$$' to '$' later when the loop body is expanded after setting the
|
||||
|
@ -1,9 +1,97 @@
|
||||
# $NetBSD: varmod-no-match.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $
|
||||
# $NetBSD: varmod-no-match.mk,v 1.3 2023/02/26 06:08:06 rillig Exp $
|
||||
#
|
||||
# Tests for the :N variable modifier, which filters words that do not match
|
||||
# the given pattern.
|
||||
# Tests for the expression modifier ':N', which filters words that do not
|
||||
# match the given pattern.
|
||||
|
||||
|
||||
# Keep all words except for 'two'.
|
||||
.if ${:U one two three :Ntwo} != "one three"
|
||||
. error
|
||||
.endif
|
||||
|
||||
# Keep all words except those starting with 't'.
|
||||
# See varmod-match.mk for the details of pattern matching.
|
||||
.if ${:U one two three four six :Nt*} != "one four six"
|
||||
. error
|
||||
.endif
|
||||
|
||||
|
||||
# Idiom: normalize whitespace
|
||||
#
|
||||
# The modifier ':N' can be used with an empty pattern. As that pattern never
|
||||
# matches a word, the only effect is that the string is split into words and
|
||||
# then joined again, thereby normalizing whitespace around and between the
|
||||
# words. And even though the 'N' in ':N' might serve as a mnemonic for
|
||||
# "normalize whitespace", this idiom is not used in practice, resorting to the
|
||||
# much more common ':M*' to "select all words" instead.
|
||||
.if ${:U :N} != ""
|
||||
. error
|
||||
.endif
|
||||
.if ${:U one two three :N} != "one two three"
|
||||
. error
|
||||
.endif
|
||||
.if ${:U one two three :M*} != "one two three"
|
||||
. error
|
||||
.endif
|
||||
|
||||
|
||||
# Idiom: single-word expression equals any of several words or patterns
|
||||
#
|
||||
# If an expression is guaranteed to consist of a single word, the modifier
|
||||
# ':N' can be chained to compare the expression to several words or even
|
||||
# patterns in a sequence. If one of the patterns matches, the final
|
||||
# expression will be the empty string.
|
||||
#
|
||||
.if ${:U word :None:Ntwo:Nthree} != ""
|
||||
# good
|
||||
.else
|
||||
. error
|
||||
.endif
|
||||
.if ${:U two :None:Ntwo:Nthree} != ""
|
||||
. error
|
||||
.else
|
||||
# good
|
||||
.endif
|
||||
#
|
||||
# The modifier ':N' is seldom used in general since positive matches with ':M'
|
||||
# are easier to grasp. Chaining the ':N' modifier is even more difficult to
|
||||
# grasp due to the many negations involved.
|
||||
#
|
||||
# The final '!= ""' adds to the confusion because at first glance, the
|
||||
# condition may look like '${VAR} != ""', which for a single-word variable is
|
||||
# always true.
|
||||
#
|
||||
# The '!= ""' can be omitted if the expression cannot have the numeric value
|
||||
# 0, which is common in practice. In that form, each ':N' can be pronounced
|
||||
# as 'neither' or 'nor', which makes the expression sound more natural.
|
||||
#
|
||||
.if ${:U word :None:Ntwo:Nthree}
|
||||
# good
|
||||
.else
|
||||
. error
|
||||
.endif
|
||||
.if ${:U two :None:Ntwo:Nthree}
|
||||
. error
|
||||
.else
|
||||
# good
|
||||
.endif
|
||||
#
|
||||
# Replacing the '${...} != ""' with '!empty(...)' doesn't improve the
|
||||
# situation as the '!' adds another level of negations, and the word 'empty'
|
||||
# is a negation on its own, thereby creating a triple negation. Furthermore,
|
||||
# due to the '!empty', the expression to be evaluated no longer starts with
|
||||
# '$' and is thus more difficult to spot quickly.
|
||||
#
|
||||
.if !empty(:U word :None:Ntwo:Nthree)
|
||||
# good
|
||||
.else
|
||||
. error
|
||||
.endif
|
||||
.if !empty(:U two :None:Ntwo:Nthree)
|
||||
. error
|
||||
.else
|
||||
# good
|
||||
.endif
|
||||
|
||||
# TODO: Implementation
|
||||
|
||||
all:
|
||||
@:;
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: varmod-order-shuffle.mk,v 1.7 2021/08/03 04:46:49 rillig Exp $
|
||||
# $NetBSD: varmod-order-shuffle.mk,v 1.8 2023/02/26 06:08:06 rillig Exp $
|
||||
#
|
||||
# Tests for the :Ox variable modifier, which returns the words of the
|
||||
# variable, shuffled.
|
||||
@ -6,8 +6,9 @@
|
||||
# The variable modifier :Ox is available since 2005-06-01.
|
||||
#
|
||||
# As of 2020-08-16, make uses random(3) seeded by the current time in seconds.
|
||||
# This makes the random numbers completely predictable since there is no other
|
||||
# part of make that uses random numbers.
|
||||
# This makes the random numbers completely predictable since the only other
|
||||
# part of make that uses random numbers is the 'randomize-targets' mode, which
|
||||
# is off by default.
|
||||
#
|
||||
# Tags: probabilistic
|
||||
|
||||
|
@ -19,6 +19,8 @@ make: Bad modifier ":Onrr" for variable "NUMBERS"
|
||||
make: "varmod-order.mk" line 77: Malformed conditional (${NUMBERS:Onrr})
|
||||
make: Bad modifier ":Orrn" for variable "NUMBERS"
|
||||
make: "varmod-order.mk" line 86: Malformed conditional (${NUMBERS:Orrn})
|
||||
make: Bad modifier ":On=Off" for variable "SWITCH"
|
||||
make: "varmod-order.mk" line 100: Malformed conditional (${SWITCH:On=Off} != "Off")
|
||||
make: Fatal errors encountered -- cannot continue
|
||||
make: stopped in unit-tests
|
||||
exit status 1
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: varmod-order.mk,v 1.8 2022/01/15 12:35:18 rillig Exp $
|
||||
# $NetBSD: varmod-order.mk,v 1.10 2023/02/27 08:29:36 rillig Exp $
|
||||
#
|
||||
# Tests for the :O variable modifier and its variants, which either sort the
|
||||
# words of the value or shuffle them.
|
||||
@ -89,4 +89,18 @@ _:= ${NUMBERS:Onr
|
||||
. error
|
||||
.endif
|
||||
|
||||
|
||||
# If a modifier that starts with ':O' is not one of the known sort or shuffle
|
||||
# forms, it is a parse error. Several other modifiers such as ':H' or ':u'
|
||||
# fall back to the SysV modifier, for example, ':H=new' is not the standard
|
||||
# ':H' modifier but instead replaces a trailing 'H' with 'new' in each word.
|
||||
# There is no such fallback for the ':O' modifiers.
|
||||
SWITCH= On
|
||||
# expect: make: Bad modifier ":On=Off" for variable "SWITCH"
|
||||
.if ${SWITCH:On=Off} != "Off"
|
||||
. error
|
||||
.else
|
||||
. error
|
||||
.endif
|
||||
|
||||
all:
|
||||
|
@ -1 +1,11 @@
|
||||
Initialize check-ignore.meta
|
||||
Building <tmpdir>/obj/check-ignore
|
||||
Skipping meta for .END: .SPECIAL
|
||||
Use .MAKE.META.IGNORE_FILTER - check-ignore is up to date
|
||||
`check-ignore' is up to date.
|
||||
Skipping meta for .END: .SPECIAL
|
||||
Skip .MAKE.META.IGNORE_FILTER - check-ignore is out of date
|
||||
<tmpdir>/obj/check-ignore.meta: <line>: file '<tmpdir>/ignore/check' is newer than the target...
|
||||
Building <tmpdir>/obj/check-ignore
|
||||
Skipping meta for .END: .SPECIAL
|
||||
exit status 0
|
||||
|
@ -1,8 +1,5 @@
|
||||
# $NetBSD: varname-dot-make-meta-ignore_filter.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $
|
||||
# $NetBSD: varname-dot-make-meta-ignore_filter.mk,v 1.3 2023/02/23 05:20:45 sjg Exp $
|
||||
#
|
||||
# Tests for the special .MAKE.META.IGNORE_FILTER variable.
|
||||
|
||||
# TODO: Implementation
|
||||
|
||||
all:
|
||||
@:;
|
||||
.include "meta-ignore.inc"
|
||||
|
@ -1 +1,11 @@
|
||||
Initialize check-ignore.meta
|
||||
Building <tmpdir>/obj/check-ignore
|
||||
Skipping meta for .END: .SPECIAL
|
||||
Use .MAKE.META.IGNORE_PATHS - check-ignore is up to date
|
||||
`check-ignore' is up to date.
|
||||
Skipping meta for .END: .SPECIAL
|
||||
Skip .MAKE.META.IGNORE_PATHS - check-ignore is out of date
|
||||
<tmpdir>/obj/check-ignore.meta: <line>: file '<tmpdir>/ignore/check' is newer than the target...
|
||||
Building <tmpdir>/obj/check-ignore
|
||||
Skipping meta for .END: .SPECIAL
|
||||
exit status 0
|
||||
|
@ -1,8 +1,5 @@
|
||||
# $NetBSD: varname-dot-make-meta-ignore_paths.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $
|
||||
# $NetBSD: varname-dot-make-meta-ignore_paths.mk,v 1.3 2023/02/23 05:20:45 sjg Exp $
|
||||
#
|
||||
# Tests for the special .MAKE.META.IGNORE_PATHS variable.
|
||||
|
||||
# TODO: Implementation
|
||||
|
||||
all:
|
||||
@:;
|
||||
.include "meta-ignore.inc"
|
||||
|
@ -1 +1,11 @@
|
||||
Initialize check-ignore.meta
|
||||
Building <tmpdir>/obj/check-ignore
|
||||
Skipping meta for .END: .SPECIAL
|
||||
Use .MAKE.META.IGNORE_PATTERNS - check-ignore is up to date
|
||||
`check-ignore' is up to date.
|
||||
Skipping meta for .END: .SPECIAL
|
||||
Skip .MAKE.META.IGNORE_PATTERNS - check-ignore is out of date
|
||||
<tmpdir>/obj/check-ignore.meta: <line>: file '<tmpdir>/ignore/check' is newer than the target...
|
||||
Building <tmpdir>/obj/check-ignore
|
||||
Skipping meta for .END: .SPECIAL
|
||||
exit status 0
|
||||
|
@ -1,8 +1,5 @@
|
||||
# $NetBSD: varname-dot-make-meta-ignore_patterns.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $
|
||||
# $NetBSD: varname-dot-make-meta-ignore_patterns.mk,v 1.3 2023/02/23 05:20:45 sjg Exp $
|
||||
#
|
||||
# Tests for the special .MAKE.META.IGNORE_PATTERNS variable.
|
||||
|
||||
# TODO: Implementation
|
||||
|
||||
all:
|
||||
@:;
|
||||
.include "meta-ignore.inc"
|
||||
|
@ -1,3 +1,10 @@
|
||||
echo "$MAKEFLAGS"
|
||||
-r -k -d 00000 -D VARNAME WITH SPACES
|
||||
make: "varname-dot-makeflags.mk" line 10: MAKEFLAGS=<undefined>
|
||||
make: "varname-dot-makeflags.mk" line 11: .MAKEFLAGS=< -r -k>
|
||||
make: "varname-dot-makeflags.mk" line 12: .MAKEOVERRIDES=<>
|
||||
make: "varname-dot-makeflags.mk" line 18: MAKEFLAGS=<undefined>
|
||||
make: "varname-dot-makeflags.mk" line 20: .MAKEFLAGS=< -r -k -D VARNAME -r>
|
||||
make: "varname-dot-makeflags.mk" line 22: .MAKEOVERRIDES=< VAR>
|
||||
runtime: MAKEFLAGS=< -r -k -D VARNAME -r VAR=value>
|
||||
runtime: .MAKEFLAGS=< -r -k -D VARNAME -r>
|
||||
runtime: .MAKEOVERRIDES=< VAR>
|
||||
exit status 0
|
||||
|
@ -1,15 +1,36 @@
|
||||
# $NetBSD: varname-dot-makeflags.mk,v 1.1 2020/12/01 20:37:30 rillig Exp $
|
||||
# $NetBSD: varname-dot-makeflags.mk,v 1.7 2023/02/25 19:24:07 rillig Exp $
|
||||
#
|
||||
# Tests for the special .MAKEFLAGS variable, which collects almost all
|
||||
# command line arguments and passes them on to any child processes via
|
||||
# the environment variable MAKEFLAGS (without leading '.').
|
||||
#
|
||||
# See also:
|
||||
# varname-dot-makeoverrides.mk
|
||||
|
||||
# When options are parsed, the option and its argument are appended as
|
||||
# separate words to .MAKEFLAGS. Special characters in the option argument
|
||||
# are not quoted though. It seems to have not been necessary at least from
|
||||
# 1993 until 2020.
|
||||
.MAKEFLAGS: -d00000 -D"VARNAME WITH SPACES"
|
||||
.info MAKEFLAGS=<${MAKEFLAGS:Uundefined}>
|
||||
.info .MAKEFLAGS=<${.MAKEFLAGS}>
|
||||
.info .MAKEOVERRIDES=<${.MAKEOVERRIDES:Uundefined}>
|
||||
|
||||
all:
|
||||
echo "$$MAKEFLAGS"
|
||||
@:;
|
||||
# Append an option with argument, a plain option and a variable assignment.
|
||||
.MAKEFLAGS: -DVARNAME -r VAR=value
|
||||
|
||||
# expect+1: MAKEFLAGS=<undefined>
|
||||
.info MAKEFLAGS=<${MAKEFLAGS:Uundefined}>
|
||||
# expect+1: .MAKEFLAGS=< -r -k -D VARNAME -r>
|
||||
.info .MAKEFLAGS=<${.MAKEFLAGS}>
|
||||
# expect+1: .MAKEOVERRIDES=< VAR>
|
||||
.info .MAKEOVERRIDES=<${.MAKEOVERRIDES}>
|
||||
|
||||
# The environment variable 'MAKEFLAGS' is not available to child processes
|
||||
# when parsing the makefiles. This is different from exported variables,
|
||||
# which are already available during parse time.
|
||||
.if ${:!echo "\${MAKEFLAGS-undef}"!} != "undef"
|
||||
. error
|
||||
.endif
|
||||
|
||||
# After parsing, the environment variable 'MAKEFLAGS' is set based on the
|
||||
# special variables '.MAKEFLAGS' and '.MAKEOVERRIDES'.
|
||||
runtime:
|
||||
@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
|
||||
@echo '$@: .MAKEFLAGS=<'${.MAKEFLAGS:Q}'>'
|
||||
@echo '$@: .MAKEOVERRIDES=<'${.MAKEOVERRIDES:Q}'>'
|
||||
|
@ -1 +1,8 @@
|
||||
all: overrides=<>
|
||||
make -f varname-dot-makeoverrides.mk stage_1 VAR=value
|
||||
stage_1: overrides=< VAR>
|
||||
make -f varname-dot-makeoverrides.mk stage_2
|
||||
stage_2: overrides=< VAR>
|
||||
make -f varname-dot-makeoverrides.mk stage_3
|
||||
stage_3: overrides=< VAR>
|
||||
exit status 0
|
||||
|
@ -1,8 +1,23 @@
|
||||
# $NetBSD: varname-dot-makeoverrides.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $
|
||||
# $NetBSD: varname-dot-makeoverrides.mk,v 1.5 2023/02/25 06:54:08 rillig Exp $
|
||||
#
|
||||
# Tests for the special .MAKE.MAKEOVERRIDES variable.
|
||||
|
||||
# TODO: Implementation
|
||||
# Tests for the special .MAKEOVERRIDES variable, which lists the names of the
|
||||
# variables that are passed on to child processes via the MAKEFLAGS
|
||||
# environment variable.
|
||||
#
|
||||
# See also:
|
||||
# varname-dot-makeflags.mk
|
||||
|
||||
all:
|
||||
@:;
|
||||
@echo '$@: overrides=<'${.MAKEOVERRIDES:Uundefined:Q}'>'
|
||||
${MAKE} -f ${MAKEFILE} stage_1 VAR=value
|
||||
|
||||
stage_1:
|
||||
@echo '$@: overrides=<'${.MAKEOVERRIDES:Q}'>'
|
||||
${MAKE} -f ${MAKEFILE} stage_2
|
||||
|
||||
stage_2:
|
||||
@echo '$@: overrides=<'${.MAKEOVERRIDES:Q}'>'
|
||||
${MAKE} -f ${MAKEFILE} stage_3
|
||||
|
||||
stage_3:
|
||||
@echo '$@: overrides=<'${.MAKEOVERRIDES:Q}'>'
|
||||
|
@ -1 +1,21 @@
|
||||
spaces_stage_0: MAKEFLAGS=< -r -k >
|
||||
spaces_stage_0: env MAKEFLAGS=< -r -k >
|
||||
spaces_stage_1: MAKEFLAGS=< -r -k -d 00000 -D VARNAME WITH SPACES >
|
||||
spaces_stage_1: env MAKEFLAGS=< -r -k -d 00000 -D VARNAME WITH SPACES >
|
||||
dollars_stage_0: MAKEFLAGS=< -r -k >
|
||||
dollars_stage_1: env MAKEFLAGS=< -r -k DOLLARS=\$\{varname\}>
|
||||
dollars_stage_1: MAKEFLAGS=< -r -k DOLLARS=\{varname\}>
|
||||
dollars_stage_1: MAKEFLAGS:q=< -r -k DOLLARS=\{varname\}>
|
||||
dollars_stage_2: env MAKEFLAGS=< -r -k DOLLARS=>
|
||||
dollars_stage_2: dollars=<>
|
||||
dollars_stage_2: MAKEFLAGS=< -r -k DOLLARS=>
|
||||
dollars_stage_3: env MAKEFLAGS=< -r -k DOLLARS=>
|
||||
dollars_stage_3: dollars=<>
|
||||
dollars_stage_3: MAKEFLAGS=< -r -k DOLLARS=>
|
||||
append_stage_0: MAKEFLAGS=< -r -k >
|
||||
append_stage_1: MAKEFLAGS=< -r -k -D before-0 -D after-0 VAR0=value>
|
||||
append_stage_2: MAKEFLAGS=< -r -k -D before-0 -D after-0 -D before-1 -D after-1 VAR0=value VAR1=value>
|
||||
append_stage_3: MAKEFLAGS=< -r -k -D before-0 -D after-0 -D before-1 -D after-1 -D before-2 -D after-2 VAR0=value VAR1=value VAR2=value>
|
||||
override_stage_1: run MAKEFLAGS=< -r -k STAGE=1 VAR=value>
|
||||
override_stage_2: STAGE=<2> VAR=<value>
|
||||
exit status 0
|
||||
|
@ -1,44 +1,182 @@
|
||||
# $NetBSD: varname-makeflags.mk,v 1.5 2022/01/16 18:16:06 sjg Exp $
|
||||
# $NetBSD: varname-makeflags.mk,v 1.7 2023/02/25 19:24:07 rillig Exp $
|
||||
#
|
||||
# Tests for the special MAKEFLAGS variable, which is basically just a normal
|
||||
# environment variable. It is closely related to .MAKEFLAGS but captures the
|
||||
# state of .MAKEFLAGS at the very beginning of make, before any makefiles are
|
||||
# read.
|
||||
# Tests for the environment variable 'MAKEFLAGS', from which additional
|
||||
# command line arguments are read before the actual command line arguments.
|
||||
#
|
||||
# After reading the makefiles and before making the targets, the arguments
|
||||
# that were collected in '.MAKEFLAGS' and '.MAKEOVERRIDES' are written back to
|
||||
# the environment variable 'MAKEFLAGS'.
|
||||
|
||||
# TODO: Implementation
|
||||
all: spaces_stage_0 dollars_stage_0 append_stage_0 override_stage_0
|
||||
|
||||
.MAKEFLAGS: -d0
|
||||
|
||||
.if !make(*stage*)
|
||||
|
||||
# The unit tests are run with an almost empty environment. In particular,
|
||||
# the variable MAKEFLAGS is not set. The '.MAKEFLAGS:' above also doesn't
|
||||
# influence the environment variable MAKEFLAGS, therefore it is still
|
||||
# undefined at this point.
|
||||
.if ${MAKEFLAGS:Uundefined} != "undefined"
|
||||
. error
|
||||
.endif
|
||||
# the variable MAKEFLAGS is not set.
|
||||
. if ${MAKEFLAGS:Uundefined} != "undefined"
|
||||
. error
|
||||
. endif
|
||||
|
||||
# The special variable .MAKEFLAGS is influenced though.
|
||||
# See varname-dot-makeflags.mk for more details.
|
||||
.if ${.MAKEFLAGS} != " -r -k -d 0"
|
||||
. error
|
||||
.endif
|
||||
. if ${.MAKEFLAGS} != " -r -k"
|
||||
. error
|
||||
. endif
|
||||
|
||||
|
||||
# In POSIX mode, the environment variable MAKEFLAGS can contain letters only,
|
||||
# for compatibility. These letters are exploded to form regular options.
|
||||
OUTPUT!= env MAKEFLAGS=ikrs ${MAKE} -f /dev/null -v .MAKEFLAGS
|
||||
.if ${OUTPUT} != " -i -k -r -s -V .MAKEFLAGS"
|
||||
. error
|
||||
.endif
|
||||
. if ${OUTPUT} != " -i -k -r -s -V .MAKEFLAGS"
|
||||
. error
|
||||
. endif
|
||||
|
||||
# As soon as there is a single non-alphabetic character in the environment
|
||||
# variable MAKEFLAGS, it is no longer split. In this example, the word
|
||||
# "d0ikrs" is treated as a target, but the option '-v' prevents any targets
|
||||
# from being built.
|
||||
OUTPUT!= env MAKEFLAGS=d0ikrs ${MAKE} -r -f /dev/null -v .MAKEFLAGS
|
||||
.if ${OUTPUT} != " -r -V .MAKEFLAGS"
|
||||
. error ${OUTPUT}
|
||||
. if ${OUTPUT} != " -r -V .MAKEFLAGS"
|
||||
. error ${OUTPUT}
|
||||
. endif
|
||||
|
||||
.endif
|
||||
|
||||
|
||||
all:
|
||||
# When options are parsed, the option and its argument are appended as
|
||||
# separate words to the MAKEFLAGS for the child processes. Special characters
|
||||
# in the option arguments are not quoted though.
|
||||
spaces_stage_0:
|
||||
@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
|
||||
@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
|
||||
@${MAKE} -f ${MAKEFILE} spaces_stage_1 -d00000 -D"VARNAME WITH SPACES"
|
||||
|
||||
# At this point, the 'VARNAME WITH SPACES' is no longer recognizable as a
|
||||
# single command line argument. In practice, variable names don't contain
|
||||
# spaces.
|
||||
spaces_stage_1:
|
||||
@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
|
||||
@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
|
||||
|
||||
|
||||
# Demonstrate that '$' characters are altered when they are passed on to child
|
||||
# make processes via MAKEFLAGS.
|
||||
dollars_stage_0:
|
||||
@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
|
||||
|
||||
# The '$$$$' becomes a literal '$$' when building the '${MAKE}'
|
||||
# command line, making the actual argument 'DOLLARS=$${varname}'.
|
||||
# At this stage, MAKEFLAGS is not yet involved.
|
||||
@${MAKE} -f ${MAKEFILE} dollars_stage_1 DOLLARS='$$$${varname}'
|
||||
|
||||
.if make(dollars_stage_1)
|
||||
# At this point, the variable 'DOLLARS' contains '$${varname}', which
|
||||
# evaluates to a literal '$' followed by '{varname}'.
|
||||
. if ${DOLLARS} != "\${varname}"
|
||||
. error
|
||||
. endif
|
||||
.endif
|
||||
dollars_stage_1:
|
||||
# At this point, the stage 1 make provides the environment variable
|
||||
# 'MAKEFLAGS' to its child processes, even if the child process is not
|
||||
# another make.
|
||||
#
|
||||
# expect: dollars_stage_1: env MAKEFLAGS=< -r -k DOLLARS=\$\{varname\}>
|
||||
#
|
||||
# The 'DOLLARS=\$\{varname\}' assignment is escaped so that the stage
|
||||
# 2 make will see it as a single word.
|
||||
@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
|
||||
|
||||
# At this point, evaluating the environment variable 'MAKEFLAGS' leads
|
||||
# to strange side effects as the string '\$\{varname\}' is interpreted
|
||||
# as:
|
||||
#
|
||||
# \ a literal string of a single backslash
|
||||
# $\ the value of the variable named '\'
|
||||
# {varname\} a literal string
|
||||
#
|
||||
# Since the variable name '\' is not defined, the resulting value is
|
||||
# '\{varname\}'. Make doesn't handle isolated '$' characters in
|
||||
# strings well, instead each '$' has to be part of a '$$' or be part
|
||||
# of a subexpression like '${VAR}'.
|
||||
@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
|
||||
|
||||
# The modifier ':q' preserves a '$$' in an expression value instead of
|
||||
# expanding it to a single '$', but it's already too late, as that
|
||||
# modifier applies after the expression has been evaluated. Except
|
||||
# for debug logging, there is no way to process strings that contain
|
||||
# isolated '$'.
|
||||
@echo '$@: MAKEFLAGS:q=<'${MAKEFLAGS:q}'>'
|
||||
|
||||
@${MAKE} -f ${MAKEFILE} dollars_stage_2
|
||||
|
||||
.if make(dollars_stage_2)
|
||||
# At this point, the variable 'DOLLARS' contains '${varname}', and since
|
||||
# 'varname' is undefined, that expression evaluates to an empty string.
|
||||
. if ${DOLLARS} != ""
|
||||
. error
|
||||
. endif
|
||||
varname= varvalue
|
||||
. if ${DOLLARS} != "varvalue"
|
||||
. error
|
||||
. endif
|
||||
. undef varname
|
||||
.endif
|
||||
dollars_stage_2:
|
||||
@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
|
||||
@echo '$@: dollars=<'${DOLLARS:Q}'>'
|
||||
@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
|
||||
@${MAKE} -f ${MAKEFILE} dollars_stage_3
|
||||
|
||||
dollars_stage_3:
|
||||
@echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>"
|
||||
@echo '$@: dollars=<'${DOLLARS:Uundefined:Q}'>'
|
||||
@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
|
||||
|
||||
|
||||
# Demonstrates in which exact order the MAKEFLAGS are built together from the
|
||||
# parent MAKEFLAGS and the flags from the command line, in particular that
|
||||
# variable assignments are passed at the end, after the options.
|
||||
append_stage_0:
|
||||
@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
|
||||
@${MAKE} -Dbefore-0 -f ${MAKEFILE} append_stage_1 VAR0=value -Dafter-0
|
||||
|
||||
append_stage_1:
|
||||
@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
|
||||
@${MAKE} -Dbefore-1 -f ${MAKEFILE} append_stage_2 VAR1=value -Dafter-1
|
||||
|
||||
append_stage_2:
|
||||
@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
|
||||
@${MAKE} -Dbefore-2 -f ${MAKEFILE} append_stage_3 VAR2=value -Dafter-2
|
||||
|
||||
append_stage_3:
|
||||
@echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
|
||||
|
||||
|
||||
# Demonstrates the implementation details of 'MAKEFLAGS', in particular that
|
||||
# it is an environment variable rather than a global variable.
|
||||
override_stage_0:
|
||||
@${MAKE} -f ${MAKEFILE} STAGE=1 VAR=value override_stage_1
|
||||
|
||||
.if make(override_stage_1)
|
||||
# While parsing the makefiles, 'MAKEFLAGS' is the value of the environment
|
||||
# variable, in this case provided by stage 0.
|
||||
. if ${MAKEFLAGS:M*} != "-r -k"
|
||||
. error
|
||||
. endif
|
||||
MAKEFLAGS= overridden # temporarily override it
|
||||
. if ${MAKEFLAGS} != "overridden"
|
||||
. error
|
||||
. endif
|
||||
.undef MAKEFLAGS # make the environment variable visible again
|
||||
. if ${MAKEFLAGS:M*} != "-r -k"
|
||||
. error
|
||||
. endif
|
||||
.endif
|
||||
override_stage_1:
|
||||
@echo '$@: run MAKEFLAGS=<'${MAKEFLAGS:Q}'>'
|
||||
@${MAKE} -f ${MAKEFILE} STAGE=2 override_stage_2
|
||||
|
||||
override_stage_2:
|
||||
@echo '$@: STAGE=<${STAGE}> VAR=<${VAR}>'
|
||||
|
@ -1,10 +1,10 @@
|
||||
make: "varparse-errors.mk" line 38: Unknown modifier "Z"
|
||||
make: "varparse-errors.mk" line 46: Unknown modifier "Z"
|
||||
make: "varparse-errors.mk" line 37: Unknown modifier "Z"
|
||||
make: "varparse-errors.mk" line 45: Unknown modifier "Z"
|
||||
make: Bad modifier ":OX" for variable ""
|
||||
make: "varparse-errors.mk" line 68: Undefined variable "${:U:OX"
|
||||
make: "varparse-errors.mk" line 67: Undefined variable "${:U:OX"
|
||||
make: Bad modifier ":OX" for variable ""
|
||||
make: Bad modifier ":OX" for variable ""
|
||||
make: "varparse-errors.mk" line 68: Undefined variable "${:U:OX"
|
||||
make: "varparse-errors.mk" line 67: Undefined variable "${:U:OX"
|
||||
make: Bad modifier ":OX" for variable ""
|
||||
make: Unclosed variable expression, expecting '}' for modifier "Q" of variable "" with value ""
|
||||
make: Unclosed variable expression, expecting '}' for modifier "sh" of variable "" with value ""
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: varparse-errors.mk,v 1.7 2022/08/24 22:09:41 rillig Exp $
|
||||
# $NetBSD: varparse-errors.mk,v 1.8 2023/02/14 21:56:48 rillig Exp $
|
||||
|
||||
# Tests for parsing and evaluating all kinds of variable expressions.
|
||||
#
|
||||
@ -6,7 +6,6 @@
|
||||
# Var_Subst, collecting typical and not so typical use cases.
|
||||
#
|
||||
# See also:
|
||||
# VarParseResult
|
||||
# Var_Parse
|
||||
# Var_Subst
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: var.c,v 1.1040 2023/02/09 07:34:15 sjg Exp $ */
|
||||
/* $NetBSD: var.c,v 1.1049 2023/03/28 14:39:31 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.1040 2023/02/09 07:34:15 sjg Exp $");
|
||||
MAKE_RCSID("$NetBSD: var.c,v 1.1049 2023/03/28 14:39:31 rillig Exp $");
|
||||
|
||||
/*
|
||||
* Variables are defined using one of the VAR=value assignments. Their
|
||||
@ -336,6 +336,7 @@ static VarExportedMode var_exportedVars = VAR_EXPORTED_NONE;
|
||||
|
||||
static const char VarEvalMode_Name[][32] = {
|
||||
"parse-only",
|
||||
"parse-balanced",
|
||||
"eval",
|
||||
"eval-defined",
|
||||
"eval-keep-dollar",
|
||||
@ -529,7 +530,7 @@ Var_Delete(GNode *scope, const char *varname)
|
||||
|
||||
if (v->exported)
|
||||
unsetenv(v->name.str);
|
||||
if (strcmp(v->name.str, MAKE_EXPORTED) == 0)
|
||||
if (strcmp(v->name.str, ".MAKE.EXPORTED") == 0)
|
||||
var_exportedVars = VAR_EXPORTED_NONE;
|
||||
|
||||
assert(v->name.freeIt == NULL);
|
||||
@ -545,7 +546,6 @@ Var_Delete(GNode *scope, const char *varname)
|
||||
void
|
||||
Var_Undef(const char *arg)
|
||||
{
|
||||
VarParseResult vpr;
|
||||
char *expanded;
|
||||
Words varnames;
|
||||
size_t i;
|
||||
@ -556,8 +556,9 @@ Var_Undef(const char *arg)
|
||||
return;
|
||||
}
|
||||
|
||||
vpr = Var_Subst(arg, SCOPE_GLOBAL, VARE_WANTRES, &expanded);
|
||||
if (vpr != VPR_OK) {
|
||||
expanded = Var_Subst(arg, SCOPE_GLOBAL, VARE_WANTRES);
|
||||
if (expanded == var_Error) {
|
||||
/* TODO: Make this part of the code reachable. */
|
||||
Parse_Error(PARSE_FATAL,
|
||||
"Error in variable names to be undefined");
|
||||
return;
|
||||
@ -627,7 +628,7 @@ ExportVarEnv(Var *v)
|
||||
|
||||
/* XXX: name is injected without escaping it */
|
||||
expr = str_concat3("${", name, "}");
|
||||
(void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &val);
|
||||
val = Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
setenv(name, val, 1);
|
||||
free(val);
|
||||
@ -727,8 +728,8 @@ Var_ReexportVars(void)
|
||||
return;
|
||||
}
|
||||
|
||||
(void)Var_Subst("${" MAKE_EXPORTED ":O:u}", SCOPE_GLOBAL, VARE_WANTRES,
|
||||
&xvarnames);
|
||||
xvarnames = Var_Subst("${.MAKE.EXPORTED:O:u}", SCOPE_GLOBAL,
|
||||
VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
if (xvarnames[0] != '\0') {
|
||||
Words varnames = Str_Words(xvarnames, false);
|
||||
@ -760,7 +761,7 @@ ExportVars(const char *varnames, bool isExport, VarExportMode mode)
|
||||
var_exportedVars = VAR_EXPORTED_SOME;
|
||||
|
||||
if (isExport && mode == VEM_PLAIN)
|
||||
Global_Append(MAKE_EXPORTED, varname);
|
||||
Global_Append(".MAKE.EXPORTED", varname);
|
||||
}
|
||||
Words_Free(words);
|
||||
}
|
||||
@ -768,9 +769,7 @@ ExportVars(const char *varnames, bool isExport, VarExportMode mode)
|
||||
static void
|
||||
ExportVarsExpand(const char *uvarnames, bool isExport, VarExportMode mode)
|
||||
{
|
||||
char *xvarnames;
|
||||
|
||||
(void)Var_Subst(uvarnames, SCOPE_GLOBAL, VARE_WANTRES, &xvarnames);
|
||||
char *xvarnames = Var_Subst(uvarnames, SCOPE_GLOBAL, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
ExportVars(xvarnames, isExport, mode);
|
||||
free(xvarnames);
|
||||
@ -795,8 +794,6 @@ Var_ExportVars(const char *varnames)
|
||||
}
|
||||
|
||||
|
||||
extern char **environ;
|
||||
|
||||
static void
|
||||
ClearEnv(void)
|
||||
{
|
||||
@ -846,10 +843,8 @@ GetVarnamesToUnexport(bool isEnv, const char *arg,
|
||||
}
|
||||
|
||||
if (what != UNEXPORT_NAMED) {
|
||||
char *expanded;
|
||||
/* Using .MAKE.EXPORTED */
|
||||
(void)Var_Subst("${" MAKE_EXPORTED ":O:u}", SCOPE_GLOBAL,
|
||||
VARE_WANTRES, &expanded);
|
||||
char *expanded = Var_Subst("${.MAKE.EXPORTED:O:u}",
|
||||
SCOPE_GLOBAL, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
varnames = FStr_InitOwn(expanded);
|
||||
}
|
||||
@ -878,12 +873,11 @@ UnexportVar(Substring varname, UnexportWhat what)
|
||||
if (what == UNEXPORT_NAMED) {
|
||||
/* Remove the variable names from .MAKE.EXPORTED. */
|
||||
/* XXX: v->name is injected without escaping it */
|
||||
char *expr = str_concat3("${" MAKE_EXPORTED ":N",
|
||||
char *expr = str_concat3("${.MAKE.EXPORTED:N",
|
||||
v->name.str, "}");
|
||||
char *cp;
|
||||
(void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &cp);
|
||||
char *cp = Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES);
|
||||
/* TODO: handle errors */
|
||||
Global_Set(MAKE_EXPORTED, cp);
|
||||
Global_Set(".MAKE.EXPORTED", cp);
|
||||
free(cp);
|
||||
free(expr);
|
||||
}
|
||||
@ -904,7 +898,7 @@ UnexportVars(FStr *varnames, UnexportWhat what)
|
||||
SubstringWords_Free(words);
|
||||
|
||||
if (what != UNEXPORT_NAMED)
|
||||
Global_Delete(MAKE_EXPORTED);
|
||||
Global_Delete(".MAKE.EXPORTED");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1014,7 +1008,7 @@ Var_SetWithFlags(GNode *scope, const char *name, const char *val,
|
||||
|
||||
/*
|
||||
* If requested, don't export these in the environment
|
||||
* individually. We still put them in MAKEOVERRIDES so
|
||||
* individually. We still put them in .MAKEOVERRIDES so
|
||||
* that the command-line settings continue to override
|
||||
* Makefile settings.
|
||||
*/
|
||||
@ -1026,7 +1020,7 @@ Var_SetWithFlags(GNode *scope, const char *name, const char *val,
|
||||
* in ExportVarPlain?
|
||||
*/
|
||||
|
||||
Global_Append(MAKEOVERRIDES, name);
|
||||
Global_Append(".MAKEOVERRIDES", name);
|
||||
}
|
||||
|
||||
if (name[0] == '.' && strcmp(name, MAKE_SAVE_DOLLARS) == 0)
|
||||
@ -1706,7 +1700,7 @@ ModifyWord_Loop(Substring word, SepBuf *buf, void *data)
|
||||
assert(word.end[0] == '\0'); /* assume null-terminated word */
|
||||
Var_SetWithFlags(args->scope, args->var, word.start,
|
||||
VAR_SET_NO_EXPORT);
|
||||
(void)Var_Subst(args->body, args->scope, args->emode, &s);
|
||||
s = Var_Subst(args->body, args->scope, args->emode);
|
||||
/* TODO: handle errors */
|
||||
|
||||
assert(word.end[0] == '\0'); /* assume null-terminated word */
|
||||
@ -2153,36 +2147,26 @@ ParseModifierPartExpr(const char **pp, LazyBuf *part, const ModChain *ch,
|
||||
VarEvalMode emode)
|
||||
{
|
||||
const char *p = *pp;
|
||||
FStr nested_val;
|
||||
|
||||
(void)Var_Parse(&p, ch->expr->scope,
|
||||
VarEvalMode_WithoutKeepDollar(emode), &nested_val);
|
||||
FStr nested_val = Var_Parse(&p, ch->expr->scope,
|
||||
VarEvalMode_WithoutKeepDollar(emode));
|
||||
/* TODO: handle errors */
|
||||
LazyBuf_AddStr(part, nested_val.str);
|
||||
if (VarEvalMode_ShouldEval(emode))
|
||||
LazyBuf_AddStr(part, nested_val.str);
|
||||
else
|
||||
LazyBuf_AddSubstring(part, Substring_Init(*pp, p));
|
||||
FStr_Done(&nested_val);
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
/*
|
||||
* In a part of a modifier, parse a subexpression but don't evaluate it.
|
||||
*
|
||||
* XXX: This whole block is very similar to Var_Parse with VARE_PARSE_ONLY.
|
||||
* There may be subtle edge cases though that are not yet covered in the unit
|
||||
* tests and that are parsed differently, depending on whether they are
|
||||
* evaluated or not.
|
||||
*
|
||||
* This subtle difference is not documented in the manual page, neither is
|
||||
* the difference between parsing ':D' and ':M' documented. No code should
|
||||
* ever depend on these details, but who knows.
|
||||
*
|
||||
* TODO: Before trying to replace this code with Var_Parse, there need to be
|
||||
* more unit tests in varmod-loop.mk. The modifier ':@' uses Var_Subst
|
||||
* internally, in which a '$' is escaped as '$$', not as '\$' like in other
|
||||
* modifiers. When parsing the body text '$${var}', skipping over the first
|
||||
* '$' would treat '${var}' as a make expression, not as a shell variable.
|
||||
* In a part of a modifier, parse some text that looks like a subexpression.
|
||||
* If the text starts with '$(', any '(' and ')' must be balanced.
|
||||
* If the text starts with '${', any '{' and '}' must be balanced.
|
||||
* If the text starts with '$', that '$' is copied, it is not parsed as a
|
||||
* short-name variable expression.
|
||||
*/
|
||||
static void
|
||||
ParseModifierPartDollar(const char **pp, LazyBuf *part)
|
||||
ParseModifierPartBalanced(const char **pp, LazyBuf *part)
|
||||
{
|
||||
const char *p = *pp;
|
||||
const char *start = *pp;
|
||||
@ -2209,7 +2193,7 @@ ParseModifierPartDollar(const char **pp, LazyBuf *part)
|
||||
}
|
||||
|
||||
/* See ParseModifierPart for the documentation. */
|
||||
static VarParseResult
|
||||
static bool
|
||||
ParseModifierPartSubst(
|
||||
const char **pp,
|
||||
char delim,
|
||||
@ -2249,10 +2233,10 @@ ParseModifierPartSubst(
|
||||
else
|
||||
LazyBuf_Add(part, *p);
|
||||
p++;
|
||||
} else if (VarEvalMode_ShouldEval(emode))
|
||||
ParseModifierPartExpr(&p, part, ch, emode);
|
||||
} else if (emode == VARE_PARSE_BALANCED)
|
||||
ParseModifierPartBalanced(&p, part);
|
||||
else
|
||||
ParseModifierPartDollar(&p, part);
|
||||
ParseModifierPartExpr(&p, part, ch, emode);
|
||||
}
|
||||
|
||||
if (*p != delim) {
|
||||
@ -2260,7 +2244,7 @@ ParseModifierPartSubst(
|
||||
Error("Unfinished modifier for \"%s\" ('%c' missing)",
|
||||
ch->expr->name, delim);
|
||||
LazyBuf_Done(part);
|
||||
return VPR_ERR;
|
||||
return false;
|
||||
}
|
||||
|
||||
*pp = p + 1;
|
||||
@ -2271,7 +2255,7 @@ ParseModifierPartSubst(
|
||||
(int)Substring_Length(sub), sub.start);
|
||||
}
|
||||
|
||||
return VPR_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2280,11 +2264,11 @@ ParseModifierPartSubst(
|
||||
* including the next unescaped delimiter. The delimiter, as well as the
|
||||
* backslash or the dollar, can be escaped with a backslash.
|
||||
*
|
||||
* Return VPR_OK if parsing succeeded, together with the parsed (and possibly
|
||||
* Return true if parsing succeeded, together with the parsed (and possibly
|
||||
* expanded) part. In that case, pp points right after the delimiter. The
|
||||
* delimiter is not included in the part though.
|
||||
*/
|
||||
static VarParseResult
|
||||
static bool
|
||||
ParseModifierPart(
|
||||
/* The parsing position, updated upon return */
|
||||
const char **pp,
|
||||
@ -2434,15 +2418,13 @@ ApplyModifier_Loop(const char **pp, ModChain *ch)
|
||||
Expr *expr = ch->expr;
|
||||
struct ModifyWord_LoopArgs args;
|
||||
char prev_sep;
|
||||
VarParseResult res;
|
||||
LazyBuf tvarBuf, strBuf;
|
||||
FStr tvar, str;
|
||||
|
||||
args.scope = expr->scope;
|
||||
|
||||
(*pp)++; /* Skip the first '@' */
|
||||
res = ParseModifierPart(pp, '@', VARE_PARSE_ONLY, ch, &tvarBuf);
|
||||
if (res != VPR_OK)
|
||||
if (!ParseModifierPart(pp, '@', VARE_PARSE_ONLY, ch, &tvarBuf))
|
||||
return AMR_CLEANUP;
|
||||
tvar = LazyBuf_DoneGet(&tvarBuf);
|
||||
args.var = tvar.str;
|
||||
@ -2454,8 +2436,7 @@ ApplyModifier_Loop(const char **pp, ModChain *ch)
|
||||
return AMR_CLEANUP;
|
||||
}
|
||||
|
||||
res = ParseModifierPart(pp, '@', VARE_PARSE_ONLY, ch, &strBuf);
|
||||
if (res != VPR_OK)
|
||||
if (!ParseModifierPart(pp, '@', VARE_PARSE_BALANCED, ch, &strBuf))
|
||||
return AMR_CLEANUP;
|
||||
str = LazyBuf_DoneGet(&strBuf);
|
||||
args.body = str.str;
|
||||
@ -2508,11 +2489,8 @@ ParseModifier_Defined(const char **pp, ModChain *ch, bool shouldEval,
|
||||
|
||||
/* Nested variable expression */
|
||||
if (*p == '$') {
|
||||
FStr val;
|
||||
|
||||
(void)Var_Parse(&p, ch->expr->scope,
|
||||
shouldEval ? ch->expr->emode : VARE_PARSE_ONLY,
|
||||
&val);
|
||||
FStr val = Var_Parse(&p, ch->expr->scope,
|
||||
shouldEval ? ch->expr->emode : VARE_PARSE_ONLY);
|
||||
/* TODO: handle errors */
|
||||
if (shouldEval)
|
||||
LazyBuf_AddStr(buf, val.str);
|
||||
@ -2666,13 +2644,11 @@ static ApplyModifierResult
|
||||
ApplyModifier_ShellCommand(const char **pp, ModChain *ch)
|
||||
{
|
||||
Expr *expr = ch->expr;
|
||||
VarParseResult res;
|
||||
LazyBuf cmdBuf;
|
||||
FStr cmd;
|
||||
|
||||
(*pp)++;
|
||||
res = ParseModifierPart(pp, '!', expr->emode, ch, &cmdBuf);
|
||||
if (res != VPR_OK)
|
||||
if (!ParseModifierPart(pp, '!', expr->emode, ch, &cmdBuf))
|
||||
return AMR_CLEANUP;
|
||||
cmd = LazyBuf_DoneGet(&cmdBuf);
|
||||
|
||||
@ -2818,7 +2794,7 @@ ParseModifier_Match(const char **pp, const ModChain *ch)
|
||||
* XXX: Contrary to ParseModifierPart, a dollar in a ':M' or
|
||||
* ':N' modifier must be escaped as '$$', not as '\$'.
|
||||
*/
|
||||
(void)Var_Subst(pattern, expr->scope, expr->emode, &pattern);
|
||||
pattern = Var_Subst(pattern, expr->scope, expr->emode);
|
||||
/* TODO: handle errors */
|
||||
free(old_pattern);
|
||||
}
|
||||
@ -2875,7 +2851,6 @@ ApplyModifier_Subst(const char **pp, ModChain *ch)
|
||||
{
|
||||
struct ModifyWord_SubstArgs args;
|
||||
bool oneBigWord;
|
||||
VarParseResult res;
|
||||
LazyBuf lhsBuf, rhsBuf;
|
||||
|
||||
char delim = (*pp)[1];
|
||||
@ -2895,15 +2870,13 @@ ApplyModifier_Subst(const char **pp, ModChain *ch)
|
||||
(*pp)++;
|
||||
}
|
||||
|
||||
res = ParseModifierPartSubst(pp, delim, ch->expr->emode, ch, &lhsBuf,
|
||||
&args.pflags, NULL);
|
||||
if (res != VPR_OK)
|
||||
if (!ParseModifierPartSubst(pp, delim, ch->expr->emode, ch, &lhsBuf,
|
||||
&args.pflags, NULL))
|
||||
return AMR_CLEANUP;
|
||||
args.lhs = LazyBuf_Get(&lhsBuf);
|
||||
|
||||
res = ParseModifierPartSubst(pp, delim, ch->expr->emode, ch, &rhsBuf,
|
||||
NULL, &args);
|
||||
if (res != VPR_OK) {
|
||||
if (!ParseModifierPartSubst(pp, delim, ch->expr->emode, ch, &rhsBuf,
|
||||
NULL, &args)) {
|
||||
LazyBuf_Done(&lhsBuf);
|
||||
return AMR_CLEANUP;
|
||||
}
|
||||
@ -2928,7 +2901,6 @@ ApplyModifier_Regex(const char **pp, ModChain *ch)
|
||||
struct ModifyWord_SubstRegexArgs args;
|
||||
bool oneBigWord;
|
||||
int error;
|
||||
VarParseResult res;
|
||||
LazyBuf reBuf, replaceBuf;
|
||||
FStr re;
|
||||
|
||||
@ -2941,13 +2913,11 @@ ApplyModifier_Regex(const char **pp, ModChain *ch)
|
||||
|
||||
*pp += 2;
|
||||
|
||||
res = ParseModifierPart(pp, delim, ch->expr->emode, ch, &reBuf);
|
||||
if (res != VPR_OK)
|
||||
if (!ParseModifierPart(pp, delim, ch->expr->emode, ch, &reBuf))
|
||||
return AMR_CLEANUP;
|
||||
re = LazyBuf_DoneGet(&reBuf);
|
||||
|
||||
res = ParseModifierPart(pp, delim, ch->expr->emode, ch, &replaceBuf);
|
||||
if (res != VPR_OK) {
|
||||
if (!ParseModifierPart(pp, delim, ch->expr->emode, ch, &replaceBuf)) {
|
||||
FStr_Done(&re);
|
||||
return AMR_CLEANUP;
|
||||
}
|
||||
@ -3180,14 +3150,12 @@ ApplyModifier_Words(const char **pp, ModChain *ch)
|
||||
Expr *expr = ch->expr;
|
||||
const char *estr;
|
||||
int first, last;
|
||||
VarParseResult res;
|
||||
const char *p;
|
||||
LazyBuf estrBuf;
|
||||
FStr festr;
|
||||
|
||||
(*pp)++; /* skip the '[' */
|
||||
res = ParseModifierPart(pp, ']', expr->emode, ch, &estrBuf);
|
||||
if (res != VPR_OK)
|
||||
if (!ParseModifierPart(pp, ']', expr->emode, ch, &estrBuf))
|
||||
return AMR_CLEANUP;
|
||||
festr = LazyBuf_DoneGet(&estrBuf);
|
||||
estr = festr.str;
|
||||
@ -3412,7 +3380,6 @@ static ApplyModifierResult
|
||||
ApplyModifier_IfElse(const char **pp, ModChain *ch)
|
||||
{
|
||||
Expr *expr = ch->expr;
|
||||
VarParseResult res;
|
||||
LazyBuf thenBuf;
|
||||
LazyBuf elseBuf;
|
||||
|
||||
@ -3429,12 +3396,10 @@ ApplyModifier_IfElse(const char **pp, ModChain *ch)
|
||||
}
|
||||
|
||||
(*pp)++; /* skip past the '?' */
|
||||
res = ParseModifierPart(pp, ':', then_emode, ch, &thenBuf);
|
||||
if (res != VPR_OK)
|
||||
if (!ParseModifierPart(pp, ':', then_emode, ch, &thenBuf))
|
||||
return AMR_CLEANUP;
|
||||
|
||||
res = ParseModifierPart(pp, ch->endc, else_emode, ch, &elseBuf);
|
||||
if (res != VPR_OK) {
|
||||
if (!ParseModifierPart(pp, ch->endc, else_emode, ch, &elseBuf)) {
|
||||
LazyBuf_Done(&thenBuf);
|
||||
return AMR_CLEANUP;
|
||||
}
|
||||
@ -3495,7 +3460,6 @@ ApplyModifier_Assign(const char **pp, ModChain *ch)
|
||||
Expr *expr = ch->expr;
|
||||
GNode *scope;
|
||||
FStr val;
|
||||
VarParseResult res;
|
||||
LazyBuf buf;
|
||||
|
||||
const char *mod = *pp;
|
||||
@ -3515,8 +3479,7 @@ ApplyModifier_Assign(const char **pp, ModChain *ch)
|
||||
|
||||
*pp = mod + (op[0] == '+' || op[0] == '?' || op[0] == '!' ? 3 : 2);
|
||||
|
||||
res = ParseModifierPart(pp, ch->endc, expr->emode, ch, &buf);
|
||||
if (res != VPR_OK)
|
||||
if (!ParseModifierPart(pp, ch->endc, expr->emode, ch, &buf))
|
||||
return AMR_CLEANUP;
|
||||
val = LazyBuf_DoneGet(&buf);
|
||||
|
||||
@ -3650,7 +3613,6 @@ static ApplyModifierResult
|
||||
ApplyModifier_SysV(const char **pp, ModChain *ch)
|
||||
{
|
||||
Expr *expr = ch->expr;
|
||||
VarParseResult res;
|
||||
LazyBuf lhsBuf, rhsBuf;
|
||||
FStr rhs;
|
||||
struct ModifyWord_SysVSubstArgs args;
|
||||
@ -3680,15 +3642,13 @@ ApplyModifier_SysV(const char **pp, ModChain *ch)
|
||||
if (*p != ch->endc || !eqFound)
|
||||
return AMR_UNKNOWN;
|
||||
|
||||
res = ParseModifierPart(pp, '=', expr->emode, ch, &lhsBuf);
|
||||
if (res != VPR_OK)
|
||||
if (!ParseModifierPart(pp, '=', expr->emode, ch, &lhsBuf))
|
||||
return AMR_CLEANUP;
|
||||
|
||||
/*
|
||||
* The SysV modifier lasts until the end of the variable expression.
|
||||
*/
|
||||
res = ParseModifierPart(pp, ch->endc, expr->emode, ch, &rhsBuf);
|
||||
if (res != VPR_OK) {
|
||||
if (!ParseModifierPart(pp, ch->endc, expr->emode, ch, &rhsBuf)) {
|
||||
LazyBuf_Done(&lhsBuf);
|
||||
return AMR_CLEANUP;
|
||||
}
|
||||
@ -3714,6 +3674,7 @@ ApplyModifier_SysV(const char **pp, ModChain *ch)
|
||||
|
||||
done:
|
||||
LazyBuf_Done(&lhsBuf);
|
||||
FStr_Done(&rhs);
|
||||
return AMR_OK;
|
||||
}
|
||||
#endif
|
||||
@ -3743,6 +3704,18 @@ ApplyModifier_SunShell(const char **pp, ModChain *ch)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In cases where the evaluation mode and the definedness are the "standard"
|
||||
* ones, don't log them, to keep the logs readable.
|
||||
*/
|
||||
static bool
|
||||
ShouldLogInSimpleFormat(const Expr *expr)
|
||||
{
|
||||
return (expr->emode == VARE_WANTRES ||
|
||||
expr->emode == VARE_UNDEFERR) &&
|
||||
expr->defined == DEF_REGULAR;
|
||||
}
|
||||
|
||||
static void
|
||||
LogBeforeApply(const ModChain *ch, const char *mod)
|
||||
{
|
||||
@ -3760,8 +3733,7 @@ LogBeforeApply(const ModChain *ch, const char *mod)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((expr->emode == VARE_WANTRES || expr->emode == VARE_UNDEFERR) &&
|
||||
expr->defined == DEF_REGULAR) {
|
||||
if (ShouldLogInSimpleFormat(expr)) {
|
||||
debug_printf(
|
||||
"Evaluating modifier ${%s:%c%s} on value \"%s\"\n",
|
||||
expr->name, mod[0], is_single_char ? "" : "...",
|
||||
@ -3782,9 +3754,7 @@ LogAfterApply(const ModChain *ch, const char *p, const char *mod)
|
||||
const char *value = Expr_Str(expr);
|
||||
const char *quot = value == var_Error ? "" : "\"";
|
||||
|
||||
if ((expr->emode == VARE_WANTRES || expr->emode == VARE_UNDEFERR) &&
|
||||
expr->defined == DEF_REGULAR) {
|
||||
|
||||
if (ShouldLogInSimpleFormat(expr)) {
|
||||
debug_printf("Result of ${%s:%.*s} is %s%s%s\n",
|
||||
expr->name, (int)(p - mod), mod,
|
||||
quot, value == var_Error ? "error" : value, quot);
|
||||
@ -3892,9 +3862,7 @@ ApplyModifiersIndirect(ModChain *ch, const char **pp)
|
||||
{
|
||||
Expr *expr = ch->expr;
|
||||
const char *p = *pp;
|
||||
FStr mods;
|
||||
|
||||
(void)Var_Parse(&p, expr->scope, expr->emode, &mods);
|
||||
FStr mods = Var_Parse(&p, expr->scope, expr->emode);
|
||||
/* TODO: handle errors */
|
||||
|
||||
if (mods.str[0] != '\0' && !IsDelimiter(*p, ch)) {
|
||||
@ -4079,7 +4047,7 @@ ApplyModifiers(
|
||||
* commands with evaluation errors should not be run at all.
|
||||
*
|
||||
* To make that happen, Var_Subst must report the actual errors
|
||||
* instead of returning VPR_OK unconditionally.
|
||||
* instead of returning the resulting string unconditionally.
|
||||
*/
|
||||
*pp = p;
|
||||
Expr_SetValueRefer(expr, var_Error);
|
||||
@ -4169,8 +4137,7 @@ ParseVarname(const char **pp, char startc, char endc,
|
||||
|
||||
/* A variable inside a variable, expand. */
|
||||
if (*p == '$') {
|
||||
FStr nested_val;
|
||||
(void)Var_Parse(&p, scope, emode, &nested_val);
|
||||
FStr nested_val = Var_Parse(&p, scope, emode);
|
||||
/* TODO: handle errors */
|
||||
LazyBuf_AddStr(buf, nested_val.str);
|
||||
FStr_Done(&nested_val);
|
||||
@ -4211,7 +4178,7 @@ IsShortVarnameValid(char varname, const char *start)
|
||||
static bool
|
||||
ParseVarnameShort(char varname, const char **pp, GNode *scope,
|
||||
VarEvalMode emode,
|
||||
VarParseResult *out_false_res, const char **out_false_val,
|
||||
const char **out_false_val,
|
||||
Var **out_true_var)
|
||||
{
|
||||
char name[2];
|
||||
@ -4220,7 +4187,6 @@ ParseVarnameShort(char varname, const char **pp, GNode *scope,
|
||||
|
||||
if (!IsShortVarnameValid(varname, *pp)) {
|
||||
(*pp)++; /* only skip the '$' */
|
||||
*out_false_res = VPR_ERR;
|
||||
*out_false_val = var_Error;
|
||||
return false;
|
||||
}
|
||||
@ -4243,22 +4209,8 @@ ParseVarnameShort(char varname, const char **pp, GNode *scope,
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@ -4289,30 +4241,22 @@ FindLocalLegacyVar(Substring varname, GNode *scope,
|
||||
return v;
|
||||
}
|
||||
|
||||
static VarParseResult
|
||||
static FStr
|
||||
EvalUndefined(bool dynamic, const char *start, const char *p,
|
||||
Substring varname, VarEvalMode emode, FStr *out_val)
|
||||
Substring varname, VarEvalMode emode)
|
||||
{
|
||||
if (dynamic) {
|
||||
*out_val = FStr_InitOwn(bmake_strsedup(start, p));
|
||||
return VPR_OK;
|
||||
}
|
||||
if (dynamic)
|
||||
return FStr_InitOwn(bmake_strsedup(start, p));
|
||||
|
||||
if (emode == VARE_UNDEFERR && opts.strict) {
|
||||
Parse_Error(PARSE_FATAL,
|
||||
"Variable \"%.*s\" is undefined",
|
||||
(int)Substring_Length(varname), varname.start);
|
||||
*out_val = FStr_InitRefer(var_Error);
|
||||
return VPR_ERR;
|
||||
return FStr_InitRefer(var_Error);
|
||||
}
|
||||
|
||||
if (emode == VARE_UNDEFERR) {
|
||||
*out_val = FStr_InitRefer(var_Error);
|
||||
return VPR_UNDEF; /* XXX: Should be VPR_ERR instead. */
|
||||
}
|
||||
|
||||
*out_val = FStr_InitRefer(varUndefined);
|
||||
return VPR_OK;
|
||||
return FStr_InitRefer(
|
||||
emode == VARE_UNDEFERR ? var_Error : varUndefined);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4329,7 +4273,6 @@ ParseVarnameLong(
|
||||
VarEvalMode emode,
|
||||
|
||||
const char **out_false_pp,
|
||||
VarParseResult *out_false_res,
|
||||
FStr *out_false_val,
|
||||
|
||||
char *out_true_endc,
|
||||
@ -4364,7 +4307,6 @@ ParseVarnameLong(
|
||||
LazyBuf_Done(&varname);
|
||||
*out_false_pp = p;
|
||||
*out_false_val = FStr_InitRefer(var_Error);
|
||||
*out_false_res = VPR_ERR;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -4394,8 +4336,8 @@ ParseVarnameLong(
|
||||
if (!haveModifier) {
|
||||
p++; /* skip endc */
|
||||
*out_false_pp = p;
|
||||
*out_false_res = EvalUndefined(dynamic, start, p,
|
||||
name, emode, out_false_val);
|
||||
*out_false_val = EvalUndefined(dynamic, start, p,
|
||||
name, emode);
|
||||
LazyBuf_Done(&varname);
|
||||
return false;
|
||||
}
|
||||
@ -4497,23 +4439,23 @@ Var_Parse_FastLane(const char **pp, VarEvalMode emode, FStr *out_value)
|
||||
* point to some random character in the string, to the
|
||||
* location of the parse error, or at the end of the
|
||||
* string.
|
||||
* *out_val The value of the variable expression, never NULL.
|
||||
* *out_val var_Error if there was a parse error.
|
||||
* *out_val var_Error if the base variable of the expression was
|
||||
* return The value of the variable expression, never NULL.
|
||||
* return var_Error if there was a parse error.
|
||||
* return var_Error if the base variable of the expression was
|
||||
* undefined, emode is VARE_UNDEFERR, and none of
|
||||
* the modifiers turned the undefined expression into a
|
||||
* defined expression.
|
||||
* XXX: It is not guaranteed that an error message has
|
||||
* been printed.
|
||||
* *out_val varUndefined if the base variable of the expression
|
||||
* return varUndefined if the base variable of the expression
|
||||
* was undefined, emode was not VARE_UNDEFERR,
|
||||
* and none of the modifiers turned the undefined
|
||||
* expression into a defined expression.
|
||||
* XXX: It is not guaranteed that an error message has
|
||||
* been printed.
|
||||
*/
|
||||
VarParseResult
|
||||
Var_Parse(const char **pp, GNode *scope, VarEvalMode emode, FStr *out_val)
|
||||
FStr
|
||||
Var_Parse(const char **pp, GNode *scope, VarEvalMode emode)
|
||||
{
|
||||
const char *p = *pp;
|
||||
const char *const start = p;
|
||||
@ -4531,15 +4473,16 @@ Var_Parse(const char **pp, GNode *scope, VarEvalMode emode, FStr *out_val)
|
||||
Var *v;
|
||||
Expr expr = Expr_Literal(NULL, FStr_InitRefer(NULL), emode,
|
||||
scope, DEF_REGULAR);
|
||||
FStr val;
|
||||
|
||||
if (Var_Parse_FastLane(pp, emode, out_val))
|
||||
return VPR_OK;
|
||||
if (Var_Parse_FastLane(pp, emode, &val))
|
||||
return val;
|
||||
|
||||
/* TODO: Reduce computations in parse-only mode. */
|
||||
|
||||
DEBUG2(VAR, "Var_Parse: %s (%s)\n", start, VarEvalMode_Name[emode]);
|
||||
|
||||
*out_val = FStr_InitRefer(NULL);
|
||||
val = FStr_InitRefer(NULL);
|
||||
extramodifiers = NULL; /* extra modifiers to apply first */
|
||||
dynamic = false;
|
||||
|
||||
@ -4547,19 +4490,16 @@ Var_Parse(const char **pp, GNode *scope, VarEvalMode emode, FStr *out_val)
|
||||
|
||||
startc = p[1];
|
||||
if (startc != '(' && startc != '{') {
|
||||
VarParseResult res;
|
||||
if (!ParseVarnameShort(startc, pp, scope, emode, &res,
|
||||
&out_val->str, &v))
|
||||
return res;
|
||||
if (!ParseVarnameShort(startc, pp, scope, emode, &val.str, &v))
|
||||
return val;
|
||||
haveModifier = false;
|
||||
p++;
|
||||
} else {
|
||||
VarParseResult res;
|
||||
if (!ParseVarnameLong(&p, startc, scope, emode,
|
||||
pp, &res, out_val,
|
||||
pp, &val,
|
||||
&endc, &v, &haveModifier, &extramodifiers,
|
||||
&dynamic, &expr.defined))
|
||||
return res;
|
||||
return val;
|
||||
}
|
||||
|
||||
expr.name = v->name.str;
|
||||
@ -4595,8 +4535,7 @@ Var_Parse(const char **pp, GNode *scope, VarEvalMode emode, FStr *out_val)
|
||||
if (opts.strict)
|
||||
nested_emode = VarEvalMode_UndefOk(nested_emode);
|
||||
v->inUse = true;
|
||||
(void)Var_Subst(Expr_Str(&expr), scope, nested_emode,
|
||||
&expanded);
|
||||
expanded = Var_Subst(Expr_Str(&expr), scope, nested_emode);
|
||||
v->inUse = false;
|
||||
/* TODO: handle errors */
|
||||
Expr_SetValueOwn(&expr, expanded);
|
||||
@ -4641,8 +4580,7 @@ Var_Parse(const char **pp, GNode *scope, VarEvalMode emode, FStr *out_val)
|
||||
VarFreeShortLived(v);
|
||||
}
|
||||
|
||||
*out_val = expr.value;
|
||||
return VPR_OK; /* XXX: Is not correct in all cases */
|
||||
return expr.value;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -4661,9 +4599,7 @@ VarSubstExpr(const char **pp, Buffer *buf, GNode *scope,
|
||||
{
|
||||
const char *p = *pp;
|
||||
const char *nested_p = p;
|
||||
FStr val;
|
||||
|
||||
(void)Var_Parse(&nested_p, scope, emode, &val);
|
||||
FStr val = Var_Parse(&nested_p, scope, emode);
|
||||
/* TODO: handle errors */
|
||||
|
||||
if (val.str == var_Error || val.str == varUndefined) {
|
||||
@ -4737,8 +4673,8 @@ VarSubstPlain(const char **pp, Buffer *res)
|
||||
* variables. The other scopes are searched as well.
|
||||
* emode The mode for parsing or evaluating subexpressions.
|
||||
*/
|
||||
VarParseResult
|
||||
Var_Subst(const char *str, GNode *scope, VarEvalMode emode, char **out_res)
|
||||
char *
|
||||
Var_Subst(const char *str, GNode *scope, VarEvalMode emode)
|
||||
{
|
||||
const char *p = str;
|
||||
Buffer res;
|
||||
@ -4762,8 +4698,7 @@ Var_Subst(const char *str, GNode *scope, VarEvalMode emode, char **out_res)
|
||||
VarSubstPlain(&p, &res);
|
||||
}
|
||||
|
||||
*out_res = Buf_DoneDataCompact(&res);
|
||||
return VPR_OK;
|
||||
return Buf_DoneDataCompact(&res);
|
||||
}
|
||||
|
||||
void
|
||||
@ -4773,7 +4708,7 @@ Var_Expand(FStr *str, GNode *scope, VarEvalMode emode)
|
||||
|
||||
if (strchr(str->str, '$') == NULL)
|
||||
return;
|
||||
(void)Var_Subst(str->str, scope, emode, &expanded);
|
||||
expanded = Var_Subst(str->str, scope, emode);
|
||||
/* TODO: handle errors */
|
||||
FStr_Done(str);
|
||||
*str = FStr_InitOwn(expanded);
|
||||
|
@ -12,7 +12,7 @@ CFLAGS+= -I${.CURDIR}
|
||||
CLEANDIRS+= FreeBSD
|
||||
CLEANFILES+= bootstrap
|
||||
|
||||
# $Id: Makefile,v 1.123 2023/01/28 02:49:20 sjg Exp $
|
||||
# $Id: Makefile,v 1.124 2023/02/25 20:27:44 sjg Exp $
|
||||
|
||||
PROG?= ${.CURDIR:T}
|
||||
|
||||
@ -140,9 +140,7 @@ SHAREDIR= ${SHAREDIR.bmake:U${prefix}/share}
|
||||
BINDIR= ${BINDIR.bmake:U${prefix}/bin}
|
||||
MANDIR= ${MANDIR.bmake:U${SHAREDIR}/man}
|
||||
|
||||
.if !exists(.depend)
|
||||
${OBJS}: config.h
|
||||
.endif
|
||||
|
||||
|
||||
# A simple unit-test driver to help catch regressions
|
||||
|
@ -7,7 +7,7 @@ SRCTOP?= ${.CURDIR:H:H}
|
||||
|
||||
# things set by configure
|
||||
|
||||
_MAKE_VERSION?=20230208
|
||||
_MAKE_VERSION?=20230414
|
||||
|
||||
prefix?= /usr
|
||||
srcdir= ${SRCTOP}/contrib/bmake
|
||||
|
@ -2,9 +2,9 @@
|
||||
# See contrib/bmake/bsd.after-import.mk
|
||||
#
|
||||
# $FreeBSD$
|
||||
# $Id: Makefile,v 1.191 2023/01/24 06:09:49 sjg Exp $
|
||||
# $Id: Makefile,v 1.193 2023/02/25 20:03:25 sjg Exp $
|
||||
#
|
||||
# $NetBSD: Makefile,v 1.331 2023/01/24 00:24:02 sjg Exp $
|
||||
# $NetBSD: Makefile,v 1.333 2023/02/25 19:30:32 sjg Exp $
|
||||
#
|
||||
# Unit tests for make(1)
|
||||
#
|
||||
@ -36,6 +36,21 @@
|
||||
.MAKE.OS?= ${uname -s:L:sh}
|
||||
.MAKE.UID?= ${id -u:L:sh}
|
||||
|
||||
# for many tests we need a TMPDIR that will not collide
|
||||
# with other users.
|
||||
.if ${.OBJDIR} != ${.CURDIR}
|
||||
# easy
|
||||
TMPDIR:= ${.OBJDIR}/tmp
|
||||
.elif defined(TMPDIR)
|
||||
TMPDIR:= ${TMPDIR}/uid${.MAKE.UID}
|
||||
.else
|
||||
TMPDIR:= /tmp/uid${.MAKE.UID}
|
||||
.endif
|
||||
# make sure it exists
|
||||
.if !exist(${TMPDIR})
|
||||
_!= mkdir -p ${TMPDIR}
|
||||
.endif
|
||||
|
||||
# Each test is in a sub-makefile.
|
||||
# Keep the list sorted.
|
||||
# Any test that is commented out must be ignored in
|
||||
@ -410,12 +425,16 @@ TESTS+= varname-dot-make-makefiles
|
||||
TESTS+= varname-dot-make-meta-bailiwick
|
||||
TESTS+= varname-dot-make-meta-created
|
||||
TESTS+= varname-dot-make-meta-files
|
||||
.if ${.MAKE.PATH_FILEMON:Uno:Nktrace:N/dev*} == "" && ${TMPDIR:N/tmp*:N/var/tmp*} != ""
|
||||
# these tests will not work if TMPDIR is or is a subdir of
|
||||
# /tmp or /var/tmp
|
||||
TESTS+= varname-dot-make-meta-ignore_filter
|
||||
TESTS+= varname-dot-make-meta-ignore_paths
|
||||
TESTS+= varname-dot-make-meta-ignore_patterns
|
||||
TESTS+= varname-dot-make-path_filemon
|
||||
.endif
|
||||
TESTS+= varname-dot-make-meta-prefix
|
||||
TESTS+= varname-dot-make-mode
|
||||
TESTS+= varname-dot-make-path_filemon
|
||||
TESTS+= varname-dot-make-pid
|
||||
TESTS+= varname-dot-make-ppid
|
||||
TESTS+= varname-dot-make-save_dollars
|
||||
@ -542,6 +561,9 @@ SED_CMDS.opt-chdir= -e 's,\(nonexistent\).[1-9][0-9]*,\1,' \
|
||||
-e '/name/s,file,File,' \
|
||||
-e 's,no such,No such,' \
|
||||
-e 's,Filename,File name,'
|
||||
|
||||
# meta line numbers can vary based on filemon implementation
|
||||
SED_CMDS.meta-ignore= -e 's,\(\.meta:\) [1-9][0-9]*:,\1 <line>:,'
|
||||
SED_CMDS.opt-debug-graph1= ${STD_SED_CMDS.dg1}
|
||||
SED_CMDS.opt-debug-graph2= ${STD_SED_CMDS.dg2}
|
||||
SED_CMDS.opt-debug-graph3= ${STD_SED_CMDS.dg3}
|
||||
@ -575,6 +597,9 @@ SED_CMDS.var-op-shell+= ${STD_SED_CMDS.white-space}
|
||||
SED_CMDS.vardebug+= -e 's,${.SHELL},</path/to/shell>,'
|
||||
SED_CMDS.varmod-subst-regex+= ${STD_SED_CMDS.regex}
|
||||
SED_CMDS.varparse-errors+= ${STD_SED_CMDS.timestamp}
|
||||
SED_CMDS.varname-dot-make-meta-ignore_filter+= ${SED_CMDS.meta-ignore}
|
||||
SED_CMDS.varname-dot-make-meta-ignore_paths+= ${SED_CMDS.meta-ignore}
|
||||
SED_CMDS.varname-dot-make-meta-ignore_patterns+= ${SED_CMDS.meta-ignore}
|
||||
SED_CMDS.varname-dot-parsedir= -e '/in some cases/ s,^make: "[^"]*,make: "<normalized>,'
|
||||
SED_CMDS.varname-dot-parsefile= -e '/in some cases/ s,^make: "[^"]*,make: "<normalized>,'
|
||||
SED_CMDS.varname-dot-shell= -e 's, = /[^ ]*, = (details omitted),g'
|
||||
@ -717,22 +742,6 @@ LANG= C
|
||||
_MKMSG_TEST= :
|
||||
.endif
|
||||
|
||||
|
||||
# for many tests we need a TMPDIR that will not collide
|
||||
# with other users.
|
||||
.if ${.OBJDIR} != ${.CURDIR}
|
||||
# easy
|
||||
TMPDIR:= ${.OBJDIR}/tmp
|
||||
.elif defined(TMPDIR)
|
||||
TMPDIR:= ${TMPDIR}/uid${.MAKE.UID}
|
||||
.else
|
||||
TMPDIR:= /tmp/uid${.MAKE.UID}
|
||||
.endif
|
||||
# make sure it exists
|
||||
.if !exist(${TMPDIR})
|
||||
_!= mkdir -p ${TMPDIR}
|
||||
.endif
|
||||
|
||||
# Some Linux systems such as Fedora have deprecated egrep in favor of grep -E.
|
||||
.if ${.MAKE.OS:NLinux} == ""
|
||||
EGREP= grep -E
|
||||
@ -772,23 +781,23 @@ LIMIT_RESOURCES?= :
|
||||
|
||||
# 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:,'
|
||||
_SED_CMDS+= -e 's,${TEST_MAKE:S,.,\\.,g},make,'
|
||||
_SED_CMDS+= -e 's,^usage: ${TEST_MAKE:T:S,.,\\.,g} ,usage: make ,'
|
||||
# replace anything after 'stopped in' with unit-tests
|
||||
# Replace anything after 'stopped in' with unit-tests
|
||||
_SED_CMDS+= -e '/stopped/s, /.*, unit-tests,'
|
||||
# Allow the test files to be placed anywhere.
|
||||
_SED_CMDS+= -e 's,\(\.PARSEDIR}\) = `'"/[^']*'"',\1 = <some-dir>,'
|
||||
_SED_CMDS+= -e 's,\(\.INCLUDEDFROMDIR}\) = `'"/[^']*'"',\1 = <some-dir>,'
|
||||
_SED_CMDS+= -e 's,${TMPDIR},<tmpdir>,g'
|
||||
_SED_CMDS+= -e 's,${TMPDIR},<tmpdir>,g' -e 's,${TMPDIR:tA},<tmpdir>,g'
|
||||
# canonicalize ${.OBJDIR} and ${.CURDIR}
|
||||
_SED_CMDS+= -e 's,${.CURDIR},<curdir>,g'
|
||||
.if ${.OBJDIR} != ${.CURDIR}
|
||||
# yes this is inaccurate but none of the tests expect <objdir> anywhere
|
||||
# which we get depending on how MAKEOBJDIR is set.
|
||||
_SED_CMDS+= -e 's,${.OBJDIR},<curdir>,g'
|
||||
_SED_CMDS+= -e 's,${.OBJDIR},<curdir>,g' -e 's,${.OBJDIR:tA},<curdir>,g'
|
||||
.endif
|
||||
_SED_CMDS+= -e 's,${.CURDIR},<curdir>,g'
|
||||
# always pretend .MAKE was called 'make'
|
||||
_SED_CMDS+= -e 's,^${TEST_MAKE:T:S,.,\\.,g}[][0-9]*:,make:,'
|
||||
_SED_CMDS+= -e 's,${TEST_MAKE:S,.,\\.,g},make,'
|
||||
_SED_CMDS+= -e 's,^usage: ${TEST_MAKE:T:S,.,\\.,g} ,usage: make ,'
|
||||
_SED_CMDS+= -e 's,<curdir>/,,g'
|
||||
_SED_CMDS+= -e 's,${UNIT_TESTS:S,.,\\.,g}/,,g'
|
||||
_SED_CMDS+= -e '/MAKE_VERSION/d'
|
||||
|
Loading…
Reference in New Issue
Block a user