mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
Merge bmake-20230510
Merge commit '945078deae448e0a13c34b3393d836087719fb16'
This commit is contained in:
commit
c1d01b5fd6
|
@ -1,3 +1,27 @@
|
||||||
|
2023-05-10 Simon J Gerraty <sjg@beast.crufty.net>
|
||||||
|
|
||||||
|
* VERSION (_MAKE_VERSION): 20230510
|
||||||
|
Merge with NetBSD make, pick up
|
||||||
|
o parse.c: don't print null filename in stack traces
|
||||||
|
o var.c: :mtime operate on each word in variable value
|
||||||
|
|
||||||
|
2023-05-09 Simon J Gerraty <sjg@beast.crufty.net>
|
||||||
|
|
||||||
|
* VERSION (_MAKE_VERSION): 20230509
|
||||||
|
Merge with NetBSD make, pick up
|
||||||
|
o for.c: skip syntactically wrong .for loops
|
||||||
|
o var.c: allow for :gmtime=${mtime}
|
||||||
|
add :mtime[=timestamp] where timestamp is used if stat(2)
|
||||||
|
fails, if :mtime=error stat(2) failure causes error.
|
||||||
|
|
||||||
|
2023-05-05 Simon J Gerraty <sjg@beast.crufty.net>
|
||||||
|
|
||||||
|
* VERSION (_MAKE_VERSION): 20230504
|
||||||
|
Merge with NetBSD make, pick up
|
||||||
|
o compat.c: fix compile on NetBSD 7.2
|
||||||
|
o make.1: fix documentation of .PREFIX to match reality and POSIX
|
||||||
|
o unit-tests: improved var-scope-local
|
||||||
|
|
||||||
2023-04-14 Simon J Gerraty <sjg@beast.crufty.net>
|
2023-04-14 Simon J Gerraty <sjg@beast.crufty.net>
|
||||||
|
|
||||||
* VERSION (_MAKE_VERSION): 20230414
|
* VERSION (_MAKE_VERSION): 20230414
|
||||||
|
|
|
@ -392,8 +392,6 @@ unit-tests/export-variants.exp
|
||||||
unit-tests/export-variants.mk
|
unit-tests/export-variants.mk
|
||||||
unit-tests/export.exp
|
unit-tests/export.exp
|
||||||
unit-tests/export.mk
|
unit-tests/export.mk
|
||||||
unit-tests/forloop.exp
|
|
||||||
unit-tests/forloop.mk
|
|
||||||
unit-tests/forsubst.exp
|
unit-tests/forsubst.exp
|
||||||
unit-tests/forsubst.mk
|
unit-tests/forsubst.mk
|
||||||
unit-tests/gnode-submake.exp
|
unit-tests/gnode-submake.exp
|
||||||
|
@ -713,6 +711,8 @@ unit-tests/varmod-match-escape.exp
|
||||||
unit-tests/varmod-match-escape.mk
|
unit-tests/varmod-match-escape.mk
|
||||||
unit-tests/varmod-match.exp
|
unit-tests/varmod-match.exp
|
||||||
unit-tests/varmod-match.mk
|
unit-tests/varmod-match.mk
|
||||||
|
unit-tests/varmod-mtime.exp
|
||||||
|
unit-tests/varmod-mtime.mk
|
||||||
unit-tests/varmod-no-match.exp
|
unit-tests/varmod-no-match.exp
|
||||||
unit-tests/varmod-no-match.mk
|
unit-tests/varmod-no-match.mk
|
||||||
unit-tests/varmod-order-numeric.exp
|
unit-tests/varmod-order-numeric.exp
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
# keep this compatible with sh and make
|
# keep this compatible with sh and make
|
||||||
_MAKE_VERSION=20230414
|
_MAKE_VERSION=20230510
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.\" $NetBSD: make.1,v 1.361 2023/03/23 03:29:28 sjg Exp $
|
.\" $NetBSD: make.1,v 1.366 2023/05/10 18:22:33 sjg Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 1990, 1993
|
.\" Copyright (c) 1990, 1993
|
||||||
.\" The Regents of the University of California. All rights reserved.
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
.\"
|
.\"
|
||||||
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
|
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
|
||||||
.\"
|
.\"
|
||||||
.Dd March 22, 2023
|
.Dd May 10, 2023
|
||||||
.Dt BMAKE 1
|
.Dt BMAKE 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -796,12 +796,10 @@ The list of sources for this target that were deemed out-of-date; also
|
||||||
known as
|
known as
|
||||||
.Sq Va \&? .
|
.Sq Va \&? .
|
||||||
.It Va .PREFIX
|
.It Va .PREFIX
|
||||||
The file prefix of the target, containing only the file portion, no suffix
|
The name of the target with suffix (if declared in
|
||||||
or preceding directory components; also known as
|
.Ic .SUFFIXES )
|
||||||
|
removed; also known as
|
||||||
.Sq Va * .
|
.Sq Va * .
|
||||||
The suffix must be one of the known suffixes declared with
|
|
||||||
.Ic .SUFFIXES ,
|
|
||||||
or it is not recognized.
|
|
||||||
.It Va .TARGET
|
.It Va .TARGET
|
||||||
The name of the target; also known as
|
The name of the target; also known as
|
||||||
.Sq Va @ .
|
.Sq Va @ .
|
||||||
|
@ -1513,6 +1511,25 @@ producing the formatted timestamp.
|
||||||
If a
|
If a
|
||||||
.Ar timestamp
|
.Ar timestamp
|
||||||
value is not provided or is 0, the current time is used.
|
value is not provided or is 0, the current time is used.
|
||||||
|
.It Cm \&:mtime Ns Oo Cm = Ns Ar timestamp Oc
|
||||||
|
Call
|
||||||
|
.Xr stat 2
|
||||||
|
with each word as pathname;
|
||||||
|
use
|
||||||
|
.Ql st_mtime
|
||||||
|
as the new value.
|
||||||
|
If
|
||||||
|
.Xr stat 2
|
||||||
|
fails; use
|
||||||
|
.Ar timestamp
|
||||||
|
or current time.
|
||||||
|
If
|
||||||
|
.Ar timestamp
|
||||||
|
is set to
|
||||||
|
.Ql error ,
|
||||||
|
then
|
||||||
|
.Xr stat 2
|
||||||
|
failure will cause an error.
|
||||||
.It Cm \&:tA
|
.It Cm \&:tA
|
||||||
Attempts to convert the value to an absolute path using
|
Attempts to convert the value to an absolute path using
|
||||||
.Xr realpath 3 .
|
.Xr realpath 3 .
|
||||||
|
@ -2735,5 +2752,3 @@ using that token pool to abort the build and exit with error code 6.
|
||||||
Sometimes the attempt to suppress a cascade of unnecessary errors,
|
Sometimes the attempt to suppress a cascade of unnecessary errors,
|
||||||
can result in a seemingly unexplained
|
can result in a seemingly unexplained
|
||||||
.Ql *** Error code 6
|
.Ql *** Error code 6
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -515,11 +515,8 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
|
||||||
[4m.OODATE[24m The list of sources for this target that were deemed out-
|
[4m.OODATE[24m The list of sources for this target that were deemed out-
|
||||||
of-date; also known as `[4m?[24m'.
|
of-date; also known as `[4m?[24m'.
|
||||||
|
|
||||||
[4m.PREFIX[24m The file prefix of the target, containing only the file
|
[4m.PREFIX[24m The name of the target with suffix (if declared in
|
||||||
portion, no suffix or preceding directory components;
|
[1m.SUFFIXES[22m) removed; also known as `[4m*[24m'.
|
||||||
also known as `[4m*[24m'. The suffix must be one of the known
|
|
||||||
suffixes declared with [1m.SUFFIXES[22m, or it is not recog-
|
|
||||||
nized.
|
|
||||||
|
|
||||||
[4m.TARGET[24m The name of the target; also known as `[4m@[24m'. For compati-
|
[4m.TARGET[24m The name of the target; also known as `[4m@[24m'. For compati-
|
||||||
bility with other makes this is an alias for [4m.ARCHIVE[24m in
|
bility with other makes this is an alias for [4m.ARCHIVE[24m in
|
||||||
|
@ -986,6 +983,12 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
|
||||||
localtime(3), producing the formatted timestamp. If a [4mtimestamp[0m
|
localtime(3), producing the formatted timestamp. If a [4mtimestamp[0m
|
||||||
value is not provided or is 0, the current time is used.
|
value is not provided or is 0, the current time is used.
|
||||||
|
|
||||||
|
[1m:mtime[22m[[1m=[4m[22mtimestamp[24m]
|
||||||
|
Call stat(2) with each word as pathname; use `st_mtime' as the new
|
||||||
|
value. If stat(2) fails; use [4mtimestamp[24m or current time. If
|
||||||
|
[4mtimestamp[24m is set to `error', then stat(2) failure will cause an er-
|
||||||
|
ror.
|
||||||
|
|
||||||
[1m:tA [22mAttempts to convert the value to an absolute path using realpath(3).
|
[1m:tA [22mAttempts to convert the value to an absolute path using realpath(3).
|
||||||
If that fails, the value is unchanged.
|
If that fails, the value is unchanged.
|
||||||
|
|
||||||
|
@ -1750,6 +1753,4 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
|
||||||
attempt to suppress a cascade of unnecessary errors, can result in a
|
attempt to suppress a cascade of unnecessary errors, can result in a
|
||||||
seemingly unexplained `*** Error code 6'
|
seemingly unexplained `*** Error code 6'
|
||||||
|
|
||||||
|
FreeBSD 13.0 May 10, 2023 FreeBSD 13.0
|
||||||
|
|
||||||
FreeBSD 13.0 March 22, 2023 FreeBSD 13.0
|
|
||||||
|
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: compat.c,v 1.246 2023/03/18 22:20:11 sjg Exp $ */
|
/* $NetBSD: compat.c,v 1.247 2023/05/04 22:31:17 sjg Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
|
||||||
|
@ -94,7 +94,7 @@
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
|
|
||||||
/* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */
|
/* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */
|
||||||
MAKE_RCSID("$NetBSD: compat.c,v 1.246 2023/03/18 22:20:11 sjg Exp $");
|
MAKE_RCSID("$NetBSD: compat.c,v 1.247 2023/05/04 22:31:17 sjg Exp $");
|
||||||
|
|
||||||
static GNode *curTarg = NULL;
|
static GNode *curTarg = NULL;
|
||||||
static pid_t compatChild;
|
static pid_t compatChild;
|
||||||
|
@ -224,7 +224,7 @@ bool
|
||||||
Compat_RunCommand(const char *cmdp, GNode *gn, StringListNode *ln)
|
Compat_RunCommand(const char *cmdp, GNode *gn, StringListNode *ln)
|
||||||
{
|
{
|
||||||
char *cmdStart; /* Start of expanded command */
|
char *cmdStart; /* Start of expanded command */
|
||||||
char *bp;
|
char *volatile bp;
|
||||||
bool silent; /* Don't print command */
|
bool silent; /* Don't print command */
|
||||||
bool doIt; /* Execute even if -n */
|
bool doIt; /* Execute even if -n */
|
||||||
volatile bool errCheck; /* Check errors */
|
volatile bool errCheck; /* Check errors */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: for.c,v 1.171 2023/02/14 21:38:31 rillig Exp $ */
|
/* $NetBSD: for.c,v 1.174 2023/05/09 19:43:12 rillig Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1992, The Regents of the University of California.
|
* Copyright (c) 1992, The Regents of the University of California.
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
#include "make.h"
|
#include "make.h"
|
||||||
|
|
||||||
/* "@(#)for.c 8.1 (Berkeley) 6/6/93" */
|
/* "@(#)for.c 8.1 (Berkeley) 6/6/93" */
|
||||||
MAKE_RCSID("$NetBSD: for.c,v 1.171 2023/02/14 21:38:31 rillig Exp $");
|
MAKE_RCSID("$NetBSD: for.c,v 1.174 2023/05/09 19:43:12 rillig Exp $");
|
||||||
|
|
||||||
|
|
||||||
typedef struct ForLoop {
|
typedef struct ForLoop {
|
||||||
|
@ -72,6 +72,22 @@ typedef struct ForLoop {
|
||||||
static ForLoop *accumFor; /* Loop being accumulated */
|
static ForLoop *accumFor; /* Loop being accumulated */
|
||||||
|
|
||||||
|
|
||||||
|
/* See LK_FOR_BODY. */
|
||||||
|
static void
|
||||||
|
skip_whitespace_or_line_continuation(const char **pp)
|
||||||
|
{
|
||||||
|
const char *p = *pp;
|
||||||
|
for (;;) {
|
||||||
|
if (ch_isspace(*p))
|
||||||
|
p++;
|
||||||
|
else if (p[0] == '\\' && p[1] == '\n')
|
||||||
|
p += 2;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*pp = p;
|
||||||
|
}
|
||||||
|
|
||||||
static ForLoop *
|
static ForLoop *
|
||||||
ForLoop_New(void)
|
ForLoop_New(void)
|
||||||
{
|
{
|
||||||
|
@ -123,6 +139,13 @@ ForLoop_Details(ForLoop *f)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
IsValidInVarname(char c)
|
||||||
|
{
|
||||||
|
return c != '$' && c != ':' && c != '\\' &&
|
||||||
|
c != '(' && c != '{' && c != ')' && c != '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
ForLoop_ParseVarnames(ForLoop *f, const char **pp)
|
ForLoop_ParseVarnames(ForLoop *f, const char **pp)
|
||||||
{
|
{
|
||||||
const char *p = *pp;
|
const char *p = *pp;
|
||||||
|
@ -133,15 +156,20 @@ ForLoop_ParseVarnames(ForLoop *f, const char **pp)
|
||||||
cpp_skip_whitespace(&p);
|
cpp_skip_whitespace(&p);
|
||||||
if (*p == '\0') {
|
if (*p == '\0') {
|
||||||
Parse_Error(PARSE_FATAL, "missing `in' in for");
|
Parse_Error(PARSE_FATAL, "missing `in' in for");
|
||||||
return false;
|
f->vars.len = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
for (len = 0; p[len] != '\0' && !ch_isspace(p[len]); len++) {
|
||||||
* XXX: This allows arbitrary variable names;
|
if (!IsValidInVarname(p[len])) {
|
||||||
* see directive-for.mk.
|
Parse_Error(PARSE_FATAL,
|
||||||
*/
|
"invalid character '%c' "
|
||||||
for (len = 1; p[len] != '\0' && !ch_isspace(p[len]); len++)
|
"in .for loop variable name",
|
||||||
continue;
|
p[len]);
|
||||||
|
f->vars.len = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (len == 2 && p[0] == 'i' && p[1] == 'n') {
|
if (len == 2 && p[0] == 'i' && p[1] == 'n') {
|
||||||
p += 2;
|
p += 2;
|
||||||
|
@ -154,11 +182,10 @@ ForLoop_ParseVarnames(ForLoop *f, const char **pp)
|
||||||
|
|
||||||
if (f->vars.len == 0) {
|
if (f->vars.len == 0) {
|
||||||
Parse_Error(PARSE_FATAL, "no iteration variables in for");
|
Parse_Error(PARSE_FATAL, "no iteration variables in for");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pp = p;
|
*pp = p;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -221,17 +248,14 @@ For_Eval(const char *line)
|
||||||
ForLoop *f;
|
ForLoop *f;
|
||||||
|
|
||||||
p = line + 1; /* skip the '.' */
|
p = line + 1; /* skip the '.' */
|
||||||
cpp_skip_whitespace(&p);
|
skip_whitespace_or_line_continuation(&p);
|
||||||
|
|
||||||
if (IsFor(p)) {
|
if (IsFor(p)) {
|
||||||
p += 3;
|
p += 3;
|
||||||
|
|
||||||
f = ForLoop_New();
|
f = ForLoop_New();
|
||||||
if (!ForLoop_ParseVarnames(f, &p)) {
|
ForLoop_ParseVarnames(f, &p);
|
||||||
ForLoop_Free(f);
|
if (f->vars.len > 0 && !ForLoop_ParseItems(f, p))
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!ForLoop_ParseItems(f, p))
|
|
||||||
f->items.len = 0; /* don't iterate */
|
f->items.len = 0; /* don't iterate */
|
||||||
|
|
||||||
accumFor = f;
|
accumFor = f;
|
||||||
|
@ -254,7 +278,7 @@ For_Accum(const char *line, int *forLevel)
|
||||||
|
|
||||||
if (*p == '.') {
|
if (*p == '.') {
|
||||||
p++;
|
p++;
|
||||||
cpp_skip_whitespace(&p);
|
skip_whitespace_or_line_continuation(&p);
|
||||||
|
|
||||||
if (IsEndfor(p)) {
|
if (IsEndfor(p)) {
|
||||||
DEBUG1(FOR, "For: end for %d\n", *forLevel);
|
DEBUG1(FOR, "For: end for %d\n", *forLevel);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.\" $NetBSD: make.1,v 1.361 2023/03/23 03:29:28 sjg Exp $
|
.\" $NetBSD: make.1,v 1.366 2023/05/10 18:22:33 sjg Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 1990, 1993
|
.\" Copyright (c) 1990, 1993
|
||||||
.\" The Regents of the University of California. All rights reserved.
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
.\"
|
.\"
|
||||||
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
|
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
|
||||||
.\"
|
.\"
|
||||||
.Dd March 22, 2023
|
.Dd May 10, 2023
|
||||||
.Dt MAKE 1
|
.Dt MAKE 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -796,12 +796,10 @@ The list of sources for this target that were deemed out-of-date; also
|
||||||
known as
|
known as
|
||||||
.Sq Va \&? .
|
.Sq Va \&? .
|
||||||
.It Va .PREFIX
|
.It Va .PREFIX
|
||||||
The file prefix of the target, containing only the file portion, no suffix
|
The name of the target with suffix (if declared in
|
||||||
or preceding directory components; also known as
|
.Ic .SUFFIXES )
|
||||||
|
removed; also known as
|
||||||
.Sq Va * .
|
.Sq Va * .
|
||||||
The suffix must be one of the known suffixes declared with
|
|
||||||
.Ic .SUFFIXES ,
|
|
||||||
or it is not recognized.
|
|
||||||
.It Va .TARGET
|
.It Va .TARGET
|
||||||
The name of the target; also known as
|
The name of the target; also known as
|
||||||
.Sq Va @ .
|
.Sq Va @ .
|
||||||
|
@ -1524,6 +1522,25 @@ producing the formatted timestamp.
|
||||||
If a
|
If a
|
||||||
.Ar timestamp
|
.Ar timestamp
|
||||||
value is not provided or is 0, the current time is used.
|
value is not provided or is 0, the current time is used.
|
||||||
|
.It Cm \&:mtime Ns Oo Cm = Ns Ar timestamp Oc
|
||||||
|
Call
|
||||||
|
.Xr stat 2
|
||||||
|
with each word as pathname;
|
||||||
|
use
|
||||||
|
.Ql st_mtime
|
||||||
|
as the new value.
|
||||||
|
If
|
||||||
|
.Xr stat 2
|
||||||
|
fails; use
|
||||||
|
.Ar timestamp
|
||||||
|
or current time.
|
||||||
|
If
|
||||||
|
.Ar timestamp
|
||||||
|
is set to
|
||||||
|
.Ql error ,
|
||||||
|
then
|
||||||
|
.Xr stat 2
|
||||||
|
failure will cause an error.
|
||||||
.It Cm \&:tA
|
.It Cm \&:tA
|
||||||
Attempts to convert the value to an absolute path using
|
Attempts to convert the value to an absolute path using
|
||||||
.Xr realpath 3 .
|
.Xr realpath 3 .
|
||||||
|
@ -2742,5 +2759,3 @@ using that token pool to abort the build and exit with error code 6.
|
||||||
Sometimes the attempt to suppress a cascade of unnecessary errors,
|
Sometimes the attempt to suppress a cascade of unnecessary errors,
|
||||||
can result in a seemingly unexplained
|
can result in a seemingly unexplained
|
||||||
.Ql *** Error code 6
|
.Ql *** Error code 6
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,38 @@
|
||||||
|
2023-05-10 Simon J Gerraty <sjg@beast.crufty.net>
|
||||||
|
|
||||||
|
* meta.autodep.mk: if LOCAL_DEPENDS_GUARD is "no"
|
||||||
|
suppress processing of .depend
|
||||||
|
|
||||||
|
2023-05-09 Simon J Gerraty <sjg@beast.crufty.net>
|
||||||
|
|
||||||
|
* dirdeps.mk: do not add _CURDIR to DIRDEPS for SRCTOP
|
||||||
|
|
||||||
|
* meta.sys.mk sys.dirdeps.mk:
|
||||||
|
originally DIRDEPS_BUILD and META_MODE were the same thing,
|
||||||
|
but META_MODE is useful by itself.
|
||||||
|
Move things from meta.sys.mk which actually pertain to
|
||||||
|
DIRDEPS_BUILD to sys.dirdeps.mk
|
||||||
|
|
||||||
|
2023-05-04 Simon J Gerraty <sjg@beast.crufty.net>
|
||||||
|
|
||||||
|
* install-mk (MK_VERSION): 20230504 May the Forth be with you
|
||||||
|
|
||||||
|
* dirdeps.mk: as with meta.sys.mk we treat "host" as special.
|
||||||
|
DEP_TARGET_SPEC is just ${DEP_MACHINE}
|
||||||
|
|
||||||
|
* meta.sys.mk: ensure DEP_* for TARGET_SPEC_VARS are set at
|
||||||
|
level > 0 since these are often refered to in Makefile.depend*
|
||||||
|
|
||||||
|
2023-04-26 Simon J Gerraty <sjg@beast.crufty.net>
|
||||||
|
|
||||||
|
* jobs.mk: report ${.TARGET} ${JOB_ARGS} ${JOB_LOG} and
|
||||||
|
anything in ${JOB_LOG_START}
|
||||||
|
|
||||||
|
* jobs.mk: look for newlog.sh in ${.SYSPATH:U${.PARSEDIR}}
|
||||||
|
or a scripts subdir before searching $PATH.
|
||||||
|
|
||||||
|
* FILES: include newlog.sh for jobs.mk
|
||||||
|
|
||||||
2023-04-20 Simon J Gerraty <sjg@beast.crufty.net>
|
2023-04-20 Simon J Gerraty <sjg@beast.crufty.net>
|
||||||
|
|
||||||
* install-mk (MK_VERSION): 20230420
|
* install-mk (MK_VERSION): 20230420
|
||||||
|
|
|
@ -30,6 +30,7 @@ man.mk
|
||||||
manifest.mk
|
manifest.mk
|
||||||
mk-files.txt
|
mk-files.txt
|
||||||
mkopt.sh
|
mkopt.sh
|
||||||
|
newlog.sh
|
||||||
nls.mk
|
nls.mk
|
||||||
obj.mk
|
obj.mk
|
||||||
options.mk
|
options.mk
|
||||||
|
@ -47,6 +48,7 @@ sys.mk
|
||||||
sys.clean-env.mk
|
sys.clean-env.mk
|
||||||
sys.debug.mk
|
sys.debug.mk
|
||||||
sys.dependfile.mk
|
sys.dependfile.mk
|
||||||
|
sys.dirdeps.mk
|
||||||
sys.vars.mk
|
sys.vars.mk
|
||||||
sys/AIX.mk
|
sys/AIX.mk
|
||||||
sys/Darwin.mk
|
sys/Darwin.mk
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# RCSid:
|
# RCSid:
|
||||||
# $Id: dirdeps-targets.mk,v 1.24 2020/12/11 18:15:43 sjg Exp $
|
# $Id: dirdeps-targets.mk,v 1.25 2023/05/11 05:07:28 sjg Exp $
|
||||||
#
|
#
|
||||||
# @(#) Copyright (c) 2019-2020 Simon J. Gerraty
|
# @(#) Copyright (c) 2019-2020 Simon J. Gerraty
|
||||||
#
|
#
|
||||||
|
@ -113,16 +113,17 @@ tqtdeps := ${DIRDEPS_TARGETS_MACHINE_LIST:@m@${tdeps:M*.$m,*}@:S,/${.MAKE.DEPEND
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
# now work out what we want in DIRDEPS
|
# now work out what we want in DIRDEPS
|
||||||
|
DIRDEPS = ${ptdeps}
|
||||||
.if empty(REQUESTED_MACHINE)
|
.if empty(REQUESTED_MACHINE)
|
||||||
# we want them all just as found
|
# we want them all just as found
|
||||||
DIRDEPS = ${ptdeps} ${mqtdeps} ${tqtdeps}
|
DIRDEPS += ${mqtdeps} ${tqtdeps}
|
||||||
.else
|
.else
|
||||||
# we only want those that match REQUESTED_MACHINE/REQUESTED_TARGET_SPEC
|
# we only want those that match REQUESTED_MACHINE/REQUESTED_TARGET_SPEC
|
||||||
# or REQUESTED_TARGET_SPEC (TARGET_SPEC)
|
# or REQUESTED_TARGET_SPEC (TARGET_SPEC)
|
||||||
DIRDEPS = \
|
DIRDEPS += \
|
||||||
${ptdeps:@d@$d.${REQUESTED_TARGET_SPEC:U${TARGET_SPEC:U${REQUESTED_MACHINE}}}@} \
|
|
||||||
${mqtdeps:M*.${REQUESTED_MACHINE}} \
|
${mqtdeps:M*.${REQUESTED_MACHINE}} \
|
||||||
${tqtdeps:M*.${REQUESTED_TARGET_SPEC:U${TARGET_SPEC}}}
|
${tqtdeps:M*.${REQUESTED_TARGET_SPEC:U${TARGET_SPEC}}} \
|
||||||
|
|
||||||
.endif
|
.endif
|
||||||
# clean up
|
# clean up
|
||||||
DIRDEPS := ${DIRDEPS:O:u}
|
DIRDEPS := ${DIRDEPS:O:u}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# $Id: dirdeps.mk,v 1.157 2023/04/22 21:07:51 sjg Exp $
|
# $Id: dirdeps.mk,v 1.160 2023/05/10 20:44:58 sjg Exp $
|
||||||
|
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
#
|
#
|
||||||
|
@ -273,6 +273,10 @@ _machine_dependfiles := ${.MAKE.DEPENDFILE_PREFERENCE:T:M*${MACHINE}*}
|
||||||
.endif
|
.endif
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
# turn a list into a set of :N modifiers
|
||||||
|
# NskipFoo = ${Foo:${M_ListToSkip}}
|
||||||
|
M_ListToSkip ?= O:u:S,^,N,:ts:
|
||||||
|
|
||||||
# this is how we identify non-machine specific dependfiles
|
# this is how we identify non-machine specific dependfiles
|
||||||
N_notmachine := ${.MAKE.DEPENDFILE_PREFERENCE:E:N*${MACHINE}*:${M_ListToSkip}}
|
N_notmachine := ${.MAKE.DEPENDFILE_PREFERENCE:E:N*${MACHINE}*:${M_ListToSkip}}
|
||||||
|
|
||||||
|
@ -333,6 +337,14 @@ DEP_${TARGET_SPEC_VARS:[$i]} := ${_tspec:[$i]}
|
||||||
DEP_MACHINE := ${_DEP_TARGET_SPEC}
|
DEP_MACHINE := ${_DEP_TARGET_SPEC}
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
# host is special
|
||||||
|
.if ${DEP_MACHINE:Mhost*} != ""
|
||||||
|
DEP_TARGET_SPEC = ${DEP_MACHINE}
|
||||||
|
.for v in ${TARGET_SPEC_VARS:O:u:NMACHINE}
|
||||||
|
.undef DEP_$v
|
||||||
|
.endfor
|
||||||
|
.endif
|
||||||
|
|
||||||
# reset each time through
|
# reset each time through
|
||||||
_build_all_dirs =
|
_build_all_dirs =
|
||||||
_build_xtra_dirs =
|
_build_xtra_dirs =
|
||||||
|
@ -653,7 +665,7 @@ _machines := ${_machines:${M_dep_qual_fixes:ts:}:O:u}
|
||||||
# reset each time through
|
# reset each time through
|
||||||
_build_dirs =
|
_build_dirs =
|
||||||
|
|
||||||
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
|
.if ${DEP_RELDIR} == ${_DEP_RELDIR} && ${_CURDIR} != ${SRCTOP}
|
||||||
# pickup other machines for this dir if necessary
|
# pickup other machines for this dir if necessary
|
||||||
_build_dirs += ${_machines:@m@${_CURDIR}.$m@}
|
_build_dirs += ${_machines:@m@${_CURDIR}.$m@}
|
||||||
.endif
|
.endif
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
# Simon J. Gerraty <sjg@crufty.net>
|
# Simon J. Gerraty <sjg@crufty.net>
|
||||||
|
|
||||||
# RCSid:
|
# RCSid:
|
||||||
# $Id: install-mk,v 1.231 2023/04/20 17:45:03 sjg Exp $
|
# $Id: install-mk,v 1.234 2023/05/13 15:52:24 sjg Exp $
|
||||||
#
|
#
|
||||||
# @(#) Copyright (c) 1994-2023 Simon J. Gerraty
|
# @(#) Copyright (c) 1994-2023 Simon J. Gerraty
|
||||||
#
|
#
|
||||||
|
@ -74,7 +74,7 @@
|
||||||
# sjg@crufty.net
|
# sjg@crufty.net
|
||||||
#
|
#
|
||||||
|
|
||||||
MK_VERSION=20230420
|
MK_VERSION=20230510
|
||||||
OWNER=
|
OWNER=
|
||||||
GROUP=
|
GROUP=
|
||||||
MODE=444
|
MODE=444
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# $Id: jobs.mk,v 1.7 2023/04/18 23:32:28 sjg Exp $
|
# $Id: jobs.mk,v 1.9 2023/04/27 18:10:27 sjg Exp $
|
||||||
#
|
#
|
||||||
# @(#) Copyright (c) 2012-2023, Simon J. Gerraty
|
# @(#) Copyright (c) 2012-2023, Simon J. Gerraty
|
||||||
#
|
#
|
||||||
|
@ -38,21 +38,30 @@ now_utc ?= ${%s:L:gmtime}
|
||||||
start_utc := ${now_utc}
|
start_utc := ${now_utc}
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
.info ${.newline}${TIME_STAMP} Start ${.TARGETS}
|
|
||||||
|
|
||||||
.if make(*-jobs)
|
.if make(*-jobs)
|
||||||
|
.info ${.newline}${TIME_STAMP} Start ${.TARGETS}
|
||||||
|
|
||||||
JOB_LOGDIR ?= ${SRCTOP:H}
|
JOB_LOGDIR ?= ${SRCTOP:H}
|
||||||
JOB_LOG = ${JOB_LOGDIR}/${.TARGET:S,-jobs,,:S,/,_,g}.log
|
JOB_LOG = ${JOB_LOGDIR}/${.TARGET:S,-jobs,,:S,/,_,g}.log
|
||||||
JOB_LOG_GENS ?= 4
|
JOB_LOG_GENS ?= 4
|
||||||
# we like to rotate logs
|
# we like to rotate logs
|
||||||
.if empty(NEWLOG_SH)
|
.if empty(NEWLOG_SH)
|
||||||
|
.for d in ${.SYSPATH:U${.PARSEDIR}:@x@$x $x/scripts@}
|
||||||
|
.if exists($d/newlog.sh)
|
||||||
|
NEWLOG_SH := $d/newlog.sh
|
||||||
|
.if ${MAKE_VERSION} > 20220924
|
||||||
|
.break
|
||||||
|
.endif
|
||||||
|
.endif
|
||||||
|
.endfor
|
||||||
|
.if empty(NEWLOG_SH)
|
||||||
.ifdef M_whence
|
.ifdef M_whence
|
||||||
NEWLOG_SH := ${newlog.sh:L:${M_whence}}
|
NEWLOG_SH := ${newlog.sh:L:${M_whence}}
|
||||||
.else
|
.else
|
||||||
NEWLOG_SH := ${(type newlog.sh) 2> /dev/null:L:sh:M/*}
|
NEWLOG_SH := ${(type newlog.sh) 2> /dev/null:L:sh:M/*}
|
||||||
.endif
|
.endif
|
||||||
.endif
|
.endif
|
||||||
|
.endif
|
||||||
.if !empty(NEWLOG_SH) && exists(${NEWLOG_SH})
|
.if !empty(NEWLOG_SH) && exists(${NEWLOG_SH})
|
||||||
NEWLOG := sh ${NEWLOG_SH}
|
NEWLOG := sh ${NEWLOG_SH}
|
||||||
JOB_NEWLOG_ARGS ?= -S -n ${JOB_LOG_GENS}
|
JOB_NEWLOG_ARGS ?= -S -n ${JOB_LOG_GENS}
|
||||||
|
@ -72,7 +81,7 @@ JOB_ARGS+= -j${JOB_MAX}
|
||||||
# build orchestration works as expected (DIRDEPS_BUILD)
|
# build orchestration works as expected (DIRDEPS_BUILD)
|
||||||
${.TARGETS:M*-jobs}:
|
${.TARGETS:M*-jobs}:
|
||||||
@${NEWLOG} ${JOB_NEWLOG_ARGS} ${JOB_LOG}
|
@${NEWLOG} ${JOB_NEWLOG_ARGS} ${JOB_LOG}
|
||||||
@echo Logging to ${JOB_LOG}
|
@echo "${TIME_STAMP} Start ${.TARGET:S,-jobs,,} ${JOB_ARGS} ${JOB_LOG_START} log=${JOB_LOG}" | tee ${JOB_LOG}
|
||||||
@cd ${.CURDIR} && env MAKELEVEL=0 \
|
@cd ${.CURDIR} && env MAKELEVEL=0 \
|
||||||
${.MAKE} ${JOB_ARGS} _TARGETS=${.TARGET:S,-jobs,,} ${.TARGET:S,-jobs,,} >> ${JOB_LOG} 2>&1
|
${.MAKE} ${JOB_ARGS} _TARGETS=${.TARGET:S,-jobs,,} ${.TARGET:S,-jobs,,} >> ${JOB_LOG} 2>&1
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# $Id: meta.autodep.mk,v 1.56 2022/09/09 17:44:29 sjg Exp $
|
# $Id: meta.autodep.mk,v 1.57 2023/05/13 15:52:24 sjg Exp $
|
||||||
|
|
||||||
#
|
#
|
||||||
# @(#) Copyright (c) 2010, Simon J. Gerraty
|
# @(#) Copyright (c) 2010, Simon J. Gerraty
|
||||||
|
@ -139,6 +139,10 @@ FORCE_DPADD += ${_nonlibs:@x@${DPADD:M*/$x}@}
|
||||||
.END: gendirdeps
|
.END: gendirdeps
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
.if ${LOCAL_DEPENDS_GUARD:U} == "no"
|
||||||
|
.depend:
|
||||||
|
.endif
|
||||||
|
|
||||||
# if we don't have OBJS, then .depend isn't useful
|
# if we don't have OBJS, then .depend isn't useful
|
||||||
.if !target(.depend) && (!empty(OBJS) || ${.ALLTARGETS:M*.o} != "")
|
.if !target(.depend) && (!empty(OBJS) || ${.ALLTARGETS:M*.o} != "")
|
||||||
# some makefiles and/or targets contain
|
# some makefiles and/or targets contain
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# $Id: meta.sys.mk,v 1.46 2023/04/18 18:43:00 sjg Exp $
|
# $Id: meta.sys.mk,v 1.51 2023/05/11 20:05:32 sjg Exp $
|
||||||
|
|
||||||
#
|
#
|
||||||
# @(#) Copyright (c) 2010-2021, Simon J. Gerraty
|
# @(#) Copyright (c) 2010-2023, Simon J. Gerraty
|
||||||
#
|
#
|
||||||
# This file is provided in the hope that it will
|
# This file is provided in the hope that it will
|
||||||
# be of use. There is absolutely NO WARRANTY.
|
# be of use. There is absolutely NO WARRANTY.
|
||||||
|
@ -17,56 +17,21 @@
|
||||||
# include this if you want to enable meta mode
|
# include this if you want to enable meta mode
|
||||||
# for maximum benefit, requires filemon(4) driver.
|
# for maximum benefit, requires filemon(4) driver.
|
||||||
|
|
||||||
.if ${MAKE_VERSION:U0} > 20100901
|
# absolute path to what we are reading.
|
||||||
.if !target(.ERROR)
|
_PARSEDIR ?= ${.PARSEDIR:tA}
|
||||||
|
|
||||||
.-include <local.meta.sys.env.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}
|
|
||||||
|
|
||||||
.if !defined(SYS_MK_DIR)
|
.if !defined(SYS_MK_DIR)
|
||||||
SYS_MK_DIR := ${_PARSEDIR}
|
SYS_MK_DIR := ${_PARSEDIR}
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
META_MODE += meta verbose
|
.if !target(.ERROR)
|
||||||
|
|
||||||
|
META_MODE += meta
|
||||||
|
.if empty(.MAKEFLAGS:M-s)
|
||||||
|
META_MODE += verbose
|
||||||
|
.endif
|
||||||
.if ${MAKE_VERSION:U0} > 20130323 && empty(.MAKE.PATH_FILEMON)
|
.if ${MAKE_VERSION:U0} > 20130323 && empty(.MAKE.PATH_FILEMON)
|
||||||
# we do not support filemon
|
# we do not support filemon
|
||||||
META_MODE += nofilemon
|
META_MODE += nofilemon
|
||||||
|
@ -102,19 +67,7 @@ META_MODE += silent=yes
|
||||||
.endif
|
.endif
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
# we use the pseudo machine "host" for the build host.
|
.if ${MK_DIRDEPS_BUILD:Uno} == "yes"
|
||||||
# this should be taken care of before we get here
|
|
||||||
.if ${OBJTOP:Ua} == ${HOST_OBJTOP:Ub}
|
|
||||||
MACHINE = host
|
|
||||||
.endif
|
|
||||||
|
|
||||||
.if !defined(MACHINE0)
|
|
||||||
# it can be handy to know which MACHINE kicked off the build
|
|
||||||
# for example, if using Makefild.depend for multiple machines,
|
|
||||||
# allowing only MACHINE0 to update can keep things simple.
|
|
||||||
MACHINE0 := ${MACHINE}
|
|
||||||
.export MACHINE0
|
|
||||||
.endif
|
|
||||||
|
|
||||||
.if !defined(META2DEPS)
|
.if !defined(META2DEPS)
|
||||||
.if defined(PYTHON) && exists(${PYTHON})
|
.if defined(PYTHON) && exists(${PYTHON})
|
||||||
|
@ -134,6 +87,11 @@ MAKE_PRINT_VAR_ON_ERROR += \
|
||||||
MAKEFILE \
|
MAKEFILE \
|
||||||
.MAKE.MODE
|
.MAKE.MODE
|
||||||
|
|
||||||
|
MK_META_ERROR_TARGET = yes
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.if ${MK_META_ERROR_TARGET:Uno} == "yes"
|
||||||
|
|
||||||
.if !defined(SB) && defined(SRCTOP)
|
.if !defined(SB) && defined(SRCTOP)
|
||||||
SB = ${SRCTOP:H}
|
SB = ${SRCTOP:H}
|
||||||
.endif
|
.endif
|
||||||
|
@ -150,21 +108,12 @@ _metaError: .NOMETA .NOTMAIN
|
||||||
echo "ERROR: log ${meta_error_log}" >&2; }; :
|
echo "ERROR: log ${meta_error_log}" >&2; }; :
|
||||||
|
|
||||||
.endif
|
.endif
|
||||||
|
.endif
|
||||||
|
|
||||||
# Are we, after all, in meta mode?
|
# Are we, after all, in meta mode?
|
||||||
.if ${.MAKE.MODE:Uno:Mmeta*} != ""
|
.if ${.MAKE.MODE:Uno:Mmeta*} != ""
|
||||||
MKDEP_MK ?= meta.autodep.mk
|
MKDEP_MK ?= meta.autodep.mk
|
||||||
|
|
||||||
.if ${.MAKE.MAKEFILES:M*sys.dependfile.mk} == ""
|
|
||||||
# this does all the smarts of setting .MAKE.DEPENDFILE
|
|
||||||
.-include <sys.dependfile.mk>
|
|
||||||
# check if we got anything sane
|
|
||||||
.if ${.MAKE.DEPENDFILE} == ".depend"
|
|
||||||
.undef .MAKE.DEPENDFILE
|
|
||||||
.endif
|
|
||||||
.MAKE.DEPENDFILE ?= Makefile.depend
|
|
||||||
.endif
|
|
||||||
|
|
||||||
# we can afford to use cookies to prevent some targets
|
# we can afford to use cookies to prevent some targets
|
||||||
# re-running needlessly
|
# re-running needlessly
|
||||||
META_COOKIE_TOUCH?= touch ${COOKIE.${.TARGET}:U${.OBJDIR}/${.TARGET:T}}
|
META_COOKIE_TOUCH?= touch ${COOKIE.${.TARGET}:U${.OBJDIR}/${.TARGET:T}}
|
||||||
|
@ -192,27 +141,13 @@ UPDATE_DEPENDFILE= NO
|
||||||
.endif
|
.endif
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
.if ${.MAKE.LEVEL} == 0
|
.else # in meta mode?
|
||||||
.if ${MK_DIRDEPS_BUILD:Uyes} == "yes"
|
|
||||||
# make sure dirdeps target exists and do it first
|
|
||||||
all: dirdeps .WAIT
|
|
||||||
dirdeps:
|
|
||||||
.NOPATH: dirdeps
|
|
||||||
|
|
||||||
.if defined(ALL_MACHINES)
|
|
||||||
# the first .MAIN: is what counts
|
|
||||||
# by default dirdeps is all we want at level0
|
|
||||||
.MAIN: dirdeps
|
|
||||||
.endif
|
|
||||||
.endif
|
|
||||||
|
|
||||||
.endif
|
|
||||||
.else
|
|
||||||
META_COOKIE_TOUCH=
|
META_COOKIE_TOUCH=
|
||||||
# some targets need to be .PHONY in non-meta mode
|
# some targets need to be .PHONY in non-meta mode
|
||||||
META_NOPHONY= .PHONY
|
META_NOPHONY= .PHONY
|
||||||
META_NOECHO= echo
|
META_NOECHO= echo
|
||||||
.endif
|
|
||||||
.endif
|
.endif # in meta mode?
|
||||||
|
|
||||||
.-include <local.meta.sys.mk>
|
.-include <local.meta.sys.mk>
|
||||||
|
|
|
@ -441,6 +441,8 @@ Leverages ``bmake`` to compute optimal link order for libraries.
|
||||||
This works nicely and makes refactoring a breeze - so long as you
|
This works nicely and makes refactoring a breeze - so long as you
|
||||||
have no (or few) cicular dependencies between libraries.
|
have no (or few) cicular dependencies between libraries.
|
||||||
|
|
||||||
|
Consider this experimental.
|
||||||
|
|
||||||
man.mk
|
man.mk
|
||||||
------
|
------
|
||||||
|
|
||||||
|
@ -509,17 +511,58 @@ then ``jobs.mk`` will run::
|
||||||
this ensures you get a build log and JOB_MAX is assumed to be set
|
this ensures you get a build log and JOB_MAX is assumed to be set
|
||||||
optimally for the host.
|
optimally for the host.
|
||||||
|
|
||||||
Meta mode
|
META_MODE
|
||||||
=========
|
=========
|
||||||
|
|
||||||
The 20110505 and later versions of ``mk-files`` include a number of
|
The 20110505 and later versions of ``mk-files`` include a number of
|
||||||
makefiles contributed by Juniper Networks, Inc.
|
makefiles contributed by Juniper Networks, Inc.
|
||||||
These allow the latest version of bmake_ to run in `meta mode`_
|
These allow the latest version of bmake_ to run in `meta mode`_
|
||||||
see `dirdeps.mk`_
|
see `dirdeps.mk`_ and DIRDEPS_BUILD_ below.
|
||||||
|
|
||||||
.. _`dirdeps.mk`: /help/sjg/dirdeps.htm
|
.. _`dirdeps.mk`: /help/sjg/dirdeps.htm
|
||||||
.. _`meta mode`: bmake-meta-mode.htm
|
.. _`meta mode`: bmake-meta-mode.htm
|
||||||
|
|
||||||
|
DIRDEPS_BUILD
|
||||||
|
=============
|
||||||
|
|
||||||
|
When the `meta mode`_ was originally done, there was no distinction
|
||||||
|
between META_MODE_ and ``DIRDEPS_BUILD``, but as these were integrated
|
||||||
|
into FreeBSD it became clear that META_MODE_ could be useful to many
|
||||||
|
developers independently of ``DIRDEPS_BUILD``.
|
||||||
|
|
||||||
|
Thus today we distinguish between the two.
|
||||||
|
We have the following makefiles which are relevant to
|
||||||
|
``DIRDEPS_BUILD`` or META_MODE_::
|
||||||
|
|
||||||
|
share/mk/auto.obj.mk
|
||||||
|
share/mk/dirdeps-cache-update.mk
|
||||||
|
share/mk/dirdeps-only.mk
|
||||||
|
share/mk/dirdeps-options.mk
|
||||||
|
share/mk/dirdeps-targets.mk
|
||||||
|
share/mk/dirdeps.mk
|
||||||
|
share/mk/gendirdeps.mk
|
||||||
|
share/mk/host-target.mk
|
||||||
|
share/mk/install-new.mk
|
||||||
|
share/mk/meta.autodep.mk
|
||||||
|
share/mk/meta.stage.mk
|
||||||
|
share/mk/meta.sys.mk
|
||||||
|
share/mk/meta2deps.py
|
||||||
|
share/mk/meta2deps.sh
|
||||||
|
share/mk/sys.dependfile.mk
|
||||||
|
share/mk/sys.dirdeps.mk
|
||||||
|
|
||||||
|
and the following are typically used for customization.
|
||||||
|
See `freebsd-meta-mode`_ and `netbsd-meta-mode`_::
|
||||||
|
|
||||||
|
share/mk/local.dirdeps-build.mk
|
||||||
|
share/mk/local.dirdeps-missing.mk
|
||||||
|
share/mk/local.dirdeps.mk
|
||||||
|
share/mk/local.meta.sys.mk
|
||||||
|
share/mk/local.sys.dirdeps.env.mk
|
||||||
|
share/mk/local.sys.dirdeps.mk
|
||||||
|
share/mk/local.sys.mk
|
||||||
|
|
||||||
|
|
||||||
Install
|
Install
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
@ -538,9 +581,11 @@ where you unpacked the tar file, you can::
|
||||||
|
|
||||||
.. _bmake: bmake.htm
|
.. _bmake: bmake.htm
|
||||||
.. _NetBSD: http://www.netbsd.org/
|
.. _NetBSD: http://www.netbsd.org/
|
||||||
.. _mkdeps.sh: http://www.crufty.net/ftp/pub/sjg/mkdeps.sh
|
.. _mkdeps.sh: https://www.crufty.net/ftp/pub/sjg/mkdeps.sh
|
||||||
.. _mk.tar.gz: http://www.crufty.net/ftp/pub/sjg/mk.tar.gz
|
.. _mk.tar.gz: https://www.crufty.net/ftp/pub/sjg/mk.tar.gz
|
||||||
|
.. _`freebsd-meta-mode`: https://www.crufty.net/sjg/docs/freebsd-meta-mode.htm
|
||||||
|
.. _`netbsd-meta-mode`: https://www.crufty.net/sjg/docs/netbsd-meta-mode.htm
|
||||||
|
|
||||||
:Author: sjg@crufty.net
|
:Author: sjg@crufty.net
|
||||||
:Revision: $Id: mk-files.txt,v 1.22 2023/04/16 23:43:33 sjg Exp $
|
:Revision: $Id: mk-files.txt,v 1.23 2023/05/11 22:55:08 sjg Exp $
|
||||||
:Copyright: Crufty.NET
|
:Copyright: Crufty.NET
|
||||||
|
|
412
contrib/bmake/mk/newlog.sh
Executable file
412
contrib/bmake/mk/newlog.sh
Executable file
|
@ -0,0 +1,412 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# NAME:
|
||||||
|
# newlog - rotate log files
|
||||||
|
#
|
||||||
|
# SYNOPSIS:
|
||||||
|
# newlog.sh [options] "log"[:"num"] ...
|
||||||
|
#
|
||||||
|
# DESCRIPTION:
|
||||||
|
# This script saves multiple generations of each "log".
|
||||||
|
# The "logs" are kept compressed except for the current and
|
||||||
|
# previous ones.
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
#
|
||||||
|
# -C "compress"
|
||||||
|
# Compact old logs (other than .0) with "compress"
|
||||||
|
# (default is 'gzip' or 'compress' if no 'gzip').
|
||||||
|
#
|
||||||
|
# -E "ext"
|
||||||
|
# If "compress" produces a file extention other than
|
||||||
|
# '.Z' or '.gz' we need to know.
|
||||||
|
#
|
||||||
|
# -G "gens"
|
||||||
|
# "gens" is a comma separated list of "log":"num" pairs
|
||||||
|
# that allows certain logs to handled differently.
|
||||||
|
#
|
||||||
|
# -N Don't actually do anything, just show us.
|
||||||
|
#
|
||||||
|
# -R Rotate rather than save logs by default.
|
||||||
|
# This is the default anyway.
|
||||||
|
#
|
||||||
|
# -S Save rather than rotate logs by default.
|
||||||
|
# Each log is saved to a unique name that remains
|
||||||
|
# unchanged. This results in far less churn.
|
||||||
|
#
|
||||||
|
# -f "fmt"
|
||||||
|
# Format ('%Y%m%d.%H%M%S') for suffix added to "log" to
|
||||||
|
# uniquely name it when using the '-S' option.
|
||||||
|
# If a "log" is saved more than once per second we add
|
||||||
|
# an extra suffix of our process-id.
|
||||||
|
#
|
||||||
|
# -d The "log" to be rotated/saved is a directory.
|
||||||
|
# We leave the mode of old directories alone.
|
||||||
|
#
|
||||||
|
# -e Normally logs are only cycled if non-empty, this
|
||||||
|
# option forces empty logs to be cycled as well.
|
||||||
|
#
|
||||||
|
# -g "group"
|
||||||
|
# Set the group of "log" to "group".
|
||||||
|
#
|
||||||
|
# -m "mode"
|
||||||
|
# Set the mode of "log".
|
||||||
|
#
|
||||||
|
# -M "mode"
|
||||||
|
# Set the mode of old logs (default 444).
|
||||||
|
#
|
||||||
|
# -n "num"
|
||||||
|
# Keep "num" generations of "log".
|
||||||
|
#
|
||||||
|
# -o "owner"
|
||||||
|
# Set the owner of "log".
|
||||||
|
#
|
||||||
|
# Regardless of whether '-R' or '-S' is provided, we attempt to
|
||||||
|
# choose the correct behavior based on observation of "log.0" if
|
||||||
|
# it exists; if it is a symbolic link, we save, otherwise
|
||||||
|
# we rotate.
|
||||||
|
#
|
||||||
|
# BUGS:
|
||||||
|
# 'Newlog.sh' tries to avoid being fooled by symbolic links, but
|
||||||
|
# multiply indirect symlinks are only handled on machines where
|
||||||
|
# test(1) supports a check for symlinks.
|
||||||
|
#
|
||||||
|
# AUTHOR:
|
||||||
|
# Simon J. Gerraty <sjg@crufty.net>
|
||||||
|
#
|
||||||
|
|
||||||
|
# RCSid:
|
||||||
|
# $Id: newlog.sh,v 1.26 2021/04/30 16:29:02 sjg Exp $
|
||||||
|
#
|
||||||
|
# @(#) Copyright (c) 1993-2016 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
|
||||||
|
#
|
||||||
|
|
||||||
|
Mydir=`dirname $0`
|
||||||
|
case $Mydir in
|
||||||
|
/*) ;;
|
||||||
|
*) Mydir=`cd $Mydir; pwd`;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# places to find chown (and setopts.sh)
|
||||||
|
PATH=$PATH:/usr/etc:/sbin:/usr/sbin:/usr/local/share/bin:/share/bin:$Mydir
|
||||||
|
|
||||||
|
# linux doesn't necessarily have compress,
|
||||||
|
# and gzip appears in various locations...
|
||||||
|
Which() {
|
||||||
|
case "$1" in
|
||||||
|
-*) t=$1; shift;;
|
||||||
|
*) t=-x;;
|
||||||
|
esac
|
||||||
|
case "$1" in
|
||||||
|
/*) test $t $1 && echo $1;;
|
||||||
|
*)
|
||||||
|
for d in `IFS=:; echo ${2:-$PATH}`
|
||||||
|
do
|
||||||
|
test $t $d/$1 && { echo $d/$1; break; }
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# shell's typically have test(1) as built-in
|
||||||
|
# and not all support all options.
|
||||||
|
test_opt() {
|
||||||
|
_o=$1
|
||||||
|
_a=$2
|
||||||
|
_t=${3:-/}
|
||||||
|
|
||||||
|
case `test -$_o $_t 2>&1` in
|
||||||
|
*:*) eval test_$_o=$_a;;
|
||||||
|
*) eval test_$_o=-$_o;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# convert find/ls mode to octal
|
||||||
|
fmode() {
|
||||||
|
eval `echo $1 |
|
||||||
|
sed 's,\(.\)\(...\)\(...\)\(...\),ft=\1 um=\2 gm=\3 om=\4,'`
|
||||||
|
sm=
|
||||||
|
case "$um" in
|
||||||
|
*s*) sm=r
|
||||||
|
um=`echo $um | sed 's,s,x,'`
|
||||||
|
;;
|
||||||
|
*) sm=-;;
|
||||||
|
esac
|
||||||
|
case "$gm" in
|
||||||
|
*[Ss]*)
|
||||||
|
sm=${sm}w
|
||||||
|
gm=`echo $gm | sed 's,s,x,;s,S,-,'`
|
||||||
|
;;
|
||||||
|
*) sm=${sm}-;;
|
||||||
|
esac
|
||||||
|
case "$om" in
|
||||||
|
*t)
|
||||||
|
sm=${sm}x
|
||||||
|
om=`echo $om | sed 's,t,x,'`
|
||||||
|
;;
|
||||||
|
*) sm=${sm}-;;
|
||||||
|
esac
|
||||||
|
echo $sm $um $gm $om |
|
||||||
|
sed 's,rwx,7,g;s,rw-,6,g;s,r-x,5,g;s,r--,4,g;s,-wx,3,g;s,-w-,2,g;s,--x,1,g;s,---,0,g;s, ,,g'
|
||||||
|
}
|
||||||
|
|
||||||
|
get_mode() {
|
||||||
|
case "$OS,$STAT" in
|
||||||
|
FreeBSD,*)
|
||||||
|
$STAT -f %Op $1 | sed 's,.*\(....\),\1,'
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
# fallback to find
|
||||||
|
fmode `find $1 -ls -prune | awk '{ print $3 }'`
|
||||||
|
}
|
||||||
|
|
||||||
|
get_mtime_suffix() {
|
||||||
|
case "$OS,$STAT" in
|
||||||
|
FreeBSD,*)
|
||||||
|
$STAT -t "${2:-$opt_f}" -f %Sm $1
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
# this will have to do
|
||||||
|
date "+${2:-$opt_f}"
|
||||||
|
}
|
||||||
|
|
||||||
|
case /$0 in
|
||||||
|
*/newlog*) rotate_func=rotate_log;;
|
||||||
|
*/save*) rotate_func=save_log;;
|
||||||
|
*) rotate_func=rotate_log;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
opt_n=7
|
||||||
|
opt_m=
|
||||||
|
opt_M=444
|
||||||
|
opt_f=%Y%m%d.%H%M%S
|
||||||
|
opt_str=dNn:o:g:G:C:M:m:eE:f:RS
|
||||||
|
|
||||||
|
. setopts.sh
|
||||||
|
|
||||||
|
test $# -gt 0 || exit 0 # nothing to do.
|
||||||
|
|
||||||
|
OS=${OS:-`uname`}
|
||||||
|
STAT=${STAT:-`Which stat`}
|
||||||
|
|
||||||
|
# sorry, setops semantics for booleans changed.
|
||||||
|
case "${opt_d:-0}" in
|
||||||
|
0) rm_f=-f
|
||||||
|
opt_d=-f
|
||||||
|
for x in $opt_C gzip compress
|
||||||
|
do
|
||||||
|
opt_C=`Which $x "/bin:/usr/bin:$PATH"`
|
||||||
|
test -x $opt_C && break
|
||||||
|
done
|
||||||
|
empty() { test ! -s $1; }
|
||||||
|
;;
|
||||||
|
*) rm_f=-rf
|
||||||
|
opt_d=-d
|
||||||
|
opt_M=
|
||||||
|
opt_C=:
|
||||||
|
empty() {
|
||||||
|
if [ -d $1 ]; then
|
||||||
|
n=`'ls' -a1 $1/. | wc -l`
|
||||||
|
[ $n -gt 2 ] && return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
case "${opt_N:-0}" in
|
||||||
|
0) ECHO=;;
|
||||||
|
*) ECHO=echo;;
|
||||||
|
esac
|
||||||
|
case "${opt_e:-0}" in
|
||||||
|
0) force=;;
|
||||||
|
*) force=yes;;
|
||||||
|
esac
|
||||||
|
case "${opt_R:-0}" in
|
||||||
|
0) ;;
|
||||||
|
*) rotate_func=rotate_log;;
|
||||||
|
esac
|
||||||
|
case "${opt_S:-0}" in
|
||||||
|
0) ;;
|
||||||
|
*) rotate_func=save_log opt_S=;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# see whether test handles -h or -L
|
||||||
|
test_opt L -h
|
||||||
|
test_opt h ""
|
||||||
|
case "$test_L,$test_h" in
|
||||||
|
-h,) test_L= ;; # we don't support either!
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$test_L" in
|
||||||
|
"") # No, so this is about all we can do...
|
||||||
|
logs=`'ls' -ld $* | awk '{ print $NF }'`
|
||||||
|
;;
|
||||||
|
*) # it does
|
||||||
|
logs="$*"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
read_link() {
|
||||||
|
case "$test_L" in
|
||||||
|
"") 'ls' -ld $1 | awk '{ print $NF }'; return;;
|
||||||
|
esac
|
||||||
|
if test $test_L $1; then
|
||||||
|
'ls' -ld $1 | sed 's,.*> ,,'
|
||||||
|
else
|
||||||
|
echo $1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# create the new log
|
||||||
|
new_log() {
|
||||||
|
log=$1
|
||||||
|
mode=$2
|
||||||
|
if test "x$opt_M" != x; then
|
||||||
|
$ECHO chmod $opt_M $log.0 2> /dev/null
|
||||||
|
fi
|
||||||
|
# someone may have managed to write to it already
|
||||||
|
# so don't truncate it.
|
||||||
|
case "$opt_d" in
|
||||||
|
-d) $ECHO mkdir -p $log;;
|
||||||
|
*) $ECHO touch $log;;
|
||||||
|
esac
|
||||||
|
# the order here matters
|
||||||
|
test "x$opt_o" = x || $ECHO chown $opt_o $log
|
||||||
|
test "x$opt_g" = x || $ECHO chgrp $opt_g $log
|
||||||
|
test "x$mode" = x || $ECHO chmod $mode $log
|
||||||
|
}
|
||||||
|
|
||||||
|
rotate_log() {
|
||||||
|
log=$1
|
||||||
|
n=${2:-$opt_n}
|
||||||
|
|
||||||
|
# make sure excess generations are trimmed
|
||||||
|
$ECHO rm $rm_f `echo $log.$n | sed 's/\([0-9]\)$/[\1-9]*/'`
|
||||||
|
|
||||||
|
mode=${opt_m:-`get_mode $log`}
|
||||||
|
while test $n -gt 0
|
||||||
|
do
|
||||||
|
p=`expr $n - 1`
|
||||||
|
if test -s $log.$p; then
|
||||||
|
$ECHO rm $rm_f $log.$p.*
|
||||||
|
$ECHO $opt_C $log.$p
|
||||||
|
if test "x$opt_M" != x; then
|
||||||
|
$ECHO chmod $opt_M $log.$p.* 2> /dev/null
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
for ext in $opt_E .gz .Z ""
|
||||||
|
do
|
||||||
|
test $opt_d $log.$p$ext || continue
|
||||||
|
$ECHO mv $log.$p$ext $log.$n$ext
|
||||||
|
done
|
||||||
|
n=$p
|
||||||
|
done
|
||||||
|
# leave $log.0 uncompressed incase some one still has it open.
|
||||||
|
$ECHO mv $log $log.0
|
||||||
|
new_log $log $mode
|
||||||
|
}
|
||||||
|
|
||||||
|
# unlike rotate_log we do not rotate files,
|
||||||
|
# but give each log a unique (but stable name).
|
||||||
|
# This avoids churn for folk who rsync things.
|
||||||
|
# We make log.0 a symlink to the most recent log
|
||||||
|
# so it can be found and compressed next time around.
|
||||||
|
save_log() {
|
||||||
|
log=$1
|
||||||
|
n=${2:-$opt_n}
|
||||||
|
fmt=$3
|
||||||
|
|
||||||
|
last=`read_link $log.0`
|
||||||
|
case "$last" in
|
||||||
|
$log.0) # should never happen
|
||||||
|
test -s $last && $ECHO mv $last $log.$$;;
|
||||||
|
$log.*)
|
||||||
|
$ECHO $opt_C $last
|
||||||
|
;;
|
||||||
|
*.*) $ECHO $opt_C `dirname $log`/$last
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
$ECHO rm -f $log.0
|
||||||
|
# remove excess logs - we rely on mtime!
|
||||||
|
$ECHO rm $rm_f `'ls' -1td $log.* 2> /dev/null | sed "1,${n}d"`
|
||||||
|
|
||||||
|
mode=${opt_m:-`get_mode $log`}
|
||||||
|
# this is our default suffix
|
||||||
|
opt_S=${opt_S:-`get_mtime_suffix $log $fmt`}
|
||||||
|
case "$fmt" in
|
||||||
|
""|$opt_f) suffix=$opt_S;;
|
||||||
|
*) suffix=`get_mtime_suffix $log $fmt`;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# find a unique name to save current log as
|
||||||
|
for nlog in $log.$suffix $log.$suffix.$$
|
||||||
|
do
|
||||||
|
for f in $nlog*
|
||||||
|
do
|
||||||
|
break
|
||||||
|
done
|
||||||
|
test $opt_d $f || break
|
||||||
|
done
|
||||||
|
# leave $log.0 uncompressed incase some one still has it open.
|
||||||
|
$ECHO mv $log $nlog
|
||||||
|
test "x$opt_M" = x || $ECHO chmod $opt_M $nlog 2> /dev/null
|
||||||
|
$ECHO ln -s `basename $nlog` $log.0
|
||||||
|
new_log $log $mode
|
||||||
|
}
|
||||||
|
|
||||||
|
for f in $logs
|
||||||
|
do
|
||||||
|
n=$opt_n
|
||||||
|
save=
|
||||||
|
case "$f" in
|
||||||
|
*:[1-9]*)
|
||||||
|
set -- `IFS=:; echo $f`; f=$1; n=$2;;
|
||||||
|
*:n=*|*:save=*)
|
||||||
|
eval `echo "f=$f" | tr ':' ' '`;;
|
||||||
|
esac
|
||||||
|
# try and pick the right function to use
|
||||||
|
rfunc=$rotate_func # default
|
||||||
|
if test $opt_d $f.0; then
|
||||||
|
case `read_link $f.0` in
|
||||||
|
$f.0) rfunc=rotate_log;;
|
||||||
|
*) rfunc=save_log;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
case "$test_L" in
|
||||||
|
-?)
|
||||||
|
while test $test_L $f # it is [still] a symlink
|
||||||
|
do
|
||||||
|
f=`read_link $f`
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
case ",${opt_G}," in
|
||||||
|
*,${f}:n=*|,${f}:save=*)
|
||||||
|
eval `echo ",${opt_G}," | sed "s!.*,${f}:\([^,]*\),.*!\1!;s,:, ,g"`
|
||||||
|
;;
|
||||||
|
*,${f}:*)
|
||||||
|
# opt_G is a , separated list of log:n pairs
|
||||||
|
n=`echo ,$opt_G, | sed -e "s,.*${f}:\([0-9][0-9]*\).*,\1,"`
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if empty $f; then
|
||||||
|
test "$force" || continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
test "$save" && rfunc=save_log
|
||||||
|
|
||||||
|
$rfunc $f $n $save
|
||||||
|
done
|
|
@ -1,6 +1,6 @@
|
||||||
# $Id: sys.dependfile.mk,v 1.9 2020/08/19 17:51:53 sjg Exp $
|
# $Id: sys.dependfile.mk,v 1.10 2023/05/10 19:23:26 sjg Exp $
|
||||||
#
|
#
|
||||||
# @(#) Copyright (c) 2012, Simon J. Gerraty
|
# @(#) Copyright (c) 2012-2023, Simon J. Gerraty
|
||||||
#
|
#
|
||||||
# This file is provided in the hope that it will
|
# This file is provided in the hope that it will
|
||||||
# be of use. There is absolutely NO WARRANTY.
|
# be of use. There is absolutely NO WARRANTY.
|
||||||
|
@ -13,7 +13,10 @@
|
||||||
# sjg@crufty.net
|
# sjg@crufty.net
|
||||||
#
|
#
|
||||||
|
|
||||||
# This only makes sense in meta mode.
|
.if !target(__${.PARSEFILE}__)
|
||||||
|
__${.PARSEFILE}__: .NOTMAIN
|
||||||
|
|
||||||
|
# This only makes sense for DIRDEPS_BUILD.
|
||||||
# This allows a mixture of auto generated as well as manually edited
|
# This allows a mixture of auto generated as well as manually edited
|
||||||
# dependency files, which can be differentiated by their names.
|
# dependency files, which can be differentiated by their names.
|
||||||
# As per dirdeps.mk we only require:
|
# As per dirdeps.mk we only require:
|
||||||
|
@ -57,3 +60,5 @@ MACHINE := ${_m}
|
||||||
.endif
|
.endif
|
||||||
.endif
|
.endif
|
||||||
.MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_DEFAULT}
|
.MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_DEFAULT}
|
||||||
|
|
||||||
|
.endif
|
||||||
|
|
183
contrib/bmake/mk/sys.dirdeps.mk
Normal file
183
contrib/bmake/mk/sys.dirdeps.mk
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
# $Id: sys.dirdeps.mk,v 1.9 2023/05/11 20:05:42 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
|
||||||
|
#
|
||||||
|
|
||||||
|
# Originally DIRDEPS_BUILD and META_MODE were the same thing.
|
||||||
|
# So, much of this was done in *meta.sys.mk and local*mk
|
||||||
|
# but properly belongs here.
|
||||||
|
|
||||||
|
# Include from [local.]sys.mk - if doing DIRDEPS_BUILD
|
||||||
|
# we should not be here otherwise
|
||||||
|
MK_DIRDEPS_BUILD ?= yes
|
||||||
|
# these are all implied
|
||||||
|
MK_AUTO_OBJ ?= yes
|
||||||
|
MK_META_MODE ?= yes
|
||||||
|
MK_STAGING ?= yes
|
||||||
|
|
||||||
|
_PARSEDIR ?= ${.PARSEDIR:tA}
|
||||||
|
|
||||||
|
.-include <local.sys.dirdeps.env.mk>
|
||||||
|
|
||||||
|
.if ${.MAKE.LEVEL} == 0
|
||||||
|
# make sure dirdeps target exists and do it first
|
||||||
|
dirdeps:
|
||||||
|
# first .MAIN is what counts
|
||||||
|
.MAIN: dirdeps
|
||||||
|
.NOPATH: dirdeps
|
||||||
|
all: dirdeps .WAIT
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.if empty(SRCTOP)
|
||||||
|
# fallback assumes share/mk!
|
||||||
|
SRCTOP := ${SB_SRC:U${.PARSEDIR:tA:H:H}}
|
||||||
|
.export SRCTOP
|
||||||
|
.endif
|
||||||
|
|
||||||
|
# fake SB if not using mk wrapper
|
||||||
|
.if !defined(SB)
|
||||||
|
SB := ${SRCTOP:H}
|
||||||
|
.export SB
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.if empty(OBJROOT)
|
||||||
|
OBJROOT := ${SB_OBJROOT:U${MAKEOBJDIRPREFIX:U${SB}/obj}/}
|
||||||
|
.export OBJROOT
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.if empty(STAGE_ROOT)
|
||||||
|
STAGE_ROOT ?= ${OBJROOT}stage
|
||||||
|
.export STAGE_ROOT
|
||||||
|
.endif
|
||||||
|
|
||||||
|
# We should be included before meta.sys.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(_tspec_env_done_)
|
||||||
|
_tspec_env_done_: .NOTMAIN
|
||||||
|
|
||||||
|
.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
|
||||||
|
|
||||||
|
.if ${TARGET_SPEC_VARS:[#]} > 1
|
||||||
|
TARGET_OBJ_SPEC ?= ${TARGET_SPEC_VARS:@v@${$v:U}@:ts.}
|
||||||
|
.else
|
||||||
|
TARGET_OBJ_SPEC ?= ${MACHINE}
|
||||||
|
.endif
|
||||||
|
|
||||||
|
MAKE_PRINT_VAR_ON_ERROR += ${TARGET_SPEC_VARS}
|
||||||
|
|
||||||
|
.if !defined(MACHINE0)
|
||||||
|
# it can be handy to know which MACHINE kicked off the build
|
||||||
|
# for example, if using Makefild.depend for multiple machines,
|
||||||
|
# allowing only MACHINE0 to update can keep things simple.
|
||||||
|
MACHINE0 := ${MACHINE}
|
||||||
|
.export MACHINE0
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.if ${MACHINE} == "host"
|
||||||
|
OBJTOP = ${HOST_OBJTOP}
|
||||||
|
.elif ${MACHINE} == "host32"
|
||||||
|
OBJTOP = ${HOST_OBJTOP32}
|
||||||
|
.endif
|
||||||
|
|
||||||
|
MACHINE_OBJ.host = ${HOST_TARGET}
|
||||||
|
MACHINE_OBJ.host32 = ${HOST_TARGET32}
|
||||||
|
MACHINE_OBJ.${MACHINE} ?= ${TARGET_OBJ_SPEC}
|
||||||
|
MACHINE_OBJDIR = ${MACHINE_OBJ.${MACHINE}}
|
||||||
|
OBJTOP = ${OBJROOT}/${MACHINE_OBJDIR}
|
||||||
|
|
||||||
|
# we do not use MAKEOBJDIRPREFIX
|
||||||
|
.undef MAKEOBJDIRPREFIX
|
||||||
|
# we use this
|
||||||
|
MAKEOBJDIR ?= ${.CURDIR:S,${SRCTOP},${OBJTOP},}
|
||||||
|
|
||||||
|
STAGE_MACHINE ?= ${MACHINE_OBJDIR}
|
||||||
|
STAGE_OBJTOP ?= ${STAGE_ROOT}/${STAGE_MACHINE}
|
||||||
|
STAGE_COMMON_OBJTOP ?= ${STAGE_ROOT}/common
|
||||||
|
STAGE_HOST_OBJTOP ?= ${STAGE_ROOT}/${HOST_TARGET}
|
||||||
|
STAGE_HOST_OBJTOP32 ?= ${STAGE_ROOT}/${HOST_TARGET32}
|
||||||
|
|
||||||
|
STAGE_INCLUDEDIR ?= ${STAGE_OBJTOP}${INCLUDEDIR:U/usr/include}
|
||||||
|
STAGE_LIBDIR ?= ${STAGE_OBJTOP}${LIBDIR:U/lib}
|
||||||
|
|
||||||
|
TIME_STAMP_FMT ?= @ %s [%Y-%m-%d %T] ${:U}
|
||||||
|
DATE_TIME_STAMP ?= `date '+${TIME_STAMP_FMT}'`
|
||||||
|
TIME_STAMP ?= ${TIME_STAMP_FMT:localtime}
|
||||||
|
|
||||||
|
.if ${MK_TIME_STAMPS:Uyes} == "yes"
|
||||||
|
TRACER = ${TIME_STAMP}
|
||||||
|
ECHO_DIR = echo ${TIME_STAMP}
|
||||||
|
ECHO_TRACE = echo ${TIME_STAMP}
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.if ${.CURDIR} == ${SRCTOP}
|
||||||
|
RELDIR= .
|
||||||
|
RELTOP= .
|
||||||
|
.elif ${.CURDIR:M${SRCTOP}/*}
|
||||||
|
RELDIR:= ${.CURDIR:S,${SRCTOP}/,,}
|
||||||
|
.else
|
||||||
|
RELDIR:= ${.OBJDIR:S,${OBJTOP}/,,}
|
||||||
|
.endif
|
||||||
|
RELTOP?= ${RELDIR:C,[^/]+,..,g}
|
||||||
|
RELOBJTOP?= ${RELTOP}
|
||||||
|
RELSRCTOP?= ${RELTOP}
|
||||||
|
|
||||||
|
# this does all the smarts of setting .MAKE.DEPENDFILE
|
||||||
|
.-include <sys.dependfile.mk>
|
||||||
|
|
||||||
|
.-include <local.sys.dirdeps.mk>
|
||||||
|
|
||||||
|
# check if we got anything sane
|
||||||
|
.if ${.MAKE.DEPENDFILE} == ".depend"
|
||||||
|
.undef .MAKE.DEPENDFILE
|
||||||
|
.endif
|
||||||
|
# just in case
|
||||||
|
.MAKE.DEPENDFILE ?= Makefile.depend
|
||||||
|
|
||||||
|
.if ${.MAKE.LEVEL} > 0
|
||||||
|
# Makefile.depend* also get read at level 1+
|
||||||
|
# and often refer to DEP_MACHINE etc,
|
||||||
|
# so ensure DEP_* (for TARGET_SPEC_VARS anyway) are set
|
||||||
|
.for V in ${TARGET_SPEC_VARS}
|
||||||
|
DEP_$V = ${$V}
|
||||||
|
.endfor
|
||||||
|
.endif
|
|
@ -1,4 +1,4 @@
|
||||||
# $Id: sys.mk,v 1.54 2022/09/09 17:44:29 sjg Exp $
|
# $Id: sys.mk,v 1.55 2023/05/10 19:23:26 sjg Exp $
|
||||||
#
|
#
|
||||||
# @(#) Copyright (c) 2003-2009, Simon J. Gerraty
|
# @(#) Copyright (c) 2003-2009, Simon J. Gerraty
|
||||||
#
|
#
|
||||||
|
@ -85,6 +85,9 @@ OPTIONS_DEFAULT_DEPENDENT += \
|
||||||
.-include <options.mk>
|
.-include <options.mk>
|
||||||
|
|
||||||
# :Uno incase options.mk not installed
|
# :Uno incase options.mk not installed
|
||||||
|
.if ${MK_DIRDEPS_BUILD:Uno} == "yes"
|
||||||
|
.-include <sys.dirdeps.mk>
|
||||||
|
.endif
|
||||||
.if ${MK_META_MODE:Uno} == "yes"
|
.if ${MK_META_MODE:Uno} == "yes"
|
||||||
.-include <meta.sys.mk>
|
.-include <meta.sys.mk>
|
||||||
.MAKE.MODE ?= meta verbose {META_MODE}
|
.MAKE.MODE ?= meta verbose {META_MODE}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: parse.c,v 1.696 2023/02/15 06:52:58 rillig Exp $ */
|
/* $NetBSD: parse.c,v 1.698 2023/05/10 16:10:02 rillig Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988, 1989, 1990, 1993
|
* Copyright (c) 1988, 1989, 1990, 1993
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
* Parse_Error Report a parse error, a warning or an informational
|
* Parse_Error Report a parse error, a warning or an informational
|
||||||
* message.
|
* message.
|
||||||
*
|
*
|
||||||
* Parse_MainName Returns a list of the single main target to create.
|
* Parse_MainName Populate the list of targets to create.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -121,7 +121,7 @@
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
|
|
||||||
/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
|
/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
|
||||||
MAKE_RCSID("$NetBSD: parse.c,v 1.696 2023/02/15 06:52:58 rillig Exp $");
|
MAKE_RCSID("$NetBSD: parse.c,v 1.698 2023/05/10 16:10:02 rillig Exp $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A file being read.
|
* A file being read.
|
||||||
|
@ -257,10 +257,7 @@ SearchPath *defSysIncPath; /* default for sysIncPath */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The parseKeywords table is searched using binary search when deciding
|
* The parseKeywords table is searched using binary search when deciding
|
||||||
* if a target or source is special. The 'spec' field is the ParseSpecial
|
* if a target or source is special.
|
||||||
* type of the keyword (SP_NOT if the keyword isn't special as a target) while
|
|
||||||
* the 'op' field is the operator to apply to the list of targets if the
|
|
||||||
* keyword is used as a source ("0" if the keyword isn't special as a source)
|
|
||||||
*/
|
*/
|
||||||
static const struct {
|
static const struct {
|
||||||
const char name[17];
|
const char name[17];
|
||||||
|
@ -325,7 +322,7 @@ GetInclude(size_t i)
|
||||||
return Vector_Get(&includes, i);
|
return Vector_Get(&includes, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The file that is currently being read. */
|
/* The makefile that is currently being read. */
|
||||||
static IncludedFile *
|
static IncludedFile *
|
||||||
CurFile(void)
|
CurFile(void)
|
||||||
{
|
{
|
||||||
|
@ -403,8 +400,11 @@ PrintStackTrace(bool includingInnermost)
|
||||||
const char *fname = entry->name.str;
|
const char *fname = entry->name.str;
|
||||||
char dirbuf[MAXPATHLEN + 1];
|
char dirbuf[MAXPATHLEN + 1];
|
||||||
|
|
||||||
if (fname[0] != '/' && strcmp(fname, "(stdin)") != 0)
|
if (fname[0] != '/' && strcmp(fname, "(stdin)") != 0) {
|
||||||
fname = realpath(fname, dirbuf);
|
const char *realPath = realpath(fname, dirbuf);
|
||||||
|
if (realPath != NULL)
|
||||||
|
fname = realPath;
|
||||||
|
}
|
||||||
|
|
||||||
if (entry->forLoop != NULL) {
|
if (entry->forLoop != NULL) {
|
||||||
char *details = ForLoop_Details(entry->forLoop);
|
char *details = ForLoop_Details(entry->forLoop);
|
||||||
|
@ -658,7 +658,7 @@ TryApplyDependencyOperator(GNode *gn, GNodeType op)
|
||||||
|
|
||||||
if (op == OP_DOUBLEDEP && (gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
|
if (op == OP_DOUBLEDEP && (gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
|
||||||
/*
|
/*
|
||||||
* If the node was of the left-hand side of a '::' operator,
|
* If the node was on the left-hand side of a '::' operator,
|
||||||
* we need to create a new instance of it for the children
|
* we need to create a new instance of it for the children
|
||||||
* and commands on this dependency line since each of these
|
* and commands on this dependency line since each of these
|
||||||
* dependency groups has its own attributes and commands,
|
* dependency groups has its own attributes and commands,
|
||||||
|
@ -3004,10 +3004,7 @@ Parse_End(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/* Populate the list with the single main target to create, or error out. */
|
||||||
* Return a list containing the single main target to create.
|
|
||||||
* If no such target exists, we Punt with an obnoxious error message.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
Parse_MainName(GNodeList *mainList)
|
Parse_MainName(GNodeList *mainList)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# $Id: Makefile,v 1.193 2023/02/25 20:03:25 sjg Exp $
|
# $Id: Makefile,v 1.195 2023/05/10 18:26:24 sjg Exp $
|
||||||
#
|
#
|
||||||
# $NetBSD: Makefile,v 1.333 2023/02/25 19:30:32 sjg Exp $
|
# $NetBSD: Makefile,v 1.335 2023/05/10 13:03:06 rillig Exp $
|
||||||
#
|
#
|
||||||
# Unit tests for make(1)
|
# Unit tests for make(1)
|
||||||
#
|
#
|
||||||
|
@ -211,7 +211,6 @@ TESTS+= export
|
||||||
TESTS+= export-all
|
TESTS+= export-all
|
||||||
TESTS+= export-env
|
TESTS+= export-env
|
||||||
TESTS+= export-variants
|
TESTS+= export-variants
|
||||||
TESTS+= forloop
|
|
||||||
TESTS+= forsubst
|
TESTS+= forsubst
|
||||||
TESTS+= gnode-submake
|
TESTS+= gnode-submake
|
||||||
TESTS+= hanoi-include
|
TESTS+= hanoi-include
|
||||||
|
@ -375,6 +374,7 @@ TESTS+= varmod-loop-delete
|
||||||
TESTS+= varmod-loop-varname
|
TESTS+= varmod-loop-varname
|
||||||
TESTS+= varmod-match
|
TESTS+= varmod-match
|
||||||
TESTS+= varmod-match-escape
|
TESTS+= varmod-match-escape
|
||||||
|
TESTS+= varmod-mtime
|
||||||
TESTS+= varmod-no-match
|
TESTS+= varmod-no-match
|
||||||
TESTS+= varmod-order
|
TESTS+= varmod-order
|
||||||
TESTS+= varmod-order-numeric
|
TESTS+= varmod-order-numeric
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
# $NetBSD: cond-func.mk,v 1.11 2022/01/07 19:30:17 rillig Exp $
|
# $NetBSD: cond-func.mk,v 1.12 2023/05/10 15:53:32 rillig Exp $
|
||||||
#
|
#
|
||||||
# Tests for those parts of the functions in .if conditions that are common
|
# Tests for those parts of the functions in .if conditions that are common
|
||||||
# among several functions.
|
# among several functions.
|
||||||
#
|
#
|
||||||
# The below test uses the function defined(...) since it has no side-effects,
|
# The below test uses the 'defined' function since it has no side-effects.
|
||||||
# the other functions (except empty(...)) would work equally well. The
|
# The other functions would work equally well, except for 'empty', which
|
||||||
# function empty is special because it uses a different parsing algorithm for
|
# parses its argument differently from the other functions.
|
||||||
# its argument.
|
#
|
||||||
|
|
||||||
DEF= defined
|
DEF= defined
|
||||||
${:UA B}= variable name with spaces
|
${:UA B}= variable name with spaces
|
||||||
|
@ -74,7 +74,7 @@ ${VARNAME_UNBALANCED_BRACES}= variable name with unbalanced braces
|
||||||
|
|
||||||
# There may be spaces around the operators and parentheses, and even
|
# There may be spaces around the operators and parentheses, and even
|
||||||
# inside the parentheses. The spaces inside the parentheses are not
|
# inside the parentheses. The spaces inside the parentheses are not
|
||||||
# allowed for the empty() function (see cond-func-empty.mk), therefore
|
# allowed for the 'empty' function (see cond-func-empty.mk), therefore
|
||||||
# they are typically omitted for the other functions as well.
|
# they are typically omitted for the other functions as well.
|
||||||
.if ! defined ( DEF )
|
.if ! defined ( DEF )
|
||||||
. error
|
. error
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
# $NetBSD: cond-late.mk,v 1.3 2020/11/15 14:07:53 rillig Exp $
|
# $NetBSD: cond-late.mk,v 1.4 2023/05/10 15:53:32 rillig Exp $
|
||||||
#
|
#
|
||||||
# Using the :? modifier, variable expressions can contain conditional
|
# Using the :? modifier, variable expressions can contain conditional
|
||||||
# expressions that are evaluated late, at expansion time.
|
# expressions that are evaluated late, at expansion time.
|
||||||
#
|
#
|
||||||
# Any variables appearing in these
|
# Any expressions appearing in these conditions are expanded before parsing
|
||||||
# conditions are expanded before parsing the condition. This is
|
# the condition. This is different from conditions in .if directives, where
|
||||||
# different from many other places.
|
# expressions are evaluated individually and only as far as necessary, see
|
||||||
|
# cond-short.mk.
|
||||||
#
|
#
|
||||||
# Because of this, variables that are used in these lazy conditions
|
# Because of this, variables that are used in these lazy conditions
|
||||||
# should not contain double-quotes, or the parser will probably fail.
|
# should not contain double-quotes, or the parser will probably fail.
|
||||||
|
@ -22,10 +23,14 @@ COND.false= "yes" != "yes"
|
||||||
# If the order of evaluation were to change to first parse the condition
|
# If the order of evaluation were to change to first parse the condition
|
||||||
# and then expand the variables, the output would change from the
|
# and then expand the variables, the output would change from the
|
||||||
# current "yes no" to "yes yes", since both variables are non-empty.
|
# current "yes no" to "yes yes", since both variables are non-empty.
|
||||||
|
# expect: yes
|
||||||
|
# expect: no
|
||||||
cond-literal:
|
cond-literal:
|
||||||
@echo ${ ${COND.true} :?yes:no}
|
@echo ${ ${COND.true} :?yes:no}
|
||||||
@echo ${ ${COND.false} :?yes:no}
|
@echo ${ ${COND.false} :?yes:no}
|
||||||
|
|
||||||
VAR+= ${${UNDEF} != "no":?:}
|
VAR= ${${UNDEF} != "no":?:}
|
||||||
|
# expect-reset
|
||||||
|
# expect: make: Bad conditional expression ' != "no"' in ' != "no"?:'
|
||||||
.if empty(VAR:Mpattern)
|
.if empty(VAR:Mpattern)
|
||||||
.endif
|
.endif
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# $NetBSD: dep-var.mk,v 1.7 2023/02/13 21:01:46 rillig Exp $
|
# $NetBSD: dep-var.mk,v 1.8 2023/05/10 15:53:32 rillig Exp $
|
||||||
#
|
#
|
||||||
# Tests for variable references in dependency declarations.
|
# Tests for variable references in dependency declarations.
|
||||||
#
|
#
|
||||||
|
@ -91,5 +91,6 @@ undef1 def2 a-def2-b 1-2-$$INDIRECT_2-2-1 ${:U\$)}:
|
||||||
|
|
||||||
.MAKEFLAGS: -d0
|
.MAKEFLAGS: -d0
|
||||||
|
|
||||||
# XXX: Why is the exit status still 0, even though Parse_Error is called
|
# XXX: The exit status is still 0, even though Parse_Error is called with
|
||||||
# with PARSE_FATAL in SuffExpandChildren?
|
# PARSE_FATAL in SuffExpandChildren. The exit status is only affected by
|
||||||
|
# parse errors when they occur in the parsing phase, see Parse_File.
|
||||||
|
|
|
@ -1,22 +1,17 @@
|
||||||
make: "directive-for-errors.mk" line 7: Unknown directive "fori"
|
make: "directive-for-errors.mk" line 11: Unknown directive "fori"
|
||||||
make: "directive-for-errors.mk" line 8: warning:
|
make: "directive-for-errors.mk" line 12: warning: <>
|
||||||
make: "directive-for-errors.mk" line 9: for-less endfor
|
make: "directive-for-errors.mk" line 13: for-less endfor
|
||||||
make: "directive-for-errors.mk" line 19: Unknown directive "for"
|
make: "directive-for-errors.mk" line 27: Unknown directive "for"
|
||||||
make: "directive-for-errors.mk" line 20: warning:
|
make: "directive-for-errors.mk" line 28: warning: <>
|
||||||
make: "directive-for-errors.mk" line 21: for-less endfor
|
make: "directive-for-errors.mk" line 29: for-less endfor
|
||||||
make: "directive-for-errors.mk" line 37: Dollar $ 1 1 and backslash 2 2 2.
|
make: "directive-for-errors.mk" line 46: invalid character '$' in .for loop variable name
|
||||||
make: "directive-for-errors.mk" line 37: Dollar $ 3 3 and backslash 4 4 4.
|
make: "directive-for-errors.mk" line 54: no iteration variables in for
|
||||||
make: "directive-for-errors.mk" line 43: no iteration variables in for
|
make: "directive-for-errors.mk" line 66: Wrong number of words (5) in .for substitution list with 3 variables
|
||||||
make: "directive-for-errors.mk" line 47: warning: Should not be reached.
|
make: "directive-for-errors.mk" line 80: missing `in' in for
|
||||||
make: "directive-for-errors.mk" line 48: for-less endfor
|
make: "directive-for-errors.mk" line 91: Unknown modifier "Z"
|
||||||
make: "directive-for-errors.mk" line 53: Wrong number of words (5) in .for substitution list with 3 variables
|
make: "directive-for-errors.mk" line 92: warning: Should not be reached.
|
||||||
make: "directive-for-errors.mk" line 64: missing `in' in for
|
make: "directive-for-errors.mk" line 92: warning: Should not be reached.
|
||||||
make: "directive-for-errors.mk" line 66: warning: Should not be reached.
|
make: "directive-for-errors.mk" line 92: warning: Should not be reached.
|
||||||
make: "directive-for-errors.mk" line 67: for-less endfor
|
|
||||||
make: "directive-for-errors.mk" line 73: Unknown modifier "Z"
|
|
||||||
make: "directive-for-errors.mk" line 74: warning: Should not be reached.
|
|
||||||
make: "directive-for-errors.mk" line 74: warning: Should not be reached.
|
|
||||||
make: "directive-for-errors.mk" line 74: warning: Should not be reached.
|
|
||||||
make: Fatal errors encountered -- cannot continue
|
make: Fatal errors encountered -- cannot continue
|
||||||
make: stopped in unit-tests
|
make: stopped in unit-tests
|
||||||
exit status 1
|
exit status 1
|
||||||
|
|
|
@ -1,45 +1,56 @@
|
||||||
# $NetBSD: directive-for-errors.mk,v 1.3 2021/04/04 10:13:09 rillig Exp $
|
# $NetBSD: directive-for-errors.mk,v 1.5 2023/05/09 19:43:12 rillig Exp $
|
||||||
#
|
#
|
||||||
# Tests for error handling in .for loops.
|
# Tests for error handling in .for loops.
|
||||||
|
|
||||||
|
# expect-all
|
||||||
|
|
||||||
|
|
||||||
# A .for directive must be followed by whitespace, everything else results
|
# A .for directive must be followed by whitespace, everything else results
|
||||||
# in a parse error.
|
# in a parse error.
|
||||||
|
# expect+1: Unknown directive "fori"
|
||||||
.fori in 1 2 3
|
.fori in 1 2 3
|
||||||
. warning ${i}
|
. warning <${i}>
|
||||||
.endfor
|
.endfor
|
||||||
|
# expect-2: <>
|
||||||
|
# expect-2: for-less endfor
|
||||||
|
|
||||||
|
|
||||||
# A slash is not whitespace, therefore this is not parsed as a .for loop.
|
# A slash is not whitespace, therefore this is not parsed as a .for loop.
|
||||||
#
|
#
|
||||||
# XXX: The error message is misleading though. As of 2020-12-31, it says
|
# XXX: The error message is misleading though. As of 2020-12-31, it says
|
||||||
# "Unknown directive "for"", but that directive is actually known. This is
|
# 'Unknown directive "for"', but that directive is actually known. This is
|
||||||
# because ForEval does not detect the .for loop as such, so parsing
|
# because ForEval does not detect the .for loop as such, so parsing
|
||||||
# continues in ParseLine > ParseDependencyLine > ParseDependency >
|
# continues in ParseLine > ParseDependencyLine > ParseDependency >
|
||||||
# ParseDependencyTargets > ParseErrorNoDependency, and there the directive
|
# ParseDependencyTargets > ParseErrorNoDependency, and there the directive
|
||||||
# name is parsed a bit differently.
|
# name is parsed a bit differently.
|
||||||
|
# expect+1: Unknown directive "for"
|
||||||
.for/i in 1 2 3
|
.for/i in 1 2 3
|
||||||
. warning ${i}
|
. warning <${i}>
|
||||||
.endfor
|
.endfor
|
||||||
|
# expect-2: warning: <>
|
||||||
|
# expect-2: for-less endfor
|
||||||
|
|
||||||
# As of 2020-12-31, the variable name can be an arbitrary word, it just needs
|
|
||||||
# to be separated by whitespace. Even '$' and '\' are valid variable names,
|
# Before for.c 1.173 from 2023-05-08, the variable name could be an arbitrary
|
||||||
# which is not useful in practice.
|
# word, it only needed to be separated by whitespace. Even '$' and '\' were
|
||||||
|
# valid variable names, which was not useful in practice.
|
||||||
#
|
#
|
||||||
# The '$$' is not replaced with the values '1' or '3' from the .for loop,
|
# The '$$' was not replaced with the values '1' or '3' from the .for loop,
|
||||||
# instead it is kept as-is, and when the .info directive expands its argument,
|
# instead it was kept as-is, and when the .info directive expanded its
|
||||||
# each '$$' gets replaced with a single '$'. The "long variable expression"
|
# argument, each '$$' got replaced with a single '$'. The "long variable
|
||||||
# ${$} gets replaced though, even though this would be a parse error everywhere
|
# expression" ${$} got replaced though, even though this would be a parse
|
||||||
# outside a .for loop.
|
# error everywhere outside a .for loop.
|
||||||
#
|
|
||||||
# The '\' on the other hand is treated as a normal variable name.
|
|
||||||
${:U\$}= dollar # see whether the "variable" '$' is local
|
${:U\$}= dollar # see whether the "variable" '$' is local
|
||||||
${:U\\}= backslash # see whether the "variable" '\' is local
|
${:U\\}= backslash # see whether the "variable" '\' is local
|
||||||
|
# expect+1: invalid character '$' in .for loop variable name
|
||||||
.for $ \ in 1 2 3 4
|
.for $ \ in 1 2 3 4
|
||||||
. info Dollar $$ ${$} $($) and backslash $\ ${\} $(\).
|
. info Dollar $$ ${$} $($) and backslash $\ ${\} $(\).
|
||||||
.endfor
|
.endfor
|
||||||
|
|
||||||
# If there are no variables, there is no point in expanding the .for loop
|
# If there are no variables, there is no point in expanding the .for loop
|
||||||
# since this would end up in an endless loop, each time consuming 0 of the
|
# since this would end up in an endless loop, consuming 0 of the 3 values in
|
||||||
# 3 values.
|
# each iteration.
|
||||||
|
# expect+1: no iteration variables in for
|
||||||
.for in 1 2 3
|
.for in 1 2 3
|
||||||
# XXX: This should not be reached. It should be skipped, as already done
|
# XXX: This should not be reached. It should be skipped, as already done
|
||||||
# when the number of values is not a multiple of the number of variables,
|
# when the number of values is not a multiple of the number of variables,
|
||||||
|
@ -47,29 +58,39 @@ ${:U\\}= backslash # see whether the "variable" '\' is local
|
||||||
. warning Should not be reached.
|
. warning Should not be reached.
|
||||||
.endfor
|
.endfor
|
||||||
|
|
||||||
|
|
||||||
# There are 3 variables and 5 values. These 5 values cannot be split evenly
|
# There are 3 variables and 5 values. These 5 values cannot be split evenly
|
||||||
# among the variables, therefore the loop is not expanded at all, it is
|
# among the variables, therefore the loop is not expanded at all, it is
|
||||||
# rather skipped.
|
# skipped instead.
|
||||||
|
# expect+1: Wrong number of words (5) in .for substitution list with 3 variables
|
||||||
.for a b c in 1 2 3 4 5
|
.for a b c in 1 2 3 4 5
|
||||||
. warning Should not be reached.
|
. warning Should not be reached.
|
||||||
.endfor
|
.endfor
|
||||||
|
|
||||||
|
|
||||||
# The list of values after the 'in' may be empty, no matter if this emptiness
|
# The list of values after the 'in' may be empty, no matter if this emptiness
|
||||||
# comes from an empty expansion or even from a syntactically empty line.
|
# comes from an empty expansion or even from a syntactically empty line.
|
||||||
.for i in
|
.for i in
|
||||||
. info Would be reached if there were items to loop over.
|
. info Would be reached if there were items to loop over.
|
||||||
.endfor
|
.endfor
|
||||||
|
|
||||||
|
|
||||||
# A missing 'in' should parse the .for loop but skip the body.
|
# A missing 'in' should parse the .for loop but skip the body.
|
||||||
.for i : k
|
# expect+1: missing `in' in for
|
||||||
|
.for i over k
|
||||||
# XXX: As of 2020-12-31, this line is reached once.
|
# XXX: As of 2020-12-31, this line is reached once.
|
||||||
. warning Should not be reached.
|
. warning Should not be reached.
|
||||||
.endfor
|
.endfor
|
||||||
|
|
||||||
|
|
||||||
# A malformed modifier should be detected and skip the body of the loop.
|
# A malformed modifier should be detected and skip the body of the loop.
|
||||||
#
|
#
|
||||||
# XXX: As of 2020-12-31, Var_Subst doesn't report any errors, therefore
|
# XXX: As of 2020-12-31, Var_Subst doesn't report any errors, therefore
|
||||||
# the loop body is expanded as if no error had happened.
|
# the loop body is expanded as if no error had happened.
|
||||||
|
# expect+1: Unknown modifier "Z"
|
||||||
.for i in 1 2 ${:U3:Z} 4
|
.for i in 1 2 ${:U3:Z} 4
|
||||||
. warning Should not be reached.
|
. warning Should not be reached.
|
||||||
.endfor
|
.endfor
|
||||||
|
# expect-2: Should not be reached.
|
||||||
|
# expect-3: Should not be reached.
|
||||||
|
# expect-4: Should not be reached.
|
||||||
|
|
|
@ -2,28 +2,28 @@ For: end for 1
|
||||||
For: loop body:
|
For: loop body:
|
||||||
. info ${:U!"#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~}
|
. info ${:U!"#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~}
|
||||||
make: Unclosed variable expression, expecting '}' for modifier "U!"" of variable "" with value "!""
|
make: Unclosed variable expression, expecting '}' for modifier "U!"" of variable "" with value "!""
|
||||||
make: "directive-for-escape.mk" line 19: !"
|
make: "directive-for-escape.mk" line 21: !"
|
||||||
For: end for 1
|
For: end for 1
|
||||||
For: loop body:
|
For: loop body:
|
||||||
. info ${:U!"\\\\#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~}
|
. info ${:U!"\\\\#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~}
|
||||||
make: Unclosed variable expression, expecting '}' for modifier "U!"\\\\" of variable "" with value "!"\\"
|
make: Unclosed variable expression, expecting '}' for modifier "U!"\\\\" of variable "" with value "!"\\"
|
||||||
make: "directive-for-escape.mk" line 29: !"\\
|
make: "directive-for-escape.mk" line 32: !"\\
|
||||||
For: end for 1
|
For: end for 1
|
||||||
For: loop body:
|
For: loop body:
|
||||||
. info ${:U\$}
|
. info ${:U\$}
|
||||||
make: "directive-for-escape.mk" line 43: $
|
make: "directive-for-escape.mk" line 47: $
|
||||||
For: loop body:
|
For: loop body:
|
||||||
. info ${:U${V}}
|
. info ${:U${V}}
|
||||||
make: "directive-for-escape.mk" line 43: value
|
make: "directive-for-escape.mk" line 47: value
|
||||||
For: loop body:
|
For: loop body:
|
||||||
. info ${:U${V:=-with-modifier}}
|
. info ${:U${V:=-with-modifier}}
|
||||||
make: "directive-for-escape.mk" line 43: value-with-modifier
|
make: "directive-for-escape.mk" line 47: value-with-modifier
|
||||||
For: loop body:
|
For: loop body:
|
||||||
. info ${:U$(V)}
|
. info ${:U$(V)}
|
||||||
make: "directive-for-escape.mk" line 43: value
|
make: "directive-for-escape.mk" line 47: value
|
||||||
For: loop body:
|
For: loop body:
|
||||||
. info ${:U$(V:=-with-modifier)}
|
. info ${:U$(V:=-with-modifier)}
|
||||||
make: "directive-for-escape.mk" line 43: value-with-modifier
|
make: "directive-for-escape.mk" line 47: value-with-modifier
|
||||||
For: end for 1
|
For: end for 1
|
||||||
For: loop body:
|
For: loop body:
|
||||||
# ${:U\${UNDEF\:U\\$\\$}
|
# ${:U\${UNDEF\:U\\$\\$}
|
||||||
|
@ -34,29 +34,25 @@ For: loop body:
|
||||||
For: end for 1
|
For: end for 1
|
||||||
For: loop body:
|
For: loop body:
|
||||||
. info ${:U\${UNDEF\:U\\$\\$}
|
. info ${:U\${UNDEF\:U\\$\\$}
|
||||||
make: "directive-for-escape.mk" line 92: ${UNDEF:U\backslash$
|
make: "directive-for-escape.mk" line 101: ${UNDEF:U\backslash$
|
||||||
For: loop body:
|
For: loop body:
|
||||||
. info ${:U{{\}\}}
|
. info ${:U{{\}\}}
|
||||||
make: "directive-for-escape.mk" line 92: {{}}
|
make: "directive-for-escape.mk" line 101: {{}}
|
||||||
For: loop body:
|
For: loop body:
|
||||||
. info ${:Uend\}}
|
. info ${:Uend\}}
|
||||||
make: "directive-for-escape.mk" line 92: end}
|
make: "directive-for-escape.mk" line 101: end}
|
||||||
For: end for 1
|
For: end for 1
|
||||||
For: loop body:
|
For: loop body:
|
||||||
. info ${:Ubegin<${UNDEF:Ufallback:N{{{}}}}>end}
|
. info ${:Ubegin<${UNDEF:Ufallback:N{{{}}}}>end}
|
||||||
make: "directive-for-escape.mk" line 113: begin<fallback>end
|
make: "directive-for-escape.mk" line 122: begin<fallback>end
|
||||||
For: end for 1
|
For: end for 1
|
||||||
For: loop body:
|
For: loop body:
|
||||||
. info ${:U\$}
|
. info ${:U\$}
|
||||||
make: "directive-for-escape.mk" line 121: $
|
make: "directive-for-escape.mk" line 131: $
|
||||||
|
make: "directive-for-escape.mk" line 140: invalid character ':' in .for loop variable name
|
||||||
For: end for 1
|
For: end for 1
|
||||||
For: loop body:
|
make: "directive-for-escape.mk" line 150: invalid character '}' in .for loop variable name
|
||||||
. info ${NUMBERS} ${:Ureplaced}
|
|
||||||
make: "directive-for-escape.mk" line 129: one two three replaced
|
|
||||||
For: end for 1
|
For: end for 1
|
||||||
For: loop body:
|
|
||||||
. info ${:Ureplaced}
|
|
||||||
make: "directive-for-escape.mk" line 139: replaced
|
|
||||||
For: end for 1
|
For: end for 1
|
||||||
For: loop body:
|
For: loop body:
|
||||||
. info . $$i: ${:Uinner}
|
. info . $$i: ${:Uinner}
|
||||||
|
@ -69,46 +65,42 @@ For: loop body:
|
||||||
. info . $${i2}: ${i2}
|
. info . $${i2}: ${i2}
|
||||||
. info . $${i,}: ${i,}
|
. info . $${i,}: ${i,}
|
||||||
. info . adjacent: ${:Uinner}${:Uinner}${:Uinner:M*}${:Uinner}
|
. info . adjacent: ${:Uinner}${:Uinner}${:Uinner:M*}${:Uinner}
|
||||||
make: "directive-for-escape.mk" line 147: . $i: inner
|
make: "directive-for-escape.mk" line 159: . $i: inner
|
||||||
make: "directive-for-escape.mk" line 148: . ${i}: inner
|
make: "directive-for-escape.mk" line 160: . ${i}: inner
|
||||||
make: "directive-for-escape.mk" line 149: . ${i:M*}: inner
|
make: "directive-for-escape.mk" line 161: . ${i:M*}: inner
|
||||||
make: "directive-for-escape.mk" line 150: . $(i): inner
|
make: "directive-for-escape.mk" line 162: . $(i): inner
|
||||||
make: "directive-for-escape.mk" line 151: . $(i:M*): inner
|
make: "directive-for-escape.mk" line 163: . $(i:M*): inner
|
||||||
make: "directive-for-escape.mk" line 152: . ${i${:U}}: outer
|
make: "directive-for-escape.mk" line 164: . ${i${:U}}: outer
|
||||||
make: "directive-for-escape.mk" line 153: . ${i\}}: inner}
|
make: "directive-for-escape.mk" line 165: . ${i\}}: inner}
|
||||||
make: "directive-for-escape.mk" line 154: . ${i2}: two
|
make: "directive-for-escape.mk" line 166: . ${i2}: two
|
||||||
make: "directive-for-escape.mk" line 155: . ${i,}: comma
|
make: "directive-for-escape.mk" line 167: . ${i,}: comma
|
||||||
make: "directive-for-escape.mk" line 156: . adjacent: innerinnerinnerinner
|
make: "directive-for-escape.mk" line 168: . adjacent: innerinnerinnerinner
|
||||||
|
make: "directive-for-escape.mk" line 187: invalid character '$' in .for loop variable name
|
||||||
For: end for 1
|
For: end for 1
|
||||||
For: loop body:
|
make: "directive-for-escape.mk" line 199: eight and no cents.
|
||||||
. info eight $$$$$$$$ and no cents.
|
|
||||||
. info eight ${:Udollar}${:Udollar}${:Udollar}${:Udollar} and no cents.
|
|
||||||
make: "directive-for-escape.mk" line 164: eight $$$$ and no cents.
|
|
||||||
make: "directive-for-escape.mk" line 165: eight dollardollardollardollar and no cents.
|
|
||||||
make: "directive-for-escape.mk" line 174: eight and no cents.
|
|
||||||
For: end for 1
|
For: end for 1
|
||||||
make: "directive-for-escape.mk" line 181: newline in .for value
|
make: "directive-for-escape.mk" line 212: newline in .for value
|
||||||
make: "directive-for-escape.mk" line 181: newline in .for value
|
make: "directive-for-escape.mk" line 212: newline in .for value
|
||||||
For: loop body:
|
For: loop body:
|
||||||
. info short: ${:U" "}
|
. info short: ${:U" "}
|
||||||
. info long: ${:U" "}
|
. info long: ${:U" "}
|
||||||
make: "directive-for-escape.mk" line 182: short: " "
|
make: "directive-for-escape.mk" line 213: short: " "
|
||||||
make: "directive-for-escape.mk" line 183: long: " "
|
make: "directive-for-escape.mk" line 214: long: " "
|
||||||
For: end for 1
|
For: end for 1
|
||||||
For: loop body:
|
For: loop body:
|
||||||
For: end for 1
|
For: end for 1
|
||||||
Parse_PushInput: .for loop in directive-for-escape.mk, line 196
|
Parse_PushInput: .for loop in directive-for-escape.mk, line 230
|
||||||
make: "directive-for-escape.mk" line 196: newline in .for value
|
make: "directive-for-escape.mk" line 230: newline in .for value
|
||||||
in .for loop from directive-for-escape.mk:196 with i = "
|
in .for loop from directive-for-escape.mk:230 with i = "
|
||||||
"
|
"
|
||||||
For: loop body:
|
For: loop body:
|
||||||
: ${:U" "}
|
: ${:U" "}
|
||||||
SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `directive-for-escape.mk'
|
SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `directive-for-escape.mk'
|
||||||
Parsing line 197: : ${:U" "}
|
Parsing line 231: : ${:U" "}
|
||||||
ParseDependency(: " ")
|
ParseDependency(: " ")
|
||||||
ParseEOF: returning to file directive-for-escape.mk, line 199
|
ParseEOF: returning to file directive-for-escape.mk, line 233
|
||||||
SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `directive-for-escape.mk'
|
SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `directive-for-escape.mk'
|
||||||
Parsing line 199: .MAKEFLAGS: -d0
|
Parsing line 233: .MAKEFLAGS: -d0
|
||||||
ParseDependency(.MAKEFLAGS: -d0)
|
ParseDependency(.MAKEFLAGS: -d0)
|
||||||
For: end for 1
|
For: end for 1
|
||||||
For: loop body:
|
For: loop body:
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
# $NetBSD: directive-for-escape.mk,v 1.16 2022/06/12 16:09:21 rillig Exp $
|
# $NetBSD: directive-for-escape.mk,v 1.18 2023/05/09 19:43:12 rillig Exp $
|
||||||
#
|
#
|
||||||
# Test escaping of special characters in the iteration values of a .for loop.
|
# Test escaping of special characters in the iteration values of a .for loop.
|
||||||
# These values get expanded later using the :U variable modifier, and this
|
# These values get expanded later using the :U variable modifier, and this
|
||||||
# escaping and unescaping must pass all characters and strings effectively
|
# escaping and unescaping must pass all characters and strings unmodified.
|
||||||
# unmodified.
|
|
||||||
|
# expect-all
|
||||||
|
|
||||||
.MAKEFLAGS: -df
|
.MAKEFLAGS: -df
|
||||||
|
|
||||||
|
@ -12,12 +13,14 @@
|
||||||
# This could be considered a bug.
|
# This could be considered a bug.
|
||||||
ASCII= !"\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
|
ASCII= !"\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
|
||||||
|
|
||||||
|
|
||||||
# XXX: As of 2020-12-31, the '#' is not preserved in the expanded body of
|
# XXX: As of 2020-12-31, the '#' is not preserved in the expanded body of
|
||||||
# the loop. Not only would it need the escaping for the variable modifier
|
# the loop. Not only would it need the escaping for the variable modifier
|
||||||
# ':U' but also the escaping for the line-end comment.
|
# ':U' but also the escaping for the line-end comment.
|
||||||
.for chars in ${ASCII}
|
.for chars in ${ASCII}
|
||||||
. info ${chars}
|
. info ${chars}
|
||||||
.endfor
|
.endfor
|
||||||
|
# expect-2: !"
|
||||||
|
|
||||||
# As of 2020-12-31, using 2 backslashes before be '#' would treat the '#'
|
# As of 2020-12-31, using 2 backslashes before be '#' would treat the '#'
|
||||||
# as comment character. Using 3 backslashes doesn't help either since
|
# as comment character. Using 3 backslashes doesn't help either since
|
||||||
|
@ -28,6 +31,7 @@ ASCII.2020-12-31= !"\\\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
|
||||||
.for chars in ${ASCII.2020-12-31}
|
.for chars in ${ASCII.2020-12-31}
|
||||||
. info ${chars}
|
. info ${chars}
|
||||||
.endfor
|
.endfor
|
||||||
|
# expect-2: !"\\
|
||||||
|
|
||||||
# Cover the code in ExprLen.
|
# Cover the code in ExprLen.
|
||||||
#
|
#
|
||||||
|
@ -42,6 +46,11 @@ VALUES= $$ $${V} $${V:=-with-modifier} $$(V) $$(V:=-with-modifier)
|
||||||
.for i in ${VALUES}
|
.for i in ${VALUES}
|
||||||
. info $i
|
. info $i
|
||||||
.endfor
|
.endfor
|
||||||
|
# expect-2: $
|
||||||
|
# expect-3: value
|
||||||
|
# expect-4: value-with-modifier
|
||||||
|
# expect-5: value
|
||||||
|
# expect-6: value-with-modifier
|
||||||
|
|
||||||
|
|
||||||
# Try to cover the code for nested '{}' in ExprLen, without success.
|
# Try to cover the code for nested '{}' in ExprLen, without success.
|
||||||
|
@ -112,6 +121,7 @@ VALUES= begin<$${UNDEF:Ufallback:N{{{}}}}>end
|
||||||
.for i in ${VALUES}
|
.for i in ${VALUES}
|
||||||
. info $i
|
. info $i
|
||||||
.endfor
|
.endfor
|
||||||
|
# expect-2: begin<fallback>end
|
||||||
|
|
||||||
# A single trailing dollar doesn't happen in practice.
|
# A single trailing dollar doesn't happen in practice.
|
||||||
# The dollar sign is correctly passed through to the body of the .for loop.
|
# The dollar sign is correctly passed through to the body of the .for loop.
|
||||||
|
@ -120,21 +130,23 @@ VALUES= begin<$${UNDEF:Ufallback:N{{{}}}}>end
|
||||||
.for i in ${:U\$}
|
.for i in ${:U\$}
|
||||||
. info ${i}
|
. info ${i}
|
||||||
.endfor
|
.endfor
|
||||||
|
# expect-2: $
|
||||||
|
|
||||||
# As of 2020-12-31, the name of the iteration variable can even contain
|
# Before for.c 1.173 from 2023-05-08, the name of the iteration variable
|
||||||
# colons, which then affects variable expressions having this exact modifier.
|
# could contain colons, which affected variable expressions having this exact
|
||||||
# This is clearly an unintended side effect of the implementation.
|
# modifier. This possibility was neither intended nor documented.
|
||||||
NUMBERS= one two three
|
NUMBERS= one two three
|
||||||
|
# expect+1: invalid character ':' in .for loop variable name
|
||||||
.for NUMBERS:M*e in replaced
|
.for NUMBERS:M*e in replaced
|
||||||
. info ${NUMBERS} ${NUMBERS:M*e}
|
. info ${NUMBERS} ${NUMBERS:M*e}
|
||||||
.endfor
|
.endfor
|
||||||
|
|
||||||
# As of 2020-12-31, the name of the iteration variable can contain braces,
|
# Before for.c 1.173 from 2023-05-08, the name of the iteration variable
|
||||||
# which gets even more surprising than colons, since it allows to replace
|
# could contain braces, which allowed to replace sequences of variable
|
||||||
# sequences of variable expressions. There is no practical use case for
|
# expressions. This possibility was neither intended nor documented.
|
||||||
# this, though.
|
|
||||||
BASENAME= one
|
BASENAME= one
|
||||||
EXT= .c
|
EXT= .c
|
||||||
|
# expect+1: invalid character '}' in .for loop variable name
|
||||||
.for BASENAME}${EXT in replaced
|
.for BASENAME}${EXT in replaced
|
||||||
. info ${BASENAME}${EXT}
|
. info ${BASENAME}${EXT}
|
||||||
.endfor
|
.endfor
|
||||||
|
@ -155,11 +167,23 @@ i,= comma
|
||||||
. info . $${i,}: ${i,}
|
. info . $${i,}: ${i,}
|
||||||
. info . adjacent: $i${i}${i:M*}$i
|
. info . adjacent: $i${i}${i:M*}$i
|
||||||
.endfor
|
.endfor
|
||||||
|
# expect-11: . $i: inner
|
||||||
|
# expect-11: . ${i}: inner
|
||||||
|
# expect-11: . ${i:M*}: inner
|
||||||
|
# expect-11: . $(i): inner
|
||||||
|
# expect-11: . $(i:M*): inner
|
||||||
|
# expect-11: . ${i${:U}}: outer
|
||||||
|
# expect-11: . ${i\}}: inner}
|
||||||
|
# expect-11: . ${i2}: two
|
||||||
|
# expect-11: . ${i,}: comma
|
||||||
|
# expect-11: . adjacent: innerinnerinnerinner
|
||||||
|
|
||||||
# The variable name can be a single '$' since there is no check on valid
|
# Before for.c 1.173 from 2023-05-08, the variable name could be a single '$'
|
||||||
# variable names. ForLoop_SubstVarShort skips "stupid" variable names though,
|
# since there was no check on valid variable names. ForLoop_SubstVarShort
|
||||||
# but ForLoop_SubstVarLong naively parses the body of the loop, substituting
|
# skipped "stupid" variable names though, but ForLoop_SubstVarLong naively
|
||||||
# each '${$}' with an actual 'dollar'.
|
# parsed the body of the loop, substituting each '${$}' with an actual
|
||||||
|
# '${:Udollar}'.
|
||||||
|
# expect+1: invalid character '$' in .for loop variable name
|
||||||
.for $ in dollar
|
.for $ in dollar
|
||||||
. info eight $$$$$$$$ and no cents.
|
. info eight $$$$$$$$ and no cents.
|
||||||
. info eight ${$}${$}${$}${$} and no cents.
|
. info eight ${$}${$}${$}${$} and no cents.
|
||||||
|
@ -171,6 +195,7 @@ i,= comma
|
||||||
# evaluates to an empty string.
|
# evaluates to an empty string.
|
||||||
closing-brace= } # guard against an
|
closing-brace= } # guard against an
|
||||||
${closing-brace}= <closing-brace> # alternative interpretation
|
${closing-brace}= <closing-brace> # alternative interpretation
|
||||||
|
# expect+1: eight and no cents.
|
||||||
.info eight ${$}${$}${$}${$} and no cents.
|
.info eight ${$}${$}${$}${$} and no cents.
|
||||||
|
|
||||||
# What happens if the values from the .for loop contain a literal newline?
|
# What happens if the values from the .for loop contain a literal newline?
|
||||||
|
@ -178,10 +203,18 @@ ${closing-brace}= <closing-brace> # alternative interpretation
|
||||||
# body of the .for loop, where it was then interpreted as a literal newline,
|
# body of the .for loop, where it was then interpreted as a literal newline,
|
||||||
# leading to syntax errors such as "Unclosed variable expression" in the upper
|
# leading to syntax errors such as "Unclosed variable expression" in the upper
|
||||||
# line and "Invalid line type" in the lower line.
|
# line and "Invalid line type" in the lower line.
|
||||||
|
#
|
||||||
|
# The error message occurs in the line of the .for loop since that's the place
|
||||||
|
# where the body of the .for loop is constructed, and at this point the
|
||||||
|
# newline character gets replaced with a plain space.
|
||||||
|
# expect+2: newline in .for value
|
||||||
|
# expect+1: newline in .for value
|
||||||
.for i in "${.newline}"
|
.for i in "${.newline}"
|
||||||
. info short: $i
|
. info short: $i
|
||||||
. info long: ${i}
|
. info long: ${i}
|
||||||
.endfor
|
.endfor
|
||||||
|
# expect-3: short: " "
|
||||||
|
# expect-3: long: " "
|
||||||
|
|
||||||
# No error since the newline character is not actually used.
|
# No error since the newline character is not actually used.
|
||||||
.for i in "${.newline}"
|
.for i in "${.newline}"
|
||||||
|
@ -193,6 +226,7 @@ ${closing-brace}= <closing-brace> # alternative interpretation
|
||||||
# loop is assembled, and at that point, ForLoop.nextItem had already been
|
# loop is assembled, and at that point, ForLoop.nextItem had already been
|
||||||
# advanced.
|
# advanced.
|
||||||
.MAKEFLAGS: -dp
|
.MAKEFLAGS: -dp
|
||||||
|
# expect+1: newline in .for value
|
||||||
.for i in "${.newline}"
|
.for i in "${.newline}"
|
||||||
: $i
|
: $i
|
||||||
.endfor
|
.endfor
|
||||||
|
|
|
@ -1,42 +1,41 @@
|
||||||
make: "directive-for.mk" line 108: outer
|
make: "directive-for.mk" line 119: outer
|
||||||
make: "directive-for.mk" line 133: a:\ a:\file.txt
|
make: "directive-for.mk" line 137: a:\ a:\file.txt
|
||||||
make: "directive-for.mk" line 133: d:\\
|
make: "directive-for.mk" line 137: d:\\
|
||||||
make: "directive-for.mk" line 133: d:\\file.txt
|
make: "directive-for.mk" line 137: d:\\file.txt
|
||||||
make: "directive-for.mk" line 140: ( ( (
|
make: "directive-for.mk" line 148: ( ( (
|
||||||
make: "directive-for.mk" line 140: [ [ [
|
make: "directive-for.mk" line 148: [ [ [
|
||||||
make: "directive-for.mk" line 140: { { {
|
make: "directive-for.mk" line 148: { { {
|
||||||
make: "directive-for.mk" line 140: ) ) )
|
make: "directive-for.mk" line 148: ) ) )
|
||||||
make: "directive-for.mk" line 140: ] ] ]
|
make: "directive-for.mk" line 148: ] ] ]
|
||||||
make: "directive-for.mk" line 140: } } }
|
make: "directive-for.mk" line 148: } } }
|
||||||
make: "directive-for.mk" line 140: (()) (()) (())
|
make: "directive-for.mk" line 148: (()) (()) (())
|
||||||
make: "directive-for.mk" line 140: [[]] [[]] [[]]
|
make: "directive-for.mk" line 148: [[]] [[]] [[]]
|
||||||
make: "directive-for.mk" line 140: {{}} {{}} {{}}
|
make: "directive-for.mk" line 148: {{}} {{}} {{}}
|
||||||
make: "directive-for.mk" line 140: )( )( )(
|
make: "directive-for.mk" line 148: )( )( )(
|
||||||
make: "directive-for.mk" line 140: ][ ][ ][
|
make: "directive-for.mk" line 148: ][ ][ ][
|
||||||
make: "directive-for.mk" line 140: }{ }{ }{
|
make: "directive-for.mk" line 148: }{ }{ }{
|
||||||
make: "directive-for.mk" line 148: outer value value
|
make: "directive-for.mk" line 168: invalid character ':' in .for loop variable name
|
||||||
make: "directive-for.mk" line 148: outer "quoted" \"quoted\"
|
make: "directive-for.mk" line 175: invalid character '$' in .for loop variable name
|
||||||
make: "directive-for.mk" line 154: Unknown modifier "Z"
|
make: "directive-for.mk" line 187: invalid character '$' in .for loop variable name
|
||||||
make: "directive-for.mk" line 155: XXX: Not reached word1
|
make: "directive-for.mk" line 198: Unknown modifier "Z"
|
||||||
make: "directive-for.mk" line 155: XXX: Not reached word3
|
make: "directive-for.mk" line 199: XXX: Not reached word1
|
||||||
make: "directive-for.mk" line 160: no iteration variables in for
|
make: "directive-for.mk" line 199: XXX: Not reached word3
|
||||||
make: "directive-for.mk" line 162: Missing argument for ".error"
|
make: "directive-for.mk" line 206: no iteration variables in for
|
||||||
make: "directive-for.mk" line 163: for-less endfor
|
make: "directive-for.mk" line 232: 1 open conditional
|
||||||
make: "directive-for.mk" line 187: 1 open conditional
|
make: "directive-for.mk" line 248: for-less endfor
|
||||||
make: "directive-for.mk" line 203: for-less endfor
|
make: "directive-for.mk" line 249: if-less endif
|
||||||
make: "directive-for.mk" line 204: if-less endif
|
make: "directive-for.mk" line 257: if-less endif
|
||||||
make: "directive-for.mk" line 212: if-less endif
|
For: new loop 2
|
||||||
|
For: end for 2
|
||||||
For: end for 1
|
For: end for 1
|
||||||
For: loop body:
|
For: loop body:
|
||||||
.\
|
.\
|
||||||
for inner in i
|
for inner in i
|
||||||
.\
|
.\
|
||||||
endfor
|
endfor
|
||||||
make: "directive-for.mk" line 229: Unexpected end of file in .for loop
|
For: end for 1
|
||||||
For: loop body:
|
For: loop body:
|
||||||
.\
|
make: "directive-for.mk" line 305: newline-item=(a)
|
||||||
endfor
|
|
||||||
make: "directive-for.mk" line 227: for-less endfor
|
|
||||||
make: Fatal errors encountered -- cannot continue
|
make: Fatal errors encountered -- cannot continue
|
||||||
make: stopped in unit-tests
|
make: stopped in unit-tests
|
||||||
exit status 1
|
exit status 1
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# $NetBSD: directive-for.mk,v 1.15 2022/10/01 09:23:04 rillig Exp $
|
# $NetBSD: directive-for.mk,v 1.20 2023/05/10 13:03:06 rillig Exp $
|
||||||
#
|
#
|
||||||
# Tests for the .for directive.
|
# Tests for the .for directive.
|
||||||
#
|
#
|
||||||
|
@ -8,11 +8,15 @@
|
||||||
# .for _FILE_ in values
|
# .for _FILE_ in values
|
||||||
# .for .FILE. in values
|
# .for .FILE. in values
|
||||||
# .for _f_ in values
|
# .for _f_ in values
|
||||||
|
|
||||||
# Using the .for loop, lists of values can be produced.
|
|
||||||
# In simple cases, the :@var@${var}@ variable modifier can be used to
|
|
||||||
# achieve the same effects.
|
|
||||||
#
|
#
|
||||||
|
# See also:
|
||||||
|
# varmod-loop.mk The ':@var@...@' modifier
|
||||||
|
|
||||||
|
# expect-all
|
||||||
|
|
||||||
|
# A typical use case for a .for loop is to populate a variable with a list of
|
||||||
|
# values depending on other variables. In simple cases, the same effect can
|
||||||
|
# be achieved using the ':@var@${var}@' modifier.
|
||||||
.undef NUMBERS
|
.undef NUMBERS
|
||||||
.for num in 1 2 3
|
.for num in 1 2 3
|
||||||
NUMBERS+= ${num}
|
NUMBERS+= ${num}
|
||||||
|
@ -21,8 +25,9 @@ NUMBERS+= ${num}
|
||||||
. error
|
. error
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
|
||||||
# The .for loop also works for multiple iteration variables.
|
# The .for loop also works for multiple iteration variables.
|
||||||
# This is something that the variable modifier :@ cannot do.
|
# This is something that the modifier :@ cannot do.
|
||||||
.for name value in VARNAME value NAME2 value2
|
.for name value in VARNAME value NAME2 value2
|
||||||
${name}= ${value}
|
${name}= ${value}
|
||||||
.endfor
|
.endfor
|
||||||
|
@ -30,12 +35,12 @@ ${name}= ${value}
|
||||||
. error
|
. error
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
|
||||||
# The .for loop splits the items at whitespace, taking quotes into account,
|
# The .for loop splits the items at whitespace, taking quotes into account,
|
||||||
# just like the :M or :S variable modifiers.
|
# just like the :M or :S modifiers.
|
||||||
#
|
|
||||||
# Until 2012-06-03, it had split the items exactly at whitespace, without
|
|
||||||
# taking the quotes into account. This had resulted in 10 words.
|
|
||||||
#
|
#
|
||||||
|
# Until 2012-06-03, the .for loop had split the items exactly at whitespace,
|
||||||
|
# without taking the quotes into account. This had resulted in 10 words.
|
||||||
.undef WORDS
|
.undef WORDS
|
||||||
.for var in one t\ w\ o "three three" 'four four' `five six`
|
.for var in one t\ w\ o "three three" 'four four' `five six`
|
||||||
WORDS+= counted
|
WORDS+= counted
|
||||||
|
@ -44,16 +49,19 @@ WORDS+= counted
|
||||||
. error
|
. error
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
|
||||||
# In the body of the .for loop, the iteration variables can be accessed
|
# In the body of the .for loop, the iteration variables can be accessed
|
||||||
# like normal variables, even though they are not really variables.
|
# like normal variables, even though they are not really variables.
|
||||||
#
|
#
|
||||||
# Instead, the expression ${var} is transformed into ${:U1}, ${:U2} and so
|
# Instead, before interpreting the body of the .for loop, the body is
|
||||||
# on, before the loop body is evaluated.
|
# generated by replacing each expression ${var} with ${:U1}, ${:U2} and so
|
||||||
|
# on.
|
||||||
#
|
#
|
||||||
# A notable effect of this implementation technique is that the .for
|
# A noticeable effect of this implementation technique is that the .for
|
||||||
# iteration variables and the normal global variables live in separate
|
# iteration variables and the normal global variables live in separate
|
||||||
# namespaces and do not influence each other.
|
# namespaces and do not influence each other. The "scope" of the .for loop
|
||||||
#
|
# variables is restricted to the current makefile, it does not reach over to
|
||||||
|
# any included makefiles.
|
||||||
var= value before
|
var= value before
|
||||||
var2= value before
|
var2= value before
|
||||||
.for var var2 in 1 2 3 4
|
.for var var2 in 1 2 3 4
|
||||||
|
@ -66,9 +74,8 @@ var2= value before
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
# Everything from the paragraph above also applies if the loop body is
|
# Everything from the paragraph above also applies if the loop body is
|
||||||
# empty, even if there is no actual iteration since the loop items are
|
# empty. In this particular example, the items to be iterated are empty as
|
||||||
# also empty.
|
# well.
|
||||||
#
|
|
||||||
var= value before
|
var= value before
|
||||||
var2= value before
|
var2= value before
|
||||||
.for var var2 in ${:U}
|
.for var var2 in ${:U}
|
||||||
|
@ -82,11 +89,13 @@ var2= value before
|
||||||
|
|
||||||
# Until 2008-12-21, the values of the iteration variables were simply
|
# Until 2008-12-21, the values of the iteration variables were simply
|
||||||
# inserted as plain text and then parsed as usual, which made it possible
|
# inserted as plain text and then parsed as usual, which made it possible
|
||||||
# to achieve all kinds of strange effects.
|
# to achieve all kinds of strange effects, such as generating '.if'
|
||||||
|
# directives or inserting '$' characters in random places, thereby changing
|
||||||
|
# how following '$' are interpreted.
|
||||||
#
|
#
|
||||||
# Before that date, the .for loop expanded to:
|
# Before that date, the .for loop below expanded to:
|
||||||
# EXPANSION+= value
|
# EXPANSION+= value
|
||||||
# Since that date, the .for loop expands to:
|
# Since that date, the .for loop below expands to:
|
||||||
# EXPANSION${:U+}= value
|
# EXPANSION${:U+}= value
|
||||||
#
|
#
|
||||||
EXPANSION= before
|
EXPANSION= before
|
||||||
|
@ -102,13 +111,16 @@ EXPANSION${plus}= value
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
# When the outer .for loop is expanded, it sees the expression ${i} and
|
# When the outer .for loop is expanded, it sees the expression ${i} and
|
||||||
# expands it. The inner loop then has nothing more to expand.
|
# expands it. The inner loop then only sees the expression ${:Uouter} and
|
||||||
|
# has nothing more to expand.
|
||||||
.for i in outer
|
.for i in outer
|
||||||
. for i in inner
|
. for i in inner
|
||||||
|
# expect+1: outer
|
||||||
. info ${i}
|
. info ${i}
|
||||||
. endfor
|
. endfor
|
||||||
.endfor
|
.endfor
|
||||||
|
|
||||||
|
|
||||||
# From https://gnats.netbsd.org/29985.
|
# From https://gnats.netbsd.org/29985.
|
||||||
#
|
#
|
||||||
# Until 2008-12-21, the .for loop was expanded by replacing the variable
|
# Until 2008-12-21, the .for loop was expanded by replacing the variable
|
||||||
|
@ -121,17 +133,13 @@ EXPANSION${plus}= value
|
||||||
# like "a:\ a:\file.txt" that ended in a single backslash. Since then, the
|
# like "a:\ a:\file.txt" that ended in a single backslash. Since then, the
|
||||||
# variable values have been replaced with expressions of the form ${:U...},
|
# variable values have been replaced with expressions of the form ${:U...},
|
||||||
# which are not interpreted as code anymore.
|
# which are not interpreted as code anymore.
|
||||||
#
|
|
||||||
# As of 2020-09-22, a comment in for.c says that it may be possible to
|
|
||||||
# produce an "unwanted substitution", but there is no demonstration code yet.
|
|
||||||
#
|
|
||||||
# The above changes prevent a backslash at the end of a word from being
|
|
||||||
# interpreted as part of the code. Because of this, the trailingBackslash
|
|
||||||
# hack in Var_Subst is no longer needed and as of 2020-09-22, has been
|
|
||||||
# removed.
|
|
||||||
.for path in a:\ a:\file.txt d:\\ d:\\file.txt
|
.for path in a:\ a:\file.txt d:\\ d:\\file.txt
|
||||||
. info ${path}
|
. info ${path}
|
||||||
.endfor
|
.endfor
|
||||||
|
# expect-2: a:\ a:\file.txt
|
||||||
|
# expect-3: d:\\
|
||||||
|
# expect-4: d:\\file.txt
|
||||||
|
|
||||||
|
|
||||||
# Ensure that braces and parentheses are properly escaped by the .for loop.
|
# Ensure that braces and parentheses are properly escaped by the .for loop.
|
||||||
# Each line must print the same word 3 times.
|
# Each line must print the same word 3 times.
|
||||||
|
@ -139,28 +147,65 @@ EXPANSION${plus}= value
|
||||||
.for v in ( [ { ) ] } (()) [[]] {{}} )( ][ }{
|
.for v in ( [ { ) ] } (()) [[]] {{}} )( ][ }{
|
||||||
. info $v ${v} $(v)
|
. info $v ${v} $(v)
|
||||||
.endfor
|
.endfor
|
||||||
|
# expect-02: ( ( (
|
||||||
|
# expect-03: [ [ [
|
||||||
|
# expect-04: { { {
|
||||||
|
# expect-05: ) ) )
|
||||||
|
# expect-06: ] ] ]
|
||||||
|
# expect-07: } } }
|
||||||
|
# expect-08: (()) (()) (())
|
||||||
|
# expect-09: [[]] [[]] [[]]
|
||||||
|
# expect-10: {{}} {{}} {{}}
|
||||||
|
# expect-11: )( )( )(
|
||||||
|
# expect-12: ][ ][ ][
|
||||||
|
# expect-13: }{ }{ }{
|
||||||
|
|
||||||
# As of 2020-10-25, the variable names may contain arbitrary characters,
|
# Before 2023-05-09, the variable names could contain arbitrary characters,
|
||||||
# except for whitespace. This allows for creative side effects. Hopefully
|
# except for whitespace, allowing for creative side effects, as usual for
|
||||||
# nobody is misusing this "feature".
|
# arbitrary code injection.
|
||||||
var= outer
|
var= outer
|
||||||
|
# expect+1: invalid character ':' in .for loop variable name
|
||||||
.for var:Q in value "quoted"
|
.for var:Q in value "quoted"
|
||||||
. info ${var} ${var:Q} ${var:Q:Q}
|
. info <${var}> <${var:Q}> <${var:Q:Q}>
|
||||||
|
.endfor
|
||||||
|
|
||||||
|
# Before 2023-05-09, when variable names could contain '$', the short
|
||||||
|
# expression '$$' was preserved, the long expressions were substituted.
|
||||||
|
# expect+1: invalid character '$' in .for loop variable name
|
||||||
|
.for $ in value
|
||||||
|
. info <$$> <${$}> <$($)>
|
||||||
|
.endfor
|
||||||
|
|
||||||
|
|
||||||
|
# https://gnats.netbsd.org/53146 mentions the idea of using a dynamic
|
||||||
|
# variable name in .for loops, based on some other variable. The .for loops
|
||||||
|
# are already tricky enough to understand in detail, even without this
|
||||||
|
# possibility, therefore the variable names are restricted to using harmless
|
||||||
|
# characters only.
|
||||||
|
INDIRECT= direct
|
||||||
|
# expect+1: invalid character '$' in .for loop variable name
|
||||||
|
.for $(INDIRECT) in value
|
||||||
|
# If the variable name could be chosen dynamically, the iteration variable
|
||||||
|
# might have been 'direct', thereby expanding the expression '${direct}'.
|
||||||
|
. info <$(INDIRECT)> <$(direct)> <$($(INDIRECT))>
|
||||||
.endfor
|
.endfor
|
||||||
|
|
||||||
|
|
||||||
# XXX: A parse error or evaluation error in the items of the .for loop
|
# XXX: A parse error or evaluation error in the items of the .for loop
|
||||||
# should skip the whole loop. As of 2020-12-27, the loop is expanded twice.
|
# should skip the whole loop. As of 2023-05-09, the loop is expanded as
|
||||||
|
# usual.
|
||||||
|
# expect+1: Unknown modifier "Z"
|
||||||
.for var in word1 ${:Uword2:Z} word3
|
.for var in word1 ${:Uword2:Z} word3
|
||||||
. info XXX: Not reached ${var}
|
. info XXX: Not reached ${var}
|
||||||
.endfor
|
.endfor
|
||||||
|
# expect-2: XXX: Not reached word1
|
||||||
|
# expect-3: XXX: Not reached word3
|
||||||
|
|
||||||
|
|
||||||
# An empty list of variables to the left of the 'in' is a parse error.
|
# An empty list of variables to the left of the 'in' is a parse error.
|
||||||
.for in value # expect+0: no iteration variables in for
|
.for in value # expect+0: no iteration variables in for
|
||||||
# XXX: The loop body is evaluated once, even with the parse error above.
|
. error
|
||||||
. error # expect+0: Missing argument for ".error"
|
.endfor
|
||||||
.endfor # expect+0: for-less endfor
|
|
||||||
|
|
||||||
# An empty list of iteration values to the right of the 'in' is accepted.
|
# An empty list of iteration values to the right of the 'in' is accepted.
|
||||||
# Unlike in the shell, it is not a parse error.
|
# Unlike in the shell, it is not a parse error.
|
||||||
|
@ -214,12 +259,19 @@ var= outer
|
||||||
.endif # no 'if-less endif'
|
.endif # no 'if-less endif'
|
||||||
|
|
||||||
|
|
||||||
# When make parses a .for loop, it assumes that there is no line break between
|
# Before for.c 1.172 from 2023-05-08, when make parsed a .for loop, it
|
||||||
# the '.' and the 'for' or 'endfor', as there is no practical reason to break
|
# assumed that there was no line continuation between the '.' and the 'for'
|
||||||
# the line at this point. When make scans the outer .for loop, it does not
|
# or 'endfor', as there is no practical reason to break the line at this
|
||||||
# recognize the inner directives as such. When make scans the inner .for
|
# point.
|
||||||
# loop, it recognizes the '.\n for' but does not recognize the '.\n endfor',
|
#
|
||||||
# as LK_FOR_BODY preserves the backslash-newline sequences.
|
# When make scanned the outer .for loop, it did not recognize the inner .for
|
||||||
|
# loop as such and instead treated it as an unknown directive. The body of
|
||||||
|
# the outer .for loop thus ended above the '.endfor'.
|
||||||
|
#
|
||||||
|
# When make scanned the inner .for loop, it did not recognize the inner
|
||||||
|
# .endfor as such, which led to a parse error 'Unexpected end of file in .for
|
||||||
|
# loop' from the '.endfor' line, followed by a second parse error 'for-less
|
||||||
|
# .endfor' from the '.\\n endfor' line.
|
||||||
.MAKEFLAGS: -df
|
.MAKEFLAGS: -df
|
||||||
.for outer in o
|
.for outer in o
|
||||||
.\
|
.\
|
||||||
|
@ -244,3 +296,12 @@ var= outer
|
||||||
. error
|
. error
|
||||||
. endif
|
. endif
|
||||||
.endfor
|
.endfor
|
||||||
|
|
||||||
|
|
||||||
|
# Since at least 1993, iteration stops at the first newline.
|
||||||
|
# Back then, the .newline variable didn't exist, therefore it was unlikely
|
||||||
|
# that a newline ever occurred.
|
||||||
|
.for var in a${.newline}b${.newline}c
|
||||||
|
. info newline-item=(${var})
|
||||||
|
.endfor
|
||||||
|
# expect-2: newline-item=(a)
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
make: "forloop.mk" line 14: x=one
|
|
||||||
make: "forloop.mk" line 14: x="two and three"
|
|
||||||
make: "forloop.mk" line 14: x=four
|
|
||||||
make: "forloop.mk" line 14: x="five"
|
|
||||||
make: "forloop.mk" line 20: x=-I/this
|
|
||||||
make: "forloop.mk" line 20: x=-I"This or that"
|
|
||||||
make: "forloop.mk" line 20: x=-Ithat
|
|
||||||
make: "forloop.mk" line 20: x="-DTHIS=\"this and that\""
|
|
||||||
make: "forloop.mk" line 27: cfl=-I/this -I"This or that" -Ithat "-DTHIS=\"this and that\""
|
|
||||||
make: "forloop.mk" line 41: newline-item=(a)
|
|
||||||
make: "forloop.mk" line 47: a=one b="two and three"
|
|
||||||
make: "forloop.mk" line 47: a=four b="five"
|
|
||||||
make: "forloop.mk" line 47: a=ONE b="TWO AND THREE"
|
|
||||||
make: "forloop.mk" line 47: a=FOUR b="FIVE"
|
|
||||||
We expect an error next:
|
|
||||||
make: "forloop.mk" line 46: Wrong number of words (9) in .for substitution list with 2 variables
|
|
||||||
make: Fatal errors encountered -- cannot continue
|
|
||||||
make: stopped in unit-tests
|
|
||||||
OK
|
|
||||||
exit status 0
|
|
|
@ -1,53 +0,0 @@
|
||||||
# $NetBSD: forloop.mk,v 1.7 2020/11/03 17:37:57 rillig Exp $
|
|
||||||
|
|
||||||
all: for-loop
|
|
||||||
|
|
||||||
LIST= one "two and three" four "five"
|
|
||||||
|
|
||||||
.if make(for-fail)
|
|
||||||
for-fail:
|
|
||||||
|
|
||||||
XTRA_LIST= xtra
|
|
||||||
.else
|
|
||||||
|
|
||||||
. for x in ${LIST}
|
|
||||||
. info x=$x
|
|
||||||
. endfor
|
|
||||||
|
|
||||||
CFL= -I/this -I"This or that" -Ithat "-DTHIS=\"this and that\""
|
|
||||||
cfl=
|
|
||||||
. for x in ${CFL}
|
|
||||||
. info x=$x
|
|
||||||
. if empty(cfl)
|
|
||||||
cfl= $x
|
|
||||||
. else
|
|
||||||
cfl+= $x
|
|
||||||
. endif
|
|
||||||
. endfor
|
|
||||||
. info cfl=${cfl}
|
|
||||||
|
|
||||||
. if ${cfl} != ${CFL}
|
|
||||||
. error ${.newline}${cfl} != ${.newline}${CFL}
|
|
||||||
. endif
|
|
||||||
|
|
||||||
. for a b in ${EMPTY}
|
|
||||||
. info a=$a b=$b
|
|
||||||
. endfor
|
|
||||||
|
|
||||||
# Since at least 1993, iteration stops at the first newline.
|
|
||||||
# Back then, the .newline variable didn't exist, therefore it was unlikely
|
|
||||||
# that a newline ever occurred.
|
|
||||||
. for var in a${.newline}b${.newline}c
|
|
||||||
. info newline-item=(${var})
|
|
||||||
. endfor
|
|
||||||
|
|
||||||
.endif # for-fail
|
|
||||||
|
|
||||||
.for a b in ${LIST} ${LIST:tu} ${XTRA_LIST}
|
|
||||||
. info a=$a b=$b
|
|
||||||
.endfor
|
|
||||||
|
|
||||||
for-loop:
|
|
||||||
@echo We expect an error next:
|
|
||||||
@(cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} for-fail) && \
|
|
||||||
{ echo "Oops that should have failed!"; exit 1; } || echo OK
|
|
|
@ -1,4 +1,4 @@
|
||||||
# $NetBSD: parse.mk,v 1.3 2022/07/24 20:25:23 rillig Exp $
|
# $NetBSD: parse.mk,v 1.4 2023/04/28 13:09:48 rillig Exp $
|
||||||
#
|
#
|
||||||
# Test those parts of the parsing that do not belong in any of the other
|
# Test those parts of the parsing that do not belong in any of the other
|
||||||
# categories.
|
# categories.
|
||||||
|
@ -22,3 +22,33 @@
|
||||||
#
|
#
|
||||||
# https://bugs.freebsd.org/265119
|
# https://bugs.freebsd.org/265119
|
||||||
one-target ${:U }
|
one-target ${:U }
|
||||||
|
|
||||||
|
|
||||||
|
# Since parse.c 1.656 from 2022-01-27 and before parse.c 1.662 from
|
||||||
|
# 2022-02-05, there was an out-of-bounds read in Parse_IsVar when looking for
|
||||||
|
# a variable assignment in a dependency line with trailing whitespace. Lines
|
||||||
|
# without trailing whitespace were not affected. Global variable assignments
|
||||||
|
# were guaranteed to have no trailing whitespace and were thus not affected.
|
||||||
|
#
|
||||||
|
# Try to reproduce some variants that may lead to a crash, depending on the
|
||||||
|
# memory allocator. To get a crash, the terminating '\0' of the line must be
|
||||||
|
# the last byte of a memory page. The expression '${:U}' forces this trailing
|
||||||
|
# whitespace.
|
||||||
|
|
||||||
|
# On FreeBSD x86_64, a crash could in some cases be forced using the following
|
||||||
|
# line, which has length 47, and if the memory for the expanded line starts at
|
||||||
|
# 0xXXXX_XXd0, the terminating '\0' may end up at 0xXXXX_Xfff:
|
||||||
|
Try_to_crash_FreeBSD.xxxxxxxxxxxxxxxxxx: 12345 ${:U}
|
||||||
|
|
||||||
|
# The following line has length 4095 after being expanded, so line[4095] ==
|
||||||
|
# '\0'. If the line is
|
||||||
|
# allocated on a page boundary and the following page is not mapped, this line
|
||||||
|
# leads to a segmentation fault.
|
||||||
|
${:U:range=511:@_@1234567@:ts.}: 12345 ${:U}
|
||||||
|
|
||||||
|
# The following line has length 8191, so line[8191] == '\0'. If the line is
|
||||||
|
# allocated on a page boundary and the following page is not mapped, this line
|
||||||
|
# leads to a segmentation fault.
|
||||||
|
${:U:range=1023:@_@1234567@:ts.}: 12345 ${:U}
|
||||||
|
|
||||||
|
12345:
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
make: "var-eval-short.mk" line 44: In the :@ modifier of "", the variable name "${FAIL}" must not contain a dollar
|
make: "var-eval-short.mk" line 44: In the :@ modifier of "", the variable name "${FAIL}" must not contain a dollar
|
||||||
make: "var-eval-short.mk" line 44: Malformed conditional (0 && ${:Uword:@${FAIL}@expr@})
|
make: "var-eval-short.mk" line 44: Malformed conditional (0 && ${:Uword:@${FAIL}@expr@})
|
||||||
make: "var-eval-short.mk" line 84: Invalid time value at "${FAIL}}"
|
|
||||||
make: "var-eval-short.mk" line 84: Malformed conditional (0 && ${:Uword:gmtime=${FAIL}})
|
|
||||||
make: "var-eval-short.mk" line 98: Invalid time value at "${FAIL}}"
|
|
||||||
make: "var-eval-short.mk" line 98: Malformed conditional (0 && ${:Uword:localtime=${FAIL}})
|
|
||||||
CondParser_Eval: 0 && ${0:?${FAIL}then:${FAIL}else}
|
CondParser_Eval: 0 && ${0:?${FAIL}then:${FAIL}else}
|
||||||
Var_Parse: ${0:?${FAIL}then:${FAIL}else} (parse-only)
|
Var_Parse: ${0:?${FAIL}then:${FAIL}else} (parse-only)
|
||||||
Parsing modifier ${0:?...}
|
Parsing modifier ${0:?...}
|
||||||
|
@ -12,7 +8,7 @@ Modifier part: "${FAIL}then"
|
||||||
Var_Parse: ${FAIL}else} (parse-only)
|
Var_Parse: ${FAIL}else} (parse-only)
|
||||||
Modifier part: "${FAIL}else"
|
Modifier part: "${FAIL}else"
|
||||||
Result of ${0:?${FAIL}then:${FAIL}else} is "" (parse-only, defined)
|
Result of ${0:?${FAIL}then:${FAIL}else} is "" (parse-only, defined)
|
||||||
Parsing line 163: DEFINED= defined
|
Parsing line 165: DEFINED= defined
|
||||||
Global: DEFINED = defined
|
Global: DEFINED = defined
|
||||||
CondParser_Eval: 0 && ${DEFINED:L:?${FAIL}then:${FAIL}else}
|
CondParser_Eval: 0 && ${DEFINED:L:?${FAIL}then:${FAIL}else}
|
||||||
Var_Parse: ${DEFINED:L:?${FAIL}then:${FAIL}else} (parse-only)
|
Var_Parse: ${DEFINED:L:?${FAIL}then:${FAIL}else} (parse-only)
|
||||||
|
@ -24,7 +20,7 @@ Modifier part: "${FAIL}then"
|
||||||
Var_Parse: ${FAIL}else} (parse-only)
|
Var_Parse: ${FAIL}else} (parse-only)
|
||||||
Modifier part: "${FAIL}else"
|
Modifier part: "${FAIL}else"
|
||||||
Result of ${DEFINED:?${FAIL}then:${FAIL}else} is "defined" (parse-only, regular)
|
Result of ${DEFINED:?${FAIL}then:${FAIL}else} is "defined" (parse-only, regular)
|
||||||
Parsing line 166: .MAKEFLAGS: -d0
|
Parsing line 168: .MAKEFLAGS: -d0
|
||||||
ParseDependency(.MAKEFLAGS: -d0)
|
ParseDependency(.MAKEFLAGS: -d0)
|
||||||
Global: .MAKEFLAGS = -r -k -d cpv -d
|
Global: .MAKEFLAGS = -r -k -d cpv -d
|
||||||
Global: .MAKEFLAGS = -r -k -d cpv -d 0
|
Global: .MAKEFLAGS = -r -k -d cpv -d 0
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# $NetBSD: var-eval-short.mk,v 1.8 2021/12/27 18:54:19 rillig Exp $
|
# $NetBSD: var-eval-short.mk,v 1.9 2023/05/09 16:27:00 rillig Exp $
|
||||||
#
|
#
|
||||||
# Tests for each variable modifier to ensure that they only do the minimum
|
# Tests for each variable modifier to ensure that they only do the minimum
|
||||||
# necessary computations. If the result of the expression is irrelevant,
|
# necessary computations. If the result of the expression is irrelevant,
|
||||||
|
@ -79,8 +79,9 @@ DEFINED= # defined
|
||||||
.if 0 && ${:Uword:E}
|
.if 0 && ${:Uword:E}
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
# As of 2021-03-14, the error 'Invalid time value: ${FAIL}}' is ok since
|
# Before var.c 1.1050 from 2023-05-09, the ':gmtime' modifier produced the
|
||||||
# ':gmtime' does not expand its argument.
|
# error message 'Invalid time value: ${FAIL}}' since it did not expand its
|
||||||
|
# argument.
|
||||||
.if 0 && ${:Uword:gmtime=${FAIL}}
|
.if 0 && ${:Uword:gmtime=${FAIL}}
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
@ -93,8 +94,9 @@ DEFINED= # defined
|
||||||
.if 0 && ${value:L}
|
.if 0 && ${value:L}
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
# As of 2021-03-14, the error 'Invalid time value: ${FAIL}}' is ok since
|
# Before var.c 1.1050 from 2023-05-09, the ':localtime' modifier produced the
|
||||||
# ':localtime' does not expand its argument.
|
# error message 'Invalid time value: ${FAIL}}' since it did not expand its
|
||||||
|
# argument.
|
||||||
.if 0 && ${:Uword:localtime=${FAIL}}
|
.if 0 && ${:Uword:localtime=${FAIL}}
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
Global: .ALLTARGETS = one
|
Global: .ALLTARGETS = all target-rule.ext dir/subdir/target-rule.ext target-rule.ir-gen-from dir/subdir/target-rule-dir.ir-gen-from inference-rule.ir-to dir/subdir/inference-rule.ir-to inference-rule.ir-from dir/subdir/inference-rule.ir-from inference-rule-chain.ir-to dir/subdir/inference-rule-chain.ir-to inference-rule-chain.ir-gen-from dir/subdir/inference-rule-chain.ir-gen-from one
|
||||||
Global: .ALLTARGETS = one two
|
Global: .ALLTARGETS = all target-rule.ext dir/subdir/target-rule.ext target-rule.ir-gen-from dir/subdir/target-rule-dir.ir-gen-from inference-rule.ir-to dir/subdir/inference-rule.ir-to inference-rule.ir-from dir/subdir/inference-rule.ir-from inference-rule-chain.ir-to dir/subdir/inference-rule-chain.ir-to inference-rule-chain.ir-gen-from dir/subdir/inference-rule-chain.ir-gen-from one two
|
||||||
Var_Parse: ${.MAKE.TARGET_LOCAL_VARIABLES} (eval)
|
Var_Parse: ${.MAKE.TARGET_LOCAL_VARIABLES} (eval)
|
||||||
Var_SetExpand: variable name "" expands to empty string, with value "three" - ignored
|
Var_SetExpand: variable name "" expands to empty string, with value "three" - ignored
|
||||||
Var_SetExpand: variable name "" expands to empty string, with value "three" - ignored
|
Var_SetExpand: variable name "" expands to empty string, with value "three" - ignored
|
||||||
|
@ -7,6 +7,56 @@ Global: one two = # (empty)
|
||||||
Global: one two = three
|
Global: one two = three
|
||||||
Global: .MAKEFLAGS = -r -k -d v -d
|
Global: .MAKEFLAGS = -r -k -d v -d
|
||||||
Global: .MAKEFLAGS = -r -k -d v -d 0
|
Global: .MAKEFLAGS = -r -k -d v -d 0
|
||||||
|
target-rule.ext: @ = <target-rule.ext>
|
||||||
|
target-rule.ext: % = <undefined>
|
||||||
|
target-rule.ext: ? = <>
|
||||||
|
target-rule.ext: < = <undefined>
|
||||||
|
target-rule.ext: * = <target-rule.ext>
|
||||||
|
dir/subdir/target-rule.ext: @ = <dir/subdir/target-rule.ext>
|
||||||
|
dir/subdir/target-rule.ext: % = <undefined>
|
||||||
|
dir/subdir/target-rule.ext: ? = <>
|
||||||
|
dir/subdir/target-rule.ext: < = <undefined>
|
||||||
|
dir/subdir/target-rule.ext: * = <dir/subdir/target-rule.ext>
|
||||||
|
target-rule.ir-gen-from: @ = <target-rule.ir-gen-from>
|
||||||
|
target-rule.ir-gen-from: % = <undefined>
|
||||||
|
target-rule.ir-gen-from: ? = <>
|
||||||
|
target-rule.ir-gen-from: < = <undefined>
|
||||||
|
target-rule.ir-gen-from: * = <target-rule>
|
||||||
|
dir/subdir/target-rule-dir.ir-gen-from: @ = <dir/subdir/target-rule-dir.ir-gen-from>
|
||||||
|
dir/subdir/target-rule-dir.ir-gen-from: % = <undefined>
|
||||||
|
dir/subdir/target-rule-dir.ir-gen-from: ? = <>
|
||||||
|
dir/subdir/target-rule-dir.ir-gen-from: < = <undefined>
|
||||||
|
dir/subdir/target-rule-dir.ir-gen-from: * = <dir/subdir/target-rule-dir>
|
||||||
|
inference-rule.ir-to: @ = <inference-rule.ir-to>
|
||||||
|
inference-rule.ir-to: % = <undefined>
|
||||||
|
inference-rule.ir-to: ? = <inference-rule.ir-from>
|
||||||
|
inference-rule.ir-to: < = <inference-rule.ir-from>
|
||||||
|
inference-rule.ir-to: * = <inference-rule>
|
||||||
|
dir/subdir/inference-rule.ir-to: @ = <dir/subdir/inference-rule.ir-to>
|
||||||
|
dir/subdir/inference-rule.ir-to: % = <undefined>
|
||||||
|
dir/subdir/inference-rule.ir-to: ? = <dir/subdir/inference-rule.ir-from>
|
||||||
|
dir/subdir/inference-rule.ir-to: < = <dir/subdir/inference-rule.ir-from>
|
||||||
|
dir/subdir/inference-rule.ir-to: * = <dir/subdir/inference-rule>
|
||||||
|
inference-rule-chain.ir-from: @ = <inference-rule-chain.ir-from>
|
||||||
|
inference-rule-chain.ir-from: % = <undefined>
|
||||||
|
inference-rule-chain.ir-from: ? = <inference-rule-chain.ir-gen-from>
|
||||||
|
inference-rule-chain.ir-from: < = <inference-rule-chain.ir-gen-from>
|
||||||
|
inference-rule-chain.ir-from: * = <inference-rule-chain>
|
||||||
|
inference-rule-chain.ir-to: @ = <inference-rule-chain.ir-to>
|
||||||
|
inference-rule-chain.ir-to: % = <undefined>
|
||||||
|
inference-rule-chain.ir-to: ? = <inference-rule-chain.ir-from>
|
||||||
|
inference-rule-chain.ir-to: < = <inference-rule-chain.ir-from>
|
||||||
|
inference-rule-chain.ir-to: * = <inference-rule-chain>
|
||||||
|
dir/subdir/inference-rule-chain.ir-from: @ = <dir/subdir/inference-rule-chain.ir-from>
|
||||||
|
dir/subdir/inference-rule-chain.ir-from: % = <undefined>
|
||||||
|
dir/subdir/inference-rule-chain.ir-from: ? = <dir/subdir/inference-rule-chain.ir-gen-from>
|
||||||
|
dir/subdir/inference-rule-chain.ir-from: < = <dir/subdir/inference-rule-chain.ir-gen-from>
|
||||||
|
dir/subdir/inference-rule-chain.ir-from: * = <dir/subdir/inference-rule-chain>
|
||||||
|
dir/subdir/inference-rule-chain.ir-to: @ = <dir/subdir/inference-rule-chain.ir-to>
|
||||||
|
dir/subdir/inference-rule-chain.ir-to: % = <undefined>
|
||||||
|
dir/subdir/inference-rule-chain.ir-to: ? = <dir/subdir/inference-rule-chain.ir-from>
|
||||||
|
dir/subdir/inference-rule-chain.ir-to: < = <dir/subdir/inference-rule-chain.ir-from>
|
||||||
|
dir/subdir/inference-rule-chain.ir-to: * = <dir/subdir/inference-rule-chain>
|
||||||
: Making var-scope-local.c out of nothing.
|
: Making var-scope-local.c out of nothing.
|
||||||
: Making var-scope-local.o from var-scope-local.c.
|
: Making var-scope-local.o from var-scope-local.c.
|
||||||
: Making basename "var-scope-local.o" in "." from "var-scope-local.c" in ".".
|
: Making basename "var-scope-local.o" in "." from "var-scope-local.c" in ".".
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# $NetBSD: var-scope-local.mk,v 1.5 2022/02/09 21:09:24 rillig Exp $
|
# $NetBSD: var-scope-local.mk,v 1.7 2023/04/29 10:16:24 rillig Exp $
|
||||||
#
|
#
|
||||||
# Tests for target-local variables, such as ${.TARGET} or $@. These variables
|
# Tests for target-local variables, such as ${.TARGET} or $@. These variables
|
||||||
# are relatively short-lived as they are created just before making the
|
# are relatively short-lived as they are created just before making the
|
||||||
|
@ -12,6 +12,64 @@
|
||||||
|
|
||||||
.MAIN: all
|
.MAIN: all
|
||||||
|
|
||||||
|
# Target-local variables in a target rule
|
||||||
|
#
|
||||||
|
# In target rules, '$*' only strips the extension off the pathname if the
|
||||||
|
# extension is listed in '.SUFFIXES'.
|
||||||
|
#
|
||||||
|
# expect: target-rule.ext: * = <target-rule.ext>
|
||||||
|
all: target-rule.ext dir/subdir/target-rule.ext
|
||||||
|
target-rule.ext dir/subdir/target-rule.ext: .PHONY
|
||||||
|
@echo '$@: @ = <${@:Uundefined}>'
|
||||||
|
@echo '$@: % = <${%:Uundefined}>'
|
||||||
|
@echo '$@: ? = <${?:Uundefined}>'
|
||||||
|
@echo '$@: < = <${<:Uundefined}>'
|
||||||
|
@echo '$@: * = <${*:Uundefined}>'
|
||||||
|
|
||||||
|
.SUFFIXES: .ir-gen-from .ir-from .ir-to
|
||||||
|
|
||||||
|
# In target rules, '$*' strips the extension off the pathname of the target
|
||||||
|
# if the extension is listed in '.SUFFIXES'.
|
||||||
|
#
|
||||||
|
# expect: target-rule.ir-gen-from: * = <target-rule>
|
||||||
|
all: target-rule.ir-gen-from dir/subdir/target-rule-dir.ir-gen-from
|
||||||
|
target-rule.ir-gen-from dir/subdir/target-rule-dir.ir-gen-from:
|
||||||
|
@echo '$@: @ = <${@:Uundefined}>'
|
||||||
|
@echo '$@: % = <${%:Uundefined}>'
|
||||||
|
@echo '$@: ? = <${?:Uundefined}>'
|
||||||
|
@echo '$@: < = <${<:Uundefined}>'
|
||||||
|
@echo '$@: * = <${*:Uundefined}>'
|
||||||
|
|
||||||
|
.ir-from.ir-to:
|
||||||
|
@echo '$@: @ = <${@:Uundefined}>'
|
||||||
|
@echo '$@: % = <${%:Uundefined}>'
|
||||||
|
@echo '$@: ? = <${?:Uundefined}>'
|
||||||
|
@echo '$@: < = <${<:Uundefined}>'
|
||||||
|
@echo '$@: * = <${*:Uundefined}>'
|
||||||
|
.ir-gen-from.ir-from:
|
||||||
|
@echo '$@: @ = <${@:Uundefined}>'
|
||||||
|
@echo '$@: % = <${%:Uundefined}>'
|
||||||
|
@echo '$@: ? = <${?:Uundefined}>'
|
||||||
|
@echo '$@: < = <${<:Uundefined}>'
|
||||||
|
@echo '$@: * = <${*:Uundefined}>'
|
||||||
|
|
||||||
|
# Target-local variables in an inference rule
|
||||||
|
all: inference-rule.ir-to dir/subdir/inference-rule.ir-to
|
||||||
|
inference-rule.ir-from: .PHONY
|
||||||
|
dir/subdir/inference-rule.ir-from: .PHONY
|
||||||
|
|
||||||
|
# Target-local variables in a chain of inference rules
|
||||||
|
all: inference-rule-chain.ir-to dir/subdir/inference-rule-chain.ir-to
|
||||||
|
inference-rule-chain.ir-gen-from: .PHONY
|
||||||
|
dir/subdir/inference-rule-chain.ir-gen-from: .PHONY
|
||||||
|
|
||||||
|
# The run-time 'check' directives from above happen after the parse-time
|
||||||
|
# 'check' directives from below.
|
||||||
|
#
|
||||||
|
# expect-reset
|
||||||
|
|
||||||
|
# Deferred evaluation during parsing
|
||||||
|
#
|
||||||
# The target-local variables can be used in expressions, just like other
|
# The target-local variables can be used in expressions, just like other
|
||||||
# variables. When these expressions are evaluated outside of a target, these
|
# variables. When these expressions are evaluated outside of a target, these
|
||||||
# expressions are not yet expanded, instead their text is preserved, to allow
|
# expressions are not yet expanded, instead their text is preserved, to allow
|
||||||
|
@ -20,8 +78,8 @@
|
||||||
#
|
#
|
||||||
# Conditions from .if directives are evaluated in the scope of the command
|
# Conditions from .if directives are evaluated in the scope of the command
|
||||||
# line, which means that variables from the command line, from the global
|
# line, which means that variables from the command line, from the global
|
||||||
# scope and from the environment are resolved, in this order (but see the
|
# scope and from the environment are resolved, in this precedence order (but
|
||||||
# command line option '-e'). In that phase, expressions involving
|
# see the command line option '-e'). In that phase, expressions involving
|
||||||
# target-local variables need to be preserved, including the exact names of
|
# target-local variables need to be preserved, including the exact names of
|
||||||
# the variables.
|
# the variables.
|
||||||
#
|
#
|
||||||
|
@ -77,13 +135,17 @@
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
|
||||||
|
# Custom local variables
|
||||||
|
#
|
||||||
# Additional target-local variables may be defined in dependency lines.
|
# Additional target-local variables may be defined in dependency lines.
|
||||||
.MAKEFLAGS: -dv
|
.MAKEFLAGS: -dv
|
||||||
# In the following line, the ':=' may either be interpreted as an assignment
|
# In the following line, the ':=' may either be interpreted as an assignment
|
||||||
# operator or as the dependency operator ':', followed by an empty variable
|
# operator or as the dependency operator ':', followed by an empty variable
|
||||||
# name and the assignment operator '='. It is the latter since in an
|
# name and the assignment operator '='. It is the latter since in an
|
||||||
# assignment, the left-hand side must be at most a single word. The empty
|
# assignment, the left-hand side must be a single word or empty.
|
||||||
# variable name is expanded twice, once for 'one' and once for 'two'.
|
#
|
||||||
|
# The empty variable name is expanded twice, once for 'one' and once for
|
||||||
|
# 'two'.
|
||||||
# expect: Var_SetExpand: variable name "" expands to empty string, with value "three" - ignored
|
# expect: Var_SetExpand: variable name "" expands to empty string, with value "three" - ignored
|
||||||
# expect: Var_SetExpand: variable name "" expands to empty string, with value "three" - ignored
|
# expect: Var_SetExpand: variable name "" expands to empty string, with value "three" - ignored
|
||||||
one two:=three
|
one two:=three
|
||||||
|
@ -205,32 +267,3 @@ a_use: .USE VAR=use
|
||||||
|
|
||||||
all: var-scope-local-use.o
|
all: var-scope-local-use.o
|
||||||
var-scope-local-use.o: a_use
|
var-scope-local-use.o: a_use
|
||||||
|
|
||||||
|
|
||||||
# Since parse.c 1.656 from 2022-01-27 and before parse.c 1.662 from
|
|
||||||
# 2022-02-05, there was an out-of-bounds read in Parse_IsVar when looking for
|
|
||||||
# a variable assignment in a dependency line with trailing whitespace. Lines
|
|
||||||
# without trailing whitespace were not affected. Global variable assignments
|
|
||||||
# were guaranteed to have no trailing whitespace and were thus not affected.
|
|
||||||
#
|
|
||||||
# Try to reproduce some variants that may lead to a crash, depending on the
|
|
||||||
# memory allocator. To get a crash, the terminating '\0' of the line must be
|
|
||||||
# the last byte of a memory page. The expression '${:U}' forces this trailing
|
|
||||||
# whitespace.
|
|
||||||
|
|
||||||
# On FreeBSD x86_64, a crash could in some cases be forced using the following
|
|
||||||
# line, which has length 47, so the terminating '\0' may end up at an address
|
|
||||||
# of the form 0xXXXX_XXXX_XXXX_Xfff:
|
|
||||||
Try_to_crash_FreeBSD.xxxxxxxxxxxxxxxxxx: 12345 ${:U}
|
|
||||||
|
|
||||||
# The following line has length 4095, so line[4095] == '\0'. If the line is
|
|
||||||
# allocated on a page boundary and the following page is not mapped, this line
|
|
||||||
# leads to a segmentation fault.
|
|
||||||
${:U:range=511:@_@1234567@:ts.}: 12345 ${:U}
|
|
||||||
|
|
||||||
# The following line has length 8191, so line[8191] == '\0'. If the line is
|
|
||||||
# allocated on a page boundary and the following page is not mapped, this line
|
|
||||||
# leads to a segmentation fault.
|
|
||||||
${:U:range=1023:@_@1234567@:ts.}: 12345 ${:U}
|
|
||||||
|
|
||||||
12345:
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
make: "varmod-gmtime.mk" line 57: Invalid time value at "${:U1593536400}} != "mtime=11593536400}""
|
make: "varmod-gmtime.mk" line 59: Invalid time value "-1"
|
||||||
make: "varmod-gmtime.mk" line 57: Malformed conditional (${%Y:L:gmtime=${:U1593536400}} != "mtime=11593536400}")
|
make: "varmod-gmtime.mk" line 59: Malformed conditional (${:L:gmtime=-1} != "")
|
||||||
make: "varmod-gmtime.mk" line 67: Invalid time value at "-1} != """
|
make: "varmod-gmtime.mk" line 68: Invalid time value " 1"
|
||||||
make: "varmod-gmtime.mk" line 67: Malformed conditional (${:L:gmtime=-1} != "")
|
make: "varmod-gmtime.mk" line 68: Malformed conditional (${:L:gmtime= 1} != "")
|
||||||
make: "varmod-gmtime.mk" line 76: Invalid time value at " 1} != """
|
make: "varmod-gmtime.mk" line 114: Invalid time value "10000000000000000000000000000000"
|
||||||
make: "varmod-gmtime.mk" line 76: Malformed conditional (${:L:gmtime= 1} != "")
|
make: "varmod-gmtime.mk" line 114: Malformed conditional (${:L:gmtime=10000000000000000000000000000000} != "")
|
||||||
make: "varmod-gmtime.mk" line 119: Invalid time value at "10000000000000000000000000000000} != """
|
make: "varmod-gmtime.mk" line 125: Invalid time value "error"
|
||||||
make: "varmod-gmtime.mk" line 119: Malformed conditional (${:L:gmtime=10000000000000000000000000000000} != "")
|
make: "varmod-gmtime.mk" line 125: Malformed conditional (${:L:gmtime=error} != "")
|
||||||
make: "varmod-gmtime.mk" line 130: Invalid time value at "error} != """
|
make: "varmod-gmtime.mk" line 134: Invalid time value "100000S,1970,bad,"
|
||||||
make: "varmod-gmtime.mk" line 130: Malformed conditional (${:L:gmtime=error} != "")
|
make: "varmod-gmtime.mk" line 134: Malformed conditional (${%Y:L:gmtime=100000S,1970,bad,} != "bad")
|
||||||
make: Fatal errors encountered -- cannot continue
|
make: Fatal errors encountered -- cannot continue
|
||||||
make: stopped in unit-tests
|
make: stopped in unit-tests
|
||||||
exit status 1
|
exit status 1
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
# $NetBSD: varmod-gmtime.mk,v 1.10 2021/01/19 05:26:34 rillig Exp $
|
# $NetBSD: varmod-gmtime.mk,v 1.14 2023/05/10 15:53:32 rillig Exp $
|
||||||
#
|
#
|
||||||
# Tests for the :gmtime variable modifier, which formats a timestamp
|
# Tests for the :gmtime variable modifier, which formats a timestamp
|
||||||
# using strftime(3) in UTC.
|
# using strftime(3) in UTC.
|
||||||
|
#
|
||||||
|
# See also:
|
||||||
|
# varmod-localtime.mk
|
||||||
|
|
||||||
.if ${TZ:Uundefined} != "undefined" # see unit-tests/Makefile
|
.if ${TZ:Uundefined} != "undefined" # see unit-tests/Makefile
|
||||||
. error
|
. error
|
||||||
|
@ -41,20 +44,9 @@
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
|
||||||
# As of 2020-08-16, it is not possible to pass the seconds via a
|
# Before var.c 1.1050 from 2023-05-09, it was not possible to pass the
|
||||||
# variable expression. This is because parsing of the :gmtime
|
# seconds via a variable expression.
|
||||||
# modifier stops at the '$' and returns to ApplyModifiers.
|
.if ${%Y:L:gmtime=${:U1593536400}} != "2020"
|
||||||
#
|
|
||||||
# There, a colon would be skipped but not a dollar.
|
|
||||||
# Parsing therefore continues at the '$' of the ${:U159...}, looking
|
|
||||||
# for an ordinary variable modifier.
|
|
||||||
#
|
|
||||||
# At this point, the ${:U} is expanded and interpreted as a variable
|
|
||||||
# modifier, which results in the error message "Unknown modifier '1'".
|
|
||||||
#
|
|
||||||
# If ApplyModifier_Gmtime were to pass its argument through
|
|
||||||
# ParseModifierPart, this would work.
|
|
||||||
.if ${%Y:L:gmtime=${:U1593536400}} != "mtime=11593536400}"
|
|
||||||
. error
|
. error
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
@ -75,6 +67,8 @@
|
||||||
# because it would make sense but just as a side-effect from using strtoul.
|
# because it would make sense but just as a side-effect from using strtoul.
|
||||||
.if ${:L:gmtime= 1} != ""
|
.if ${:L:gmtime= 1} != ""
|
||||||
. error
|
. error
|
||||||
|
.else
|
||||||
|
. error
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -115,7 +109,8 @@
|
||||||
# ULONG_MAX, which got converted to -1. This resulted in a time stamp of
|
# ULONG_MAX, which got converted to -1. This resulted in a time stamp of
|
||||||
# the second before 1970.
|
# the second before 1970.
|
||||||
#
|
#
|
||||||
# Since var.c 1.631, the overflow is detected and produces a parse error.
|
# Since var.c 1.631 from 2020-10-31, the overflow is detected and produces a
|
||||||
|
# parse error.
|
||||||
.if ${:L:gmtime=10000000000000000000000000000000} != ""
|
.if ${:L:gmtime=10000000000000000000000000000000} != ""
|
||||||
. error
|
. error
|
||||||
.else
|
.else
|
||||||
|
@ -133,5 +128,11 @@
|
||||||
. error
|
. error
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
# Before var.c 1.1050 from 2023-05-09, the timestamp could be directly
|
||||||
|
# followed by the next modifier, without a ':' separator. This was the same
|
||||||
|
# bug as for the ':L' and ':P' modifiers.
|
||||||
|
.if ${%Y:L:gmtime=100000S,1970,bad,} != "bad"
|
||||||
|
. error
|
||||||
|
.endif
|
||||||
|
|
||||||
all:
|
all:
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
make: "varmod-localtime.mk" line 57: Invalid time value at "${:U1593536400}} != "mtime=11593536400}""
|
make: "varmod-localtime.mk" line 59: Invalid time value "-1"
|
||||||
make: "varmod-localtime.mk" line 57: Malformed conditional (${%Y:L:localtime=${:U1593536400}} != "mtime=11593536400}")
|
make: "varmod-localtime.mk" line 59: Malformed conditional (${:L:localtime=-1} != "")
|
||||||
make: "varmod-localtime.mk" line 67: Invalid time value at "-1} != """
|
make: "varmod-localtime.mk" line 68: Invalid time value " 1"
|
||||||
make: "varmod-localtime.mk" line 67: Malformed conditional (${:L:localtime=-1} != "")
|
make: "varmod-localtime.mk" line 68: Malformed conditional (${:L:localtime= 1} != "")
|
||||||
make: "varmod-localtime.mk" line 76: Invalid time value at " 1} != """
|
make: "varmod-localtime.mk" line 114: Invalid time value "10000000000000000000000000000000"
|
||||||
make: "varmod-localtime.mk" line 76: Malformed conditional (${:L:localtime= 1} != "")
|
make: "varmod-localtime.mk" line 114: Malformed conditional (${:L:localtime=10000000000000000000000000000000} != "")
|
||||||
make: "varmod-localtime.mk" line 119: Invalid time value at "10000000000000000000000000000000} != """
|
make: "varmod-localtime.mk" line 125: Invalid time value "error"
|
||||||
make: "varmod-localtime.mk" line 119: Malformed conditional (${:L:localtime=10000000000000000000000000000000} != "")
|
make: "varmod-localtime.mk" line 125: Malformed conditional (${:L:localtime=error} != "")
|
||||||
make: "varmod-localtime.mk" line 130: Invalid time value at "error} != """
|
make: "varmod-localtime.mk" line 134: Invalid time value "100000S,1970,bad,"
|
||||||
make: "varmod-localtime.mk" line 130: Malformed conditional (${:L:localtime=error} != "")
|
make: "varmod-localtime.mk" line 134: Malformed conditional (${%Y:L:localtime=100000S,1970,bad,} != "bad")
|
||||||
make: Fatal errors encountered -- cannot continue
|
make: Fatal errors encountered -- cannot continue
|
||||||
make: stopped in unit-tests
|
make: stopped in unit-tests
|
||||||
exit status 1
|
exit status 1
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
# $NetBSD: varmod-localtime.mk,v 1.8 2021/01/19 05:26:34 rillig Exp $
|
# $NetBSD: varmod-localtime.mk,v 1.12 2023/05/10 15:53:32 rillig Exp $
|
||||||
#
|
#
|
||||||
# Tests for the :localtime variable modifier, which formats a timestamp
|
# Tests for the :localtime variable modifier, which formats a timestamp
|
||||||
# using strftime(3) in local time.
|
# using strftime(3) in local time.
|
||||||
|
#
|
||||||
|
# See also:
|
||||||
|
# varmod-gmtime.mk
|
||||||
|
|
||||||
.if ${TZ:Uno:NEurope/Berlin:NUTC-1} != "" # see unit-tests/Makefile
|
.if ${TZ:Uno:NEurope/Berlin:NUTC-1} != "" # see unit-tests/Makefile
|
||||||
. error
|
. error
|
||||||
|
@ -41,20 +44,9 @@
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
|
||||||
# As of 2020-08-16, it is not possible to pass the seconds via a
|
# Before var.c 1.1050 from 2023-05-09, it was not possible to pass the
|
||||||
# variable expression. This is because parsing of the :localtime
|
# seconds via a variable expression.
|
||||||
# modifier stops at the '$' and returns to ApplyModifiers.
|
.if ${%Y:L:localtime=${:U1593536400}} != "2020"
|
||||||
#
|
|
||||||
# There, a colon would be skipped but not a dollar.
|
|
||||||
# Parsing therefore continues at the '$' of the ${:U159...}, looking
|
|
||||||
# for an ordinary variable modifier.
|
|
||||||
#
|
|
||||||
# At this point, the ${:U} is expanded and interpreted as a variable
|
|
||||||
# modifier, which results in the error message "Unknown modifier '1'".
|
|
||||||
#
|
|
||||||
# If ApplyModifier_Localtime were to pass its argument through
|
|
||||||
# ParseModifierPart, this would work.
|
|
||||||
.if ${%Y:L:localtime=${:U1593536400}} != "mtime=11593536400}"
|
|
||||||
. error
|
. error
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
@ -75,6 +67,8 @@
|
||||||
# because it would make sense but just as a side-effect from using strtoul.
|
# because it would make sense but just as a side-effect from using strtoul.
|
||||||
.if ${:L:localtime= 1} != ""
|
.if ${:L:localtime= 1} != ""
|
||||||
. error
|
. error
|
||||||
|
.else
|
||||||
|
. error
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -115,7 +109,8 @@
|
||||||
# ULONG_MAX, which got converted to -1. This resulted in a time stamp of
|
# ULONG_MAX, which got converted to -1. This resulted in a time stamp of
|
||||||
# the second before 1970.
|
# the second before 1970.
|
||||||
#
|
#
|
||||||
# Since var.c 1.631, the overflow is detected and produces a parse error.
|
# Since var.c 1.631 from 2020-10-31, the overflow is detected and produces a
|
||||||
|
# parse error.
|
||||||
.if ${:L:localtime=10000000000000000000000000000000} != ""
|
.if ${:L:localtime=10000000000000000000000000000000} != ""
|
||||||
. error
|
. error
|
||||||
.else
|
.else
|
||||||
|
@ -133,5 +128,11 @@
|
||||||
. error
|
. error
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
# Before var.c 1.1050 from 2023-05-09, the timestamp could be directly
|
||||||
|
# followed by the next modifier, without a ':' separator. This was the same
|
||||||
|
# bug as for the ':L' and ':P' modifiers.
|
||||||
|
.if ${%Y:L:localtime=100000S,1970,bad,} != "bad"
|
||||||
|
. error
|
||||||
|
.endif
|
||||||
|
|
||||||
all:
|
all:
|
||||||
|
|
1
contrib/bmake/unit-tests/varmod-mtime.exp
Normal file
1
contrib/bmake/unit-tests/varmod-mtime.exp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
exit status 0
|
30
contrib/bmake/unit-tests/varmod-mtime.mk
Normal file
30
contrib/bmake/unit-tests/varmod-mtime.mk
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# $NetBSD: varmod-mtime.mk,v 1.1 2023/05/09 20:14:27 sjg Exp $
|
||||||
|
#
|
||||||
|
# Tests for the :mtime variable modifier, which provides mtime
|
||||||
|
# of variable value assumed to be a pathname.
|
||||||
|
|
||||||
|
all:
|
||||||
|
|
||||||
|
# mtime of this makefile
|
||||||
|
mtime:= ${MAKEFILE:mtime}
|
||||||
|
|
||||||
|
# if pathname does not exist and timestamp is provided
|
||||||
|
# that is the result
|
||||||
|
.if ${no/such:L:mtime=0} != "0"
|
||||||
|
. error
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.if ${no/such:L:mtime=42} != "42"
|
||||||
|
. error
|
||||||
|
.endif
|
||||||
|
|
||||||
|
# if no timestamp is provided and stat(2) fails use current time
|
||||||
|
.if ${no/such:L:mtime} < ${mtime}
|
||||||
|
. error no/such:L:mtime ${no/such:L:mtime} < ${mtime}
|
||||||
|
.endif
|
||||||
|
|
||||||
|
COOKIE = ${TMPDIR}/varmod-mtime.cookie
|
||||||
|
x!= touch ${COOKIE}
|
||||||
|
.if ${COOKIE:mtime=0} < ${mtime}
|
||||||
|
. error COOKIE:mtime=0 ${COOKIE:mtime=0} < ${mtime}
|
||||||
|
.endif
|
|
@ -1,4 +1,4 @@
|
||||||
# $NetBSD: varmod-path.mk,v 1.3 2020/08/23 08:10:49 rillig Exp $
|
# $NetBSD: varmod-path.mk,v 1.4 2023/05/10 15:53:32 rillig Exp $
|
||||||
#
|
#
|
||||||
# Tests for the :P variable modifier, which looks up the path for a given
|
# Tests for the :P variable modifier, which looks up the path for a given
|
||||||
# target.
|
# target.
|
||||||
|
@ -7,11 +7,12 @@
|
||||||
# as of 2020-08-23 it is nevertheless resolved to a path. This is probably
|
# as of 2020-08-23 it is nevertheless resolved to a path. This is probably
|
||||||
# unintended.
|
# unintended.
|
||||||
#
|
#
|
||||||
# The real target is located in a subdirectory, and its full path is returned.
|
# In this test, the real target is located in a subdirectory, and its full
|
||||||
# If it had been in the current directory, the difference between its path and
|
# path is returned. If it had been in the current directory, the difference
|
||||||
# its name would not be visible.
|
# between its path and its name would not be visible.
|
||||||
#
|
#
|
||||||
# The enoent target does not exist, therefore the target name is returned.
|
# The enoent target does not exist, therefore the plain name of the target
|
||||||
|
# is returned.
|
||||||
|
|
||||||
.MAIN: all
|
.MAIN: all
|
||||||
|
|
||||||
|
@ -20,7 +21,8 @@ _!= mkdir varmod-path.subdir
|
||||||
_!= > varmod-path.subdir/varmod-path.phony
|
_!= > varmod-path.subdir/varmod-path.phony
|
||||||
_!= > varmod-path.subdir/varmod-path.real
|
_!= > varmod-path.subdir/varmod-path.real
|
||||||
|
|
||||||
# To have an effect, this .PATH declaration must be after the directory is created.
|
# To have an effect, this .PATH declaration must be processed after the
|
||||||
|
# directory has been created.
|
||||||
.PATH: varmod-path.subdir
|
.PATH: varmod-path.subdir
|
||||||
|
|
||||||
varmod-path.phony: .PHONY
|
varmod-path.phony: .PHONY
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: var.c,v 1.1049 2023/03/28 14:39:31 rillig Exp $ */
|
/* $NetBSD: var.c,v 1.1054 2023/05/10 18:22:33 sjg Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988, 1989, 1990, 1993
|
* Copyright (c) 1988, 1989, 1990, 1993
|
||||||
|
@ -147,7 +147,7 @@
|
||||||
#include "metachar.h"
|
#include "metachar.h"
|
||||||
|
|
||||||
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
|
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
|
||||||
MAKE_RCSID("$NetBSD: var.c,v 1.1049 2023/03/28 14:39:31 rillig Exp $");
|
MAKE_RCSID("$NetBSD: var.c,v 1.1054 2023/05/10 18:22:33 sjg Exp $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Variables are defined using one of the VAR=value assignments. Their
|
* Variables are defined using one of the VAR=value assignments. Their
|
||||||
|
@ -2196,6 +2196,8 @@ ParseModifierPartBalanced(const char **pp, LazyBuf *part)
|
||||||
static bool
|
static bool
|
||||||
ParseModifierPartSubst(
|
ParseModifierPartSubst(
|
||||||
const char **pp,
|
const char **pp,
|
||||||
|
/* If true, parse up to but excluding the next ':' or ch->endc. */
|
||||||
|
bool whole,
|
||||||
char delim,
|
char delim,
|
||||||
VarEvalMode emode,
|
VarEvalMode emode,
|
||||||
ModChain *ch,
|
ModChain *ch,
|
||||||
|
@ -2213,11 +2215,14 @@ ParseModifierPartSubst(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
const char *p;
|
const char *p;
|
||||||
|
char end1, end2;
|
||||||
|
|
||||||
p = *pp;
|
p = *pp;
|
||||||
LazyBuf_Init(part, p);
|
LazyBuf_Init(part, p);
|
||||||
|
|
||||||
while (*p != '\0' && *p != delim) {
|
end1 = whole ? ':' : delim;
|
||||||
|
end2 = whole ? ch->endc : delim;
|
||||||
|
while (*p != '\0' && *p != end1 && *p != end2) {
|
||||||
if (IsEscapedModifierPart(p, delim, subst)) {
|
if (IsEscapedModifierPart(p, delim, subst)) {
|
||||||
LazyBuf_Add(part, p[1]);
|
LazyBuf_Add(part, p[1]);
|
||||||
p += 2;
|
p += 2;
|
||||||
|
@ -2239,15 +2244,15 @@ ParseModifierPartSubst(
|
||||||
ParseModifierPartExpr(&p, part, ch, emode);
|
ParseModifierPartExpr(&p, part, ch, emode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*p != delim) {
|
*pp = p;
|
||||||
*pp = p;
|
if (*p != end1 && *p != end2) {
|
||||||
Error("Unfinished modifier for \"%s\" ('%c' missing)",
|
Error("Unfinished modifier for \"%s\" ('%c' missing)",
|
||||||
ch->expr->name, delim);
|
ch->expr->name, end2);
|
||||||
LazyBuf_Done(part);
|
LazyBuf_Done(part);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!whole)
|
||||||
*pp = p + 1;
|
(*pp)++;
|
||||||
|
|
||||||
{
|
{
|
||||||
Substring sub = LazyBuf_Get(part);
|
Substring sub = LazyBuf_Get(part);
|
||||||
|
@ -2280,7 +2285,8 @@ ParseModifierPart(
|
||||||
LazyBuf *part
|
LazyBuf *part
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return ParseModifierPartSubst(pp, delim, emode, ch, part, NULL, NULL);
|
return ParseModifierPartSubst(pp, false, delim, emode, ch, part,
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
MAKE_INLINE bool
|
MAKE_INLINE bool
|
||||||
|
@ -2576,11 +2582,23 @@ ApplyModifier_Time(const char **pp, ModChain *ch)
|
||||||
|
|
||||||
if (args[0] == '=') {
|
if (args[0] == '=') {
|
||||||
const char *p = args + 1;
|
const char *p = args + 1;
|
||||||
if (!TryParseTime(&p, &t)) {
|
LazyBuf buf;
|
||||||
Parse_Error(PARSE_FATAL,
|
if (!ParseModifierPartSubst(&p, true, '\0', ch->expr->emode,
|
||||||
"Invalid time value at \"%s\"", p);
|
ch, &buf, NULL, NULL))
|
||||||
return AMR_CLEANUP;
|
return AMR_CLEANUP;
|
||||||
}
|
if (ModChain_ShouldEval(ch)) {
|
||||||
|
Substring arg = LazyBuf_Get(&buf);
|
||||||
|
const char *arg_p = arg.start;
|
||||||
|
if (!TryParseTime(&arg_p, &t) || arg_p != arg.end) {
|
||||||
|
Parse_Error(PARSE_FATAL,
|
||||||
|
"Invalid time value \"%.*s\"",
|
||||||
|
(int)Substring_Length(arg), arg.start);
|
||||||
|
LazyBuf_Done(&buf);
|
||||||
|
return AMR_CLEANUP;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
t = 0;
|
||||||
|
LazyBuf_Done(&buf);
|
||||||
*pp = p;
|
*pp = p;
|
||||||
} else {
|
} else {
|
||||||
t = 0;
|
t = 0;
|
||||||
|
@ -2823,6 +2841,71 @@ ApplyModifier_Match(const char **pp, ModChain *ch)
|
||||||
return AMR_OK;
|
return AMR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ModifyWord_MtimeArgs {
|
||||||
|
bool error;
|
||||||
|
bool fallback;
|
||||||
|
ApplyModifierResult rc;
|
||||||
|
time_t t;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
ModifyWord_Mtime(Substring word, SepBuf *buf, void *data)
|
||||||
|
{
|
||||||
|
char tbuf[BUFSIZ];
|
||||||
|
struct stat st;
|
||||||
|
struct ModifyWord_MtimeArgs *args = data;
|
||||||
|
|
||||||
|
if (Substring_IsEmpty(word))
|
||||||
|
return;
|
||||||
|
assert(word.end[0] == '\0'); /* assume null-terminated word */
|
||||||
|
if (stat(word.start, &st) < 0) {
|
||||||
|
if (args->error) {
|
||||||
|
Parse_Error(PARSE_FATAL,
|
||||||
|
"Cannot determine mtime for '%s': %s",
|
||||||
|
word.start, strerror(errno));
|
||||||
|
args->rc = AMR_CLEANUP;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (args->fallback)
|
||||||
|
st.st_mtime = args->t;
|
||||||
|
else
|
||||||
|
time(&st.st_mtime);
|
||||||
|
}
|
||||||
|
snprintf(tbuf, sizeof(tbuf), "%u", (unsigned)st.st_mtime);
|
||||||
|
SepBuf_AddStr(buf, tbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* :mtime */
|
||||||
|
static ApplyModifierResult
|
||||||
|
ApplyModifier_Mtime(const char **pp, ModChain *ch)
|
||||||
|
{
|
||||||
|
const char *p, *mod = *pp;
|
||||||
|
struct ModifyWord_MtimeArgs args;
|
||||||
|
|
||||||
|
if (!ModMatchEq(mod, "mtime", ch))
|
||||||
|
return AMR_UNKNOWN;
|
||||||
|
*pp += 5;
|
||||||
|
p = *pp;
|
||||||
|
args.error = args.fallback = false;
|
||||||
|
args.rc = AMR_OK;
|
||||||
|
if (p[0] == '=') {
|
||||||
|
p++;
|
||||||
|
args.fallback = true;
|
||||||
|
if (!TryParseTime(&p, &args.t)) {
|
||||||
|
if (strncmp(p, "error", 5) == 0) {
|
||||||
|
args.error = true;
|
||||||
|
p += 5;
|
||||||
|
} else
|
||||||
|
return AMR_BAD;
|
||||||
|
}
|
||||||
|
*pp = p;
|
||||||
|
}
|
||||||
|
if (!ModChain_ShouldEval(ch))
|
||||||
|
return AMR_OK;
|
||||||
|
ModifyWords(ch, ModifyWord_Mtime, &args, ch->oneBigWord);
|
||||||
|
return args.rc;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ParsePatternFlags(const char **pp, PatternFlags *pflags, bool *oneBigWord)
|
ParsePatternFlags(const char **pp, PatternFlags *pflags, bool *oneBigWord)
|
||||||
{
|
{
|
||||||
|
@ -2870,13 +2953,13 @@ ApplyModifier_Subst(const char **pp, ModChain *ch)
|
||||||
(*pp)++;
|
(*pp)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ParseModifierPartSubst(pp, delim, ch->expr->emode, ch, &lhsBuf,
|
if (!ParseModifierPartSubst(pp,
|
||||||
&args.pflags, NULL))
|
false, delim, ch->expr->emode, ch, &lhsBuf, &args.pflags, NULL))
|
||||||
return AMR_CLEANUP;
|
return AMR_CLEANUP;
|
||||||
args.lhs = LazyBuf_Get(&lhsBuf);
|
args.lhs = LazyBuf_Get(&lhsBuf);
|
||||||
|
|
||||||
if (!ParseModifierPartSubst(pp, delim, ch->expr->emode, ch, &rhsBuf,
|
if (!ParseModifierPartSubst(pp,
|
||||||
NULL, &args)) {
|
false, delim, ch->expr->emode, ch, &rhsBuf, NULL, &args)) {
|
||||||
LazyBuf_Done(&lhsBuf);
|
LazyBuf_Done(&lhsBuf);
|
||||||
return AMR_CLEANUP;
|
return AMR_CLEANUP;
|
||||||
}
|
}
|
||||||
|
@ -3805,6 +3888,8 @@ ApplyModifier(const char **pp, ModChain *ch)
|
||||||
case 'M':
|
case 'M':
|
||||||
case 'N':
|
case 'N':
|
||||||
return ApplyModifier_Match(pp, ch);
|
return ApplyModifier_Match(pp, ch);
|
||||||
|
case 'm':
|
||||||
|
return ApplyModifier_Mtime(pp, ch);
|
||||||
case 'O':
|
case 'O':
|
||||||
return ApplyModifier_Order(pp, ch);
|
return ApplyModifier_Order(pp, ch);
|
||||||
case 'P':
|
case 'P':
|
||||||
|
|
Loading…
Reference in a new issue