Import bmake-20260704

Intersting/relevant changes since bmake-20260508

ChangeLog since bmake-20260508

2026-07-04  Simon J Gerraty  <[email protected]>

	* VERSION (_MAKE_VERSION): 20260704

2026-07-03  Simon J Gerraty  <[email protected]>

	* VERSION (_MAKE_VERSION): 20260703
	Merge with NetBSD make, pick up
	o meta.c: do a better job of resolving relative paths
	o var.c: add alternation support to :M
	eg. :M*{Makefile*,.mk} matches any *Makefile* or *.mk

2026-07-02  Simon J Gerraty  <[email protected]>

	* VERSION (_MAKE_VERSION): 20260702
	Merge with NetBSD make, pick up
	o meta.c: .MAKE.META.FILTER can be used to more generally filter
	relevant content of .meta file in meta_oodate.

2026-06-19  Simon J Gerraty  <[email protected]>

	* VERSION (_MAKE_VERSION): 20260619
	Merge with NetBSD make, pick up
	o make.1: fix description of .MADE it is a source not a target.

	* update mk files

2026-06-10  Simon J Gerraty  <[email protected]>

	* VERSION (_MAKE_VERSION): 20260609
	Merge with NetBSD make, pick up
	o parse.c: allow semicolons and parentheses in dependency line
	expressions

mk/ChangeLog since bmake-20260508

2026-07-04  Simon J Gerraty  <[email protected]>

	* install-mk (MK_VERSION): 20260704

2026-07-03  Simon J Gerraty  <[email protected]>

	* dirdeps.mk: make use of alternation support in latest bmake
	when setting .MAKE.META.IGNORE_FILTER so we can get both
	Makefile.depend* and *.mk to make cache out-of-date.

2026-07-02  Simon J Gerraty  <[email protected]>

	* meta2deps.py: detect corrupted filemon data on Linux,
	caused by lost newlines.

2026-06-21  Simon J Gerraty  <[email protected]>

	* install-mk (MK_VERSION): 20260621

	* gendirdeps.mk: more debug output

	* meta.autodep.mk: remove extra } from GENDIRDEPS_ENV

2026-06-19  Simon J Gerraty  <[email protected]>

	* install-mk (MK_VERSION): 20260619

	* install-new.mk: for POSIX_SHELL we need .new*
	rather than just .new

2026-05-21  Simon J Gerraty  <[email protected]>

	* meta2deps.{py,sh}: skip pathnames with spaces - not worth the pain.
This commit is contained in:
Simon J. Gerraty committed 2026-07-05 11:22:31 -07:00
1 parent ef402bba84
commit e988c5eab5
25 files changed
+648 -203

No files matched your search

+34
View File
@@ -1,3 +1,37 @@
2026-07-04 Simon J Gerraty <[email protected]>
* VERSION (_MAKE_VERSION): 20260704
2026-07-03 Simon J Gerraty <[email protected]>
* VERSION (_MAKE_VERSION): 20260703
Merge with NetBSD make, pick up
o meta.c: do a better job of resolving relative paths
o var.c: add alternation support to :M
eg. :M*{Makefile*,.mk} matches any *Makefile* or *.mk
2026-07-02 Simon J Gerraty <[email protected]>
* VERSION (_MAKE_VERSION): 20260702
Merge with NetBSD make, pick up
o meta.c: .MAKE.META.FILTER can be used to more generally filter
relevant content of .meta file in meta_oodate.
2026-06-19 Simon J Gerraty <[email protected]>
* VERSION (_MAKE_VERSION): 20260619
Merge with NetBSD make, pick up
o make.1: fix description of .MADE it is a source not a target.
* update mk files
2026-06-10 Simon J Gerraty <[email protected]>
* VERSION (_MAKE_VERSION): 20260609
Merge with NetBSD make, pick up
o parse.c: allow semicolons and parentheses in dependency line
expressions
2026-05-08 Simon J Gerraty <[email protected]>
* VERSION (_MAKE_VERSION): 20260508
+1 -1
View File
@@ -1,2 +1,2 @@
# keep this compatible with sh and make
_MAKE_VERSION=20260508
_MAKE_VERSION=20260704
+32 -8
View File
@@ -1,4 +1,4 @@
.\" $NetBSD: make.1,v 1.391 2026/05/08 16:11:21 sjg Exp $
.\" $NetBSD: make.1,v 1.394 2026/07/03 15:31:34 sjg Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -29,7 +29,7 @@
.\"
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\"
.Dd May 8, 2026
.Dd July 3, 2026
.Dt BMAKE 1
.Os
.Sh NAME
@@ -1038,11 +1038,26 @@ the current target is considered out-of-date.
.It Va .MAKE.META.CMP_FILTER
In
.Dq meta
mode, it can (very rarely!) be useful to filter command
mode, it can sometimes be useful to filter command
lines before comparison.
This variable can be set to a set of modifiers that are applied to
each line of the old and new command that differ, if the filtered
commands still differ, the target is considered out-of-date.
This variable can contain a list of modifiers that will be joined with
.Ql \&:
and applied to each line of the old and new command that differ.
If the filtered commands still differ,
the target is considered out-of-date.
.It Va .MAKE.META.FILTER
In
.Dq meta
mode, it can be useful to filter most of the data in a meta file.
For example, when a pre-built tree is relocated or cloned,
all the targets would be considered out-of-date without a filter
to replace the old location with the new.
This variable is similar to
.Va .MAKE.META.CMP_FILTER
but is appliled to commands, cwd and the syscall records from filemon.
In the case of commands, this is done prior to any
.Va .MAKE.META.CMP_FILTER
modifiers are applied during comparison.
.It Va .MAKE.META.CREATED
In
.Dq meta
@@ -1506,7 +1521,16 @@ and
.Ql \&[] )
may
be used.
The wildcard characters may be escaped with a backslash
Braces can be used to list alternate patterns.
For example,
.Ql ${.ALLSRC:M*{Makefile*,.mk}}
could be used to match any
.Ql *Makefile*
or
.Ql *.mk
in
.Va .ALLSRC .
The wildcard characters and braces may be escaped with a backslash
.Pq Ql \e .
As a consequence of the way values are split into words, matched,
and then joined, the construct
@@ -2317,7 +2341,7 @@ as if they all were preceded by a dash
.\" .It Ic .JOIN
.\" XXX
.It Ic .MADE
Mark all sources of this target as being up to date.
Mark the target(s) up to date.
.It Ic .MAKE
Execute the commands associated with this target even if the
.Fl n
+25 -12
View File
@@ -675,11 +675,21 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
current target is considered out-of-date.
_._M_A_K_E_._M_E_T_A_._C_M_P___F_I_L_T_E_R
In "meta" mode, it can (very rarely!) be useful to filter command
lines before comparison. This variable can be set to a set of
modifiers that are applied to each line of the old and new
command that differ, if the filtered commands still differ, the
target is considered out-of-date.
In "meta" mode, it can sometimes be useful to filter command
lines before comparison. This variable can contain a list of
modifiers that will be joined with `:' and applied to each line
of the old and new command that differ. If the filtered commands
still differ, the target is considered out-of-date.
_._M_A_K_E_._M_E_T_A_._F_I_L_T_E_R
In "meta" mode, it can be useful to filter most of the data in a
meta file. For example, when a pre-built tree is relocated or
cloned, all the targets would be considered out-of-date without a
filter to replace the old location with the new. This variable
is similar to _._M_A_K_E_._M_E_T_A_._C_M_P___F_I_L_T_E_R but is appliled to commands,
cwd and the syscall records from filemon. In the case of
commands, this is done prior to any _._M_A_K_E_._M_E_T_A_._C_M_P___F_I_L_T_E_R
modifiers are applied during comparison.
_._M_A_K_E_._M_E_T_A_._C_R_E_A_T_E_D
In "meta" mode, this variable contains a list of all the meta
@@ -978,11 +988,14 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
::MM_p_a_t_t_e_r_n
Selects only those words that match _p_a_t_t_e_r_n. The standard shell
wildcard characters (`*', `?', and `[]') may be used. The wildcard
characters may be escaped with a backslash (`\'). As a consequence
of the way values are split into words, matched, and then joined,
the construct `${VAR:M*}' removes all leading and trailing
whitespace and normalizes the inter-word spacing to a single space.
wildcard characters (`*', `?', and `[]') may be used. Braces can be
used to list alternate patterns. For example,
`${.ALLSRC:M*{Makefile*,.mk}}' could be used to match any
`*Makefile*' or `*.mk' in _._A_L_L_S_R_C. The wildcard characters and
braces may be escaped with a backslash (`\'). As a consequence of
the way values are split into words, matched, and then joined, the
construct `${VAR:M*}' removes all leading and trailing whitespace
and normalizes the inter-word spacing to a single space.
::NN_p_a_t_t_e_r_n
This is the opposite of `::MM', selecting all words which do _n_o_t match
@@ -1489,7 +1502,7 @@ SSPPEECCIIAALL SSOOUURRCCEESS ((AATTTTRRIIBBUUTTEESS))
..IIGGNNOORREE Ignore any errors from the commands associated with this
target, exactly as if they all were preceded by a dash (`-').
..MMAADDEE Mark all sources of this target as being up to date.
..MMAADDEE Mark the target(s) up to date.
..MMAAKKEE Execute the commands associated with this target even if the --nn
or --tt options were specified. Normally used to mark recursive
@@ -1882,4 +1895,4 @@ BBUUGGSS
attempt to suppress a cascade of unnecessary errors, can result in a
seemingly unexplained `*** Error code 6'
FreeBSD 14.3-RELEASE-p9 May 8, 2026 FreeBSD 14.3-RELEASE-p9
FreeBSD 14.4-RELEASE-p3 July 3, 2026 BMAKE(1)

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 96 KiB

+12 -9
View File
@@ -1,4 +1,4 @@
/* $NetBSD: dir.c,v 1.298 2026/04/06 17:13:54 rillig Exp $ */
/* $NetBSD: dir.c,v 1.299 2026/07/03 15:31:34 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -89,6 +89,9 @@
* Returns true if the name given it needs to
* be wildcard-expanded.
*
* ExpandCurly
* Expand a pattern containing braces to a StringList.
*
* SearchPath_Expand
* Expand a filename pattern to find all matching files
* from the search path.
@@ -132,7 +135,7 @@
#include "job.h"
/* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */
MAKE_RCSID("$NetBSD: dir.c,v 1.298 2026/04/06 17:13:54 rillig Exp $");
MAKE_RCSID("$NetBSD: dir.c,v 1.299 2026/07/03 15:31:34 sjg Exp $");
/*
* A search path is a list of CachedDir structures. A CachedDir has in it the
@@ -752,8 +755,8 @@ concat3(const char *a, size_t a_len, const char *b, size_t b_len,
/*
* Expand curly braces like the C shell. Brace expansion by itself is purely
* textual, the expansions are not looked up in the file system. But if an
* expanded word contains wildcard characters, it is expanded further,
* matching only the actually existing files.
* expanded word contains wildcard characters, and path is provided,
* it is expanded further, matching only the actually existing files.
*
* Example: "{a{b,c}}" expands to "ab" and "ac".
* Example: "{a}" expands to "a".
@@ -762,11 +765,11 @@ concat3(const char *a, size_t a_len, const char *b, size_t b_len,
* Input:
* word Entire word to expand
* brace First curly brace in it
* path Search path to use
* path Search path to use (NULL to skip wildcard expansion)
* expansions Place to store the expansions
*/
static void
DirExpandCurly(const char *word, const char *brace, SearchPath *path,
void
ExpandCurly(const char *word, const char *brace, SearchPath *path,
StringList *expansions)
{
const char *prefix, *middle, *piece, *middle_end, *suffix;
@@ -796,7 +799,7 @@ DirExpandCurly(const char *word, const char *brace, SearchPath *path,
char *file = concat3(prefix, prefix_len, piece, piece_len,
suffix, suffix_len);
if (contains_wildcard(file)) {
if (path != NULL && contains_wildcard(file)) {
SearchPath_Expand(path, file, expansions);
free(file);
} else {
@@ -898,7 +901,7 @@ SearchPath_Expand(SearchPath *path, const char *pattern, StringList *expansions)
brace = strchr(pattern, '{');
if (brace != NULL) {
DirExpandCurly(pattern, brace, path, expansions);
ExpandCurly(pattern, brace, path, expansions);
goto done;
}
+2 -1
View File
@@ -1,4 +1,4 @@
/* $NetBSD: dir.h,v 1.49 2024/07/07 07:50:57 rillig Exp $ */
/* $NetBSD: dir.h,v 1.50 2026/07/03 15:31:34 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -86,6 +86,7 @@ void Dir_End(void);
void Dir_SetPATH(void);
void Dir_SetSYSPATH(void);
bool Dir_HasWildcards(const char *) MAKE_ATTR_USE;
void ExpandCurly(const char *, const char *, SearchPath *, StringList *);
void SearchPath_Expand(SearchPath *, const char *, StringList *);
char *Dir_FindFile(const char *, SearchPath *) MAKE_ATTR_USE;
char *Dir_FindInclude(const char *, SearchPath *) MAKE_ATTR_USE;
+14 -1
View File
@@ -1,4 +1,4 @@
/* $NetBSD: filemon_dev.c,v 1.9 2022/03/04 23:17:16 sjg Exp $ */
/* $NetBSD: filemon_dev.c,v 1.10 2026/07/03 03:34:25 sjg Exp $ */
/*
* Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -123,6 +123,19 @@ filemon_close(struct filemon *F)
{
int error = 0;
#ifdef FILEMON_FLUSH_IOCTL
/*
* Ask the kernel to write the footer and flush the trailing records to
* the output file *now*, synchronously, before we close the device.
* Otherwise finalization happens only at device release, which the
* kernel defers until the last reference to the device is dropped; a
* child that transiently inherited this fd across a fork->exec window
* can hold that reference past our read of the output file, yielding a
* truncated .meta (records + "# Bye bye" footer missing).
*/
(void)ioctl(F->fd, FILEMON_FLUSH_IOCTL);
#endif
/* Close the filemon device fd. */
if (close(F->fd) == -1 && error == 0)
error = errno;
+32 -8
View File
@@ -1,4 +1,4 @@
.\" $NetBSD: make.1,v 1.391 2026/05/08 16:11:21 sjg Exp $
.\" $NetBSD: make.1,v 1.394 2026/07/03 15:31:34 sjg Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -29,7 +29,7 @@
.\"
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\"
.Dd May 8, 2026
.Dd July 3, 2026
.Dt MAKE 1
.Os
.Sh NAME
@@ -1038,11 +1038,26 @@ the current target is considered out-of-date.
.It Va .MAKE.META.CMP_FILTER
In
.Dq meta
mode, it can (very rarely!) be useful to filter command
mode, it can sometimes be useful to filter command
lines before comparison.
This variable can be set to a set of modifiers that are applied to
each line of the old and new command that differ, if the filtered
commands still differ, the target is considered out-of-date.
This variable can contain a list of modifiers that will be joined with
.Ql \&:
and applied to each line of the old and new command that differ.
If the filtered commands still differ,
the target is considered out-of-date.
.It Va .MAKE.META.FILTER
In
.Dq meta
mode, it can be useful to filter most of the data in a meta file.
For example, when a pre-built tree is relocated or cloned,
all the targets would be considered out-of-date without a filter
to replace the old location with the new.
This variable is similar to
.Va .MAKE.META.CMP_FILTER
but is appliled to commands, cwd and the syscall records from filemon.
In the case of commands, this is done prior to any
.Va .MAKE.META.CMP_FILTER
modifiers are applied during comparison.
.It Va .MAKE.META.CREATED
In
.Dq meta
@@ -1506,7 +1521,16 @@ and
.Ql \&[] )
may
be used.
The wildcard characters may be escaped with a backslash
Braces can be used to list alternate patterns.
For example,
.Ql ${.ALLSRC:M*{Makefile*,.mk}}
could be used to match any
.Ql *Makefile*
or
.Ql *.mk
in
.Va .ALLSRC .
The wildcard characters and braces may be escaped with a backslash
.Pq Ql \e .
As a consequence of the way values are split into words, matched,
and then joined, the construct
@@ -2317,7 +2341,7 @@ as if they all were preceded by a dash
.\" .It Ic .JOIN
.\" XXX
.It Ic .MADE
Mark all sources of this target as being up to date.
Mark the target(s) up to date.
.It Ic .MAKE
Execute the commands associated with this target even if the
.Fl n
+268 -105
View File
@@ -1,4 +1,4 @@
/* $NetBSD: meta.c,v 1.221 2026/04/06 17:13:54 rillig Exp $ */
/* $NetBSD: meta.c,v 1.223 2026/07/03 18:58:40 sjg Exp $ */
/*
* Implement 'meta' mode.
@@ -64,18 +64,11 @@ static char *metaBailiwickStr; /* string storage for the list */
static StringList metaIgnorePaths = LST_INIT; /* paths we deliberately ignore */
static char *metaIgnorePathsStr; /* string storage for the list */
#ifndef MAKE_META_IGNORE_PATHS
#define MAKE_META_IGNORE_PATHS ".MAKE.META.IGNORE_PATHS"
#endif
#ifndef MAKE_META_IGNORE_PATTERNS
#define MAKE_META_IGNORE_PATTERNS ".MAKE.META.IGNORE_PATTERNS"
#endif
#ifndef MAKE_META_IGNORE_FILTER
#define MAKE_META_IGNORE_FILTER ".MAKE.META.IGNORE_FILTER"
#endif
#ifndef MAKE_META_CMP_FILTER
#define MAKE_META_CMP_FILTER ".MAKE.META.CMP_FILTER"
#endif
#define MAKE_META_FILTER ".MAKE.META.FILTER"
bool useMeta = false;
static bool useFilemon = false;
@@ -88,6 +81,7 @@ static bool metaIgnoreCMDs = false; /* ignore CMDs in .meta files */
static bool metaIgnorePatterns = false; /* do we need to do pattern matches */
static bool metaIgnoreFilter = false; /* do we have more complex filtering? */
static bool metaCmpFilter = false; /* do we have CMP_FILTER ? */
static bool metaFilter = false; /* do we have FILTER */
static bool metaCurdirOk = false; /* write .meta in .CURDIR Ok? */
static bool metaSilent = false; /* if we have a .meta be SILENT */
@@ -606,6 +600,7 @@ meta_mode_init(const char *make_mode)
metaIgnorePatterns = Var_Exists(SCOPE_GLOBAL, MAKE_META_IGNORE_PATTERNS);
metaIgnoreFilter = Var_Exists(SCOPE_GLOBAL, MAKE_META_IGNORE_FILTER);
metaCmpFilter = Var_Exists(SCOPE_GLOBAL, MAKE_META_CMP_FILTER);
metaFilter = Var_Exists(SCOPE_GLOBAL, MAKE_META_FILTER);
}
MAKE_INLINE BuildMon *
@@ -1001,16 +996,86 @@ append_if_new(StringList *list, const char *str)
Lst_Append(list, bmake_strdup(str));
}
/* A "reserved" variable to store the command to be filtered */
#define META_CMD_FILTER_VAR ".MAKE.cmd_filtered"
/* remove any missingFiles entries that match p */
static void
remove_missing(StringList *missingFiles, const char *p)
{
StringListNode *ln = missingFiles->first;
while (ln != NULL) {
StringListNode *next = ln->next;
if (path_starts_with(ln->datum, p)) {
free(ln->datum);
Lst_Remove(missingFiles, ln);
}
ln = next;
}
}
static void
remove_relative_missing(StringList *missingFiles, const char *p, char *sdirs[])
{
char buf[MAXPATHLEN];
char **sdp;
for (sdp = sdirs; *sdp != NULL; sdp++) {
snprintf(buf, sizeof(buf), "%s/%s", *sdp, p);
remove_missing(missingFiles, buf);
}
}
/* try to find a relative path */
static char *
meta_resolve_path(char *buf, size_t bufsz, const char *p,
char *cwd, struct cached_stat *cstp, char *sdirs[])
{
char **sdp;
if (strcmp(p, ".") == 0)
return cwd;
for (sdp = sdirs; *sdp != NULL; sdp++) {
snprintf(buf, bufsz, "%s/%s", *sdp, p);
if (cached_stat(buf, cstp) == 0)
return buf;
}
return NULL;
}
/*
* Update sdirs to contain a NULL terminated list of
* unique dirs to try and resolve relative paths against.
*/
static void
set_sdirs(char *sdirs[], size_t sdsz,
char *latestdir, char *lcwd, char *cwd)
{
size_t i = 0;
sdirs[i++] = latestdir;
if (i < sdsz && strcmp(latestdir, lcwd) != 0)
sdirs[i++] = lcwd;
if (i < sdsz && strcmp(lcwd, cwd) != 0)
sdirs[i++] = cwd;
if (i < sdsz)
sdirs[i] = NULL;
else
sdirs[i - 1] = NULL; /* should never happen */
}
/* A "reserved" variable to store the string to be filtered */
#define META_FILTER_VAR ".MAKE.META._filtered_"
static char *
meta_filter_cmd(GNode *gn, char *s)
meta_filter(GNode *gn, char *s, const char *filter)
{
Var_Set(gn, META_CMD_FILTER_VAR, s);
s = Var_Subst(
"${" META_CMD_FILTER_VAR ":${" MAKE_META_CMP_FILTER ":ts:}}",
gn, VARE_EVAL);
char buf[sizeof(META_FILTER_VAR) + sizeof(MAKE_META_CMP_FILTER) + 24];
Var_Set(gn, META_FILTER_VAR, s);
/* ":N" is a harmless do nothing */
snprintf(buf, sizeof(buf), "${%s:${%s:UN:ts:}}",
META_FILTER_VAR, filter);
s = Var_Subst(buf, gn, VARE_EVAL);
return s;
}
@@ -1022,15 +1087,25 @@ meta_cmd_cmp(GNode *gn, char *a, char *b, bool filter)
rc = strcmp(a, b);
if (rc == 0 || !filter)
return rc;
a = meta_filter_cmd(gn, a);
b = meta_filter_cmd(gn, b);
a = meta_filter(gn, a, MAKE_META_CMP_FILTER);
b = meta_filter(gn, b, MAKE_META_CMP_FILTER);
rc = strcmp(a, b);
free(a);
free(b);
Var_Delete(gn, META_CMD_FILTER_VAR);
return rc;
}
typedef enum MetaSection {
META_HEADER,
META_CMD,
META_CWD,
META_TARGET,
META_OODATE,
META_ENV,
META_OUTPUT,
META_FILEMON
} MetaSection;
bool
meta_oodate(GNode *gn, bool oodate)
{
@@ -1043,7 +1118,6 @@ meta_oodate(GNode *gn, bool oodate)
char fname[MAXPATHLEN];
char fname1[MAXPATHLEN];
char fname2[MAXPATHLEN];
char fname3[MAXPATHLEN];
FStr dname;
const char *tname;
char *p;
@@ -1054,7 +1128,6 @@ meta_oodate(GNode *gn, bool oodate)
FILE *fp;
bool needOODATE = false;
StringList missingFiles;
bool have_filemon = false;
bool cmp_filter;
if (oodate)
@@ -1063,10 +1136,10 @@ meta_oodate(GNode *gn, bool oodate)
dname = Var_Value(gn, ".OBJDIR");
tname = GNode_VarTarget(gn);
/* if this succeeds fname3 is realpath of dname */
if (!meta_needed(gn, dname.str, fname3, false))
/* if this succeeds fname2 is realpath of dname */
if (!meta_needed(gn, dname.str, fname2, false))
goto oodate_out;
dname.str = fname3;
dname.str = fname2;
Lst_Init(&missingFiles);
@@ -1087,12 +1160,17 @@ meta_oodate(GNode *gn, bool oodate)
if ((fp = fopen(fname, "r")) != NULL) {
static char *buf = NULL;
static size_t bufsz;
char *rp;
char *freeit = NULL;
char *sdirs[4];
unsigned lineno = 0;
int lastpid = 0;
int pid;
int x;
bool found;
StringListNode *cmdNode;
struct cached_stat cst;
MetaSection section = META_HEADER;
if (buf == NULL) {
bufsz = 8 * BUFSIZ;
@@ -1107,6 +1185,10 @@ meta_oodate(GNode *gn, bool oodate)
strlcpy(lcwd, cwd, sizeof lcwd);
strlcpy(latestdir, cwd, sizeof latestdir);
/* adjust this when lcwd or latestdir change */
sdirs[0] = cwd;
sdirs[1] = NULL;
if (tmpdir == NULL) {
tmpdir = getTmpdir();
tmplen = strlen(tmpdir);
@@ -1115,10 +1197,14 @@ meta_oodate(GNode *gn, bool oodate)
/* we want to track all the .meta we read */
Global_Append(".MAKE.META.FILES", fname);
cmp_filter = metaCmpFilter || Var_Exists(gn, MAKE_META_CMP_FILTER);
cmp_filter = metaFilter || metaCmpFilter || Var_Exists(gn, MAKE_META_CMP_FILTER);
cmdNode = gn->commands.first;
while (!oodate && (x = fgetLine(&buf, &bufsz, 0, fp)) > 0) {
if (freeit != NULL) {
free(freeit);
freeit = NULL;
}
lineno++;
if (buf[x - 1] == '\n')
buf[x - 1] = '\0';
@@ -1129,16 +1215,37 @@ meta_oodate(GNode *gn, bool oodate)
}
link_src = NULL;
move_target = NULL;
/* Find the start of the build monitor section. */
if (!have_filemon) {
if (strncmp(buf, "-- filemon", 10) == 0) {
have_filemon = true;
continue;
}
if (strncmp(buf, "# buildmon", 10) == 0) {
have_filemon = true;
continue;
}
/*
* Track which section of the meta file we are in.
* For CMD, CWD, and FILEMON we may have to do filtering
* the rest are of no interest here.
*/
switch (section) {
case META_HEADER:
section = META_CMD;
continue;
case META_CMD:
if (strncmp(buf, "CWD", 3) == 0)
section = META_CWD;
break;
case META_CWD:
if (strncmp(buf, "TARG", 4) == 0)
section = META_TARGET;
break;
case META_TARGET:
case META_OODATE:
case META_ENV:
if (strncmp(buf, "-- command", 10) == 0)
section = META_OUTPUT;
continue;
case META_OUTPUT:
if (strncmp(buf, "-- filemon", 10) == 0)
section = META_FILEMON;
if (strncmp(buf, "# buildmon", 10) == 0)
section = META_FILEMON;
continue;
case META_FILEMON:
break;
}
/* Delimit the record type. */
@@ -1146,8 +1253,35 @@ meta_oodate(GNode *gn, bool oodate)
#ifdef DEBUG_META_MODE
DEBUG3(META, "%s:%u: %s\n", fname, lineno, buf);
#endif
if (metaFilter) {
switch (buf[0]) {
case '#': /* these do not need filtering */
case 'F':
case 'V':
case 'X':
break;
default:
switch (section) {
default:
break;
case META_CMD:
case META_CWD:
case META_FILEMON:
freeit = p = meta_filter(gn, p, MAKE_META_FILTER);
#ifdef DEBUG_META_MODE
DEBUG3(META, "%s:%u: filtered: %s\n", fname, lineno, p);
#endif
break;
}
break;
}
}
strsep(&p, " ");
if (have_filemon) {
switch (section) {
default:
break;
case META_FILEMON:
/*
* We are in the 'filemon' output section.
* Each record from filemon follows the general form:
@@ -1206,6 +1340,7 @@ meta_oodate(GNode *gn, bool oodate)
strlcpy(lcwd, ldir.str, sizeof lcwd);
FStr_Done(&ldir);
}
set_sdirs(sdirs, 4, latestdir, lcwd, cwd);
}
/* Skip past the pid. */
if (strsep(&p, " ") == NULL)
@@ -1261,6 +1396,7 @@ meta_oodate(GNode *gn, bool oodate)
DEBUG4(META, "%s:%u: cwd=%s ldir=%s\n",
fname, lineno, cwd, lcwd);
#endif
set_sdirs(sdirs, 4, latestdir, lcwd, cwd);
break;
case 'M': /* renaMe */
@@ -1283,18 +1419,26 @@ meta_oodate(GNode *gn, bool oodate)
DEQUOTE(move_target);
/* FALLTHROUGH */
case 'D': /* unlink */
if (*p == '/') {
/* remove any missingFiles entries that match p */
StringListNode *ln = missingFiles.first;
while (ln != NULL) {
StringListNode *next = ln->next;
if (path_starts_with(ln->datum, p)) {
free(ln->datum);
Lst_Remove(&missingFiles, ln);
}
ln = next;
if (*p != '/') {
#ifdef DEBUG_META_MODE
DEBUG3(META, "%s:%u: looking for: %s ...\n",
fname, lineno, p);
#endif
rp = meta_resolve_path(fname1, sizeof(fname1), p,
lcwd, &cst, sdirs);
if (rp != NULL) {
#ifdef DEBUG_META_MODE
DEBUG3(META, "%s:%u: found: %s\n",
fname, lineno, rp);
#endif
p = rp;
}
}
if (*p == '/') {
remove_missing(&missingFiles, p);
} else {
remove_relative_missing(&missingFiles, p, sdirs);
}
if (buf[0] == 'M') {
/* the target of the mv is a file 'W'ritten */
#ifdef DEBUG_META_MODE
@@ -1330,10 +1474,34 @@ meta_oodate(GNode *gn, bool oodate)
* but outside of .OBJDIR is missing,
* we need to do it again.
*/
/* ignore non-absolute paths */
if (*p != '/')
if (*p != '/') {
#ifdef DEBUG_META_MODE
DEBUG3(META, "%s:%u: looking for: %s ...\n",
fname, lineno, p);
#endif
rp = meta_resolve_path(fname1, sizeof(fname1), p,
lcwd, &cst, sdirs);
if (rp != NULL) {
#ifdef DEBUG_META_MODE
DEBUG3(META, "%s:%u: found: %s\n",
fname, lineno, rp);
#endif
p = rp;
}
}
if (*p != '/') {
/*
* it is missing or we should have found it
*/
snprintf(fname1, sizeof(fname1), "%s/%s",
lcwd, p);
#ifdef DEBUG_META_MODE
DEBUG3(META, "%s:%u: maybe missing: %s\n",
fname, lineno, fname1);
#endif
append_if_new(&missingFiles, fname1);
break;
}
if (Lst_IsEmpty(&metaBailiwick))
break;
@@ -1378,73 +1546,59 @@ meta_oodate(GNode *gn, bool oodate)
/*
* The rest of the record is the file name.
* Check if it's not an absolute path.
*/
{
char *sdirs[4];
char **sdp;
int sdx = 0;
bool found = false;
if (*p == '/') {
sdirs[sdx++] = p; /* done */
} else {
if (strcmp(".", p) == 0)
continue; /* no point */
/* Check vs latestdir */
if (snprintf(fname1, sizeof fname1, "%s/%s", latestdir, p) < (int)(sizeof fname1))
sdirs[sdx++] = fname1;
if (strcmp(latestdir, lcwd) != 0) {
/* Check vs lcwd */
if (snprintf(fname2, sizeof fname2, "%s/%s", lcwd, p) < (int)(sizeof fname2))
sdirs[sdx++] = fname2;
}
if (strcmp(lcwd, cwd) != 0) {
/* Check vs cwd */
if (snprintf(fname3, sizeof fname3, "%s/%s", cwd, p) < (int)(sizeof fname3))
sdirs[sdx++] = fname3;
}
}
sdirs[sdx++] = NULL;
for (sdp = sdirs; *sdp != NULL && !found; sdp++) {
#ifdef DEBUG_META_MODE
DEBUG3(META, "%s:%u: looking for: %s\n",
fname, lineno, *sdp);
#endif
if (cached_stat(*sdp, &cst) == 0) {
found = true;
p = *sdp;
}
}
if (found) {
if (*p == '/') {
if (cached_stat(p, &cst) == 0) {
found = true;
#ifdef DEBUG_META_MODE
DEBUG3(META, "%s:%u: found: %s\n",
fname, lineno, p);
fname, lineno, p);
#endif
if (!S_ISDIR(cst.cst_mode) &&
cst.cst_mtime > gn->mtime) {
DEBUG3(META, "%s:%u: file '%s' is newer than the target...\n",
fname, lineno, p);
oodate = true;
} else if (S_ISDIR(cst.cst_mode)) {
/* Update the latest directory. */
cached_realpath(p, latestdir);
}
} else if (errno == ENOENT && *p == '/' &&
strncmp(p, cwd, cwdlen) != 0) {
}
} else {
#ifdef DEBUG_META_MODE
DEBUG3(META, "%s:%u: looking for: %s ...\n",
fname, lineno, p);
#endif
rp = meta_resolve_path(fname1, sizeof(fname1), p,
lcwd, &cst, sdirs);
if (rp != NULL) {
#ifdef DEBUG_META_MODE
DEBUG3(META, "%s:%u: found: %s\n",
fname, lineno, rp);
#endif
p = rp;
found = true;
}
}
if (found) {
if (!S_ISDIR(cst.cst_mode) &&
cst.cst_mtime > gn->mtime) {
DEBUG3(META, "%s:%u: file '%s' is newer than the target...\n",
fname, lineno, p);
oodate = true;
} else if (S_ISDIR(cst.cst_mode)) {
/* Update the latest directory. */
cached_realpath(p, latestdir);
set_sdirs(sdirs, 4, latestdir, lcwd, cwd);
}
} else if (errno == ENOENT) {
if (*p != '/' || strncmp(p, cwd, cwdlen) != 0) {
/*
* A referenced file outside of CWD is missing.
* We cannot catch every eventuality here...
*/
#ifdef DEBUG_META_MODE
DEBUG3(META, "%s:%u: maybe missing: %s\n",
fname, lineno, p);
#endif
append_if_new(&missingFiles, p);
}
}
if (buf[0] == 'E') {
/* previous latestdir is no longer relevant */
strlcpy(latestdir, lcwd, sizeof latestdir);
set_sdirs(sdirs, 4, latestdir, lcwd, cwd);
}
break;
default:
@@ -1452,7 +1606,8 @@ meta_oodate(GNode *gn, bool oodate)
}
if (!oodate && buf[0] == 'L' && link_src != NULL)
goto check_link_src;
} else if (strcmp(buf, "CMD") == 0) {
break;
case META_CMD:
/*
* Compare the current command with the one in the
* meta data file.
@@ -1518,7 +1673,8 @@ meta_oodate(GNode *gn, bool oodate)
free(cmd);
cmdNode = cmdNode->next;
}
} else if (strcmp(buf, "CWD") == 0) {
break;
case META_CWD:
/*
* Check if there are extra commands now
* that weren't in the meta data file.
@@ -1534,8 +1690,13 @@ meta_oodate(GNode *gn, bool oodate)
fname, lineno, p, curdir);
oodate = true;
}
break;
}
}
free(freeit);
if (metaFilter || metaCmpFilter)
Var_Delete(gn, META_FILTER_VAR);
fclose(fp);
if (!Lst_IsEmpty(&missingFiles)) {
@@ -1543,10 +1704,12 @@ meta_oodate(GNode *gn, bool oodate)
fname, (char *)missingFiles.first->datum);
oodate = true;
}
if (!oodate && !have_filemon && filemonMissing) {
#ifdef USE_FILEMON
if (!oodate && section != META_FILEMON && filemonMissing) {
DEBUG1(META, "%s: missing filemon data\n", fname);
oodate = true;
}
#endif
} else {
if (writeMeta && (metaMissing || (gn->type & OP_META))) {
const char *cp = NULL;
+34
View File
@@ -1,3 +1,37 @@
2026-07-04 Simon J Gerraty <[email protected]>
* install-mk (MK_VERSION): 20260704
2026-07-03 Simon J Gerraty <[email protected]>
* dirdeps.mk: make use of alternation support in latest bmake
when setting .MAKE.META.IGNORE_FILTER so we can get both
Makefile.depend* and *.mk to make cache out-of-date.
2026-07-02 Simon J Gerraty <[email protected]>
* meta2deps.py: detect corrupted filemon data on Linux,
caused by lost newlines.
2026-06-21 Simon J Gerraty <[email protected]>
* install-mk (MK_VERSION): 20260621
* gendirdeps.mk: more debug output
* meta.autodep.mk: remove extra } from GENDIRDEPS_ENV
2026-06-19 Simon J Gerraty <[email protected]>
* install-mk (MK_VERSION): 20260619
* install-new.mk: for POSIX_SHELL we need .new*
rather than just .new
2026-05-21 Simon J Gerraty <[email protected]>
* meta2deps.{py,sh}: skip pathnames with spaces - not worth the pain.
2026-05-09 Simon J Gerraty <[email protected]>
* gendirdeps.mk: also apply ':S,/$,,' and ':C,/(\.[^.]*)$,\1,'
+5 -1
View File
@@ -1,4 +1,4 @@
# $Id: dirdeps.mk,v 1.178 2026/05/09 20:33:46 sjg Exp $
# $Id: dirdeps.mk,v 1.179 2026/07/03 15:46:16 sjg Exp $
# SPDX-License-Identifier: BSD-2-Clause
#
@@ -570,7 +570,11 @@ M_oneperline = @x@\\${.newline} $$x@
BUILD_DIRDEPS = no
# ignore anything but these
.if ${MAKE_VERSION} > 20260702
.MAKE.META.IGNORE_FILTER = M*{/${.MAKE.DEPENDFILE_PREFIX}*,.mk}
.else
.MAKE.META.IGNORE_FILTER = M*/${.MAKE.DEPENDFILE_PREFIX}*
.endif
dirdeps: dirdeps-cached
dirdeps-cached: ${DIRDEPS_CACHE} .MAKE
+17 -3
View File
@@ -1,4 +1,4 @@
# $Id: gendirdeps.mk,v 1.55 2026/05/09 20:46:13 sjg Exp $
# $Id: gendirdeps.mk,v 1.57 2026/06/21 19:04:57 sjg Exp $
# SPDX-License-Identifier: BSD-2-Clause
#
@@ -87,6 +87,12 @@ _debug.gendirdeps = 0
all:
.if ${_debug.gendirdeps}
.if ${DEBUG_GENDIRDEPS:M-d*}
.MAKEFLAGS: ${DEBUG_GENDIRDEPS:M-d*}
.endif
.endif
_CURDIR ?= ${.CURDIR}
_OBJDIR ?= ${.OBJDIR}
_OBJTOP ?= ${OBJTOP}
@@ -157,10 +163,12 @@ META2DEPS := ${META2DEPS}
.if ${_debug.gendirdeps} && ${DEBUG_GENDIRDEPS:Mmeta2d*} != ""
_time = time
_set_x = set -x;
_sh_x = sh -x
_py_d = -ddd
.else
_time =
_set_x =
_sh_x =
_py_d =
.endif
@@ -238,7 +246,11 @@ x != echo; for m in $$_meta_files; do echo $$m; done > meta.list
_meta_files_arg:= ${_meta_files}
.endif
dir_list != cd ${_OBJDIR} && \
.if ${_debug.gendirdeps}
.info ${RELDIR}: _meta_files_arg='${_meta_files_arg}'
.endif
dir_list != cd ${_OBJDIR} && ${_set_x} \
${META2DEPS_CMD} MACHINE=${MACHINE} \
SRCTOP=${SRCTOP} RELDIR=${RELDIR} CURDIR=${_CURDIR} \
${META2DEPS_ARGS} \
@@ -250,6 +262,9 @@ dir_list != cd ${_OBJDIR} && \
.warning Skipping ${_DEPENDFILE:S,${SRCTOP}/,,}
# we are not going to update anything
.else
.if ${_debug.gendirdeps}
.info ${RELDIR}: raw_dir_list='${dir_list}'
.endif
dpadd_dir_list=
.if !empty(DPADD)
_nonlibs := ${DPADD:T:Nlib*:N*include}
@@ -270,7 +285,6 @@ ddeps != cat ${ddep_list:O:u} | ${META2DEPS_FILTER} ${_skip_gendirdeps} \
sed ${GENDIRDEPS_SEDCMDS}
.if ${_debug.gendirdeps}
.info ${RELDIR}: raw_dir_list='${dir_list}'
.info ${RELDIR}: ddeps='${ddeps}'
.endif
dir_list += ${ddeps}
+2 -2
View File
@@ -59,7 +59,7 @@
# Simon J. Gerraty <[email protected]>
# RCSid:
# $Id: install-mk,v 1.275 2026/04/24 19:56:48 sjg Exp $
# $Id: install-mk,v 1.278 2026/07/04 16:44:08 sjg Exp $
#
# @(#) Copyright (c) 1994-2025 Simon J. Gerraty
#
@@ -69,7 +69,7 @@
# [email protected]
#
MK_VERSION=20260424
MK_VERSION=20260704
OWNER=
GROUP=
MODE=444
+2 -2
View File
@@ -1,4 +1,4 @@
# $Id: install-new.mk,v 1.9 2025/11/19 17:44:15 sjg Exp $
# $Id: install-new.mk,v 1.10 2026/06/19 19:47:03 sjg Exp $
#
# @(#) Copyright (c) 2009, Simon J. Gerraty
#
@@ -47,7 +47,7 @@ InstallNew= ${CmpCpMv}; InstallNew() { \
for new in "$$@"; do \
if test $$_t $$new; then \
if ${isPOSIX_SHELL:Ufalse}; then \
target=$${new%.new}; \
target=$${new%.new*}; \
else \
target=`expr $$new : '\(.*\).new'`; \
fi; \
+2 -2
View File
@@ -1,4 +1,4 @@
# $Id: meta.autodep.mk,v 1.72 2026/01/11 05:32:29 sjg Exp $
# $Id: meta.autodep.mk,v 1.73 2026/06/21 19:01:21 sjg Exp $
#
# @(#) Copyright (c) 2010-2025, Simon J. Gerraty
#
@@ -275,7 +275,7 @@ META_FILES = ${.MAKE.META.FILES:N.depend*}
# objects in subdirs
META_FILE_FILTER += S,${_OBJDIR}/,,:O:u
# we have to defer evaluation until the target script runs
GENDIRDEPS_ENV += META_FILES="${META_FILES:${META_FILE_FILTER:O:u:ts:}}}"
GENDIRDEPS_ENV += META_FILES="${META_FILES:${META_FILE_FILTER:O:u:ts:}}"
.if ${_debug.autodep}
.info ${_DEPENDFILE:S,${SRCTOP}/,,}: ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} xtras=${META_XTRAS}
+19 -1
View File
@@ -39,7 +39,7 @@ We only pay attention to a subset of the information in the
SPDX-License-Identifier: BSD-2-Clause
RCSid:
$Id: meta2deps.py,v 1.55 2026/01/13 04:32:45 sjg Exp $
$Id: meta2deps.py,v 1.57 2026/07/03 15:45:29 sjg Exp $
Copyright (c) 2011-2025, Simon J. Gerraty
Copyright (c) 2011-2017, Juniper Networks, Inc.
@@ -73,6 +73,13 @@ import re
import sys
import stat
# Attempt to match bogus filemon data that could potentitally be truncated by
# the unreliable Linux filemon such as:
# R 2712488 /X 2712597 0
# or
# R 1096904 /path/foo-linuR 1096904 /path/bar.py
filemon_fused_re = re.compile(r'[CDEFLMRSVWX] [0-9]+ ')
def resolve(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr):
"""
Return an absolute path, resolving via cwd or last_dir if needed.
@@ -515,6 +522,17 @@ class MetaFile:
if self.debug > 2:
print('op={} elen={} wlen={} line="{}"'.format(w[0], elen, wlen, line.strip()), file=self.debug_out)
if wlen != elen:
if wlen > elen and w[0] in 'CELMRW':
# Before assuming spaces in a pathname, make sure this
# isn't two records fused onto one line because of
# dropped data (unreliable Linux filemon).
if filemon_fused_re.search(line.split(None, 2)[2]):
raise AssertionError('corrupted filemon data: fused records (dropped newline): {} in: {}'.format(error_name, line.strip()))
# It could just be spaces in pathname.
# More trouble than its worth, just skip it.
if self.debug > 0:
print('Skipping: wrong number of words: expected {} got {} in: {}'.format(elen, wlen, line), file=self.debug_out)
continue
raise AssertionError('corrupted filemon data: wrong number of words: expected {} got {} in: {}'.format(elen, wlen, line))
pid = int(w[1])
+13 -2
View File
@@ -77,7 +77,7 @@
# RCSid:
# $Id: meta2deps.sh,v 1.26 2025/12/08 17:34:02 sjg Exp $
# $Id: meta2deps.sh,v 1.27 2026/05/22 00:33:26 sjg Exp $
# SPDX-License-Identifier: BSD-2-Clause
#
@@ -162,6 +162,10 @@ error() {
exit 1
}
warning() {
echo "WARNING: $@" >&2
}
meta2deps() {
DPDEPS=
SRCTOPS=$SRCTOP
@@ -273,8 +277,15 @@ meta2deps() {
;;
\#*) ;; # ok
[LM],) error "missing path2 in: '$op $pid $path'";;
[LMX],*" "*) error "wrong number of words in: '$op $pid $path $path2'";;
[LMX],*" "*)
warning "wrong number of words in: '$op $pid $path $path2'"
continue
;;
*,|[LMX],*) ;; # ok
[CELMRW],*)
warning "wrong number of words in: '$op $pid $path $path2'"
continue
;;
*) error "wrong number of words in: '$op $pid $path $path2'";;
esac
# we track cwd and ldir (of interest) per pid
+2 -2
View File
@@ -1,4 +1,4 @@
# $Id: sys.dirdeps.mk,v 1.20 2026/04/24 19:56:01 sjg Exp $
# $Id: sys.dirdeps.mk,v 1.21 2026/05/22 00:32:40 sjg Exp $
#
# @(#) Copyright (c) 2012-2023, Simon J. Gerraty
#
@@ -15,8 +15,8 @@
# Include from [local.]sys.mk - if doing DIRDEPS_BUILD
# we should not be here otherwise
MK_DIRDEPS_BUILD ?= yes
MK_META_AUTODEP ?= yes
# these are all implied
MK_META_AUTODEP ?= yes
MK_AUTO_OBJ ?= yes
MK_META_MODE ?= yes
MK_STAGING ?= yes
Regular → Executable
View File
File mode changed.
+17 -16
View File
@@ -1,4 +1,4 @@
/* $NetBSD: parse.c,v 1.756 2026/04/06 17:13:55 rillig Exp $ */
/* $NetBSD: parse.c,v 1.757 2026/06/09 08:27:08 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -110,7 +110,7 @@
#include "pathnames.h"
/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
MAKE_RCSID("$NetBSD: parse.c,v 1.756 2026/04/06 17:13:55 rillig Exp $");
MAKE_RCSID("$NetBSD: parse.c,v 1.757 2026/06/09 08:27:08 rillig Exp $");
/* Detects a multiple-inclusion guard in a makefile. */
typedef enum {
@@ -2838,22 +2838,23 @@ Parse_GuardEndif(void)
static char *
FindSemicolon(char *p)
{
int depth = 0;
if (strchr(p, ';') == NULL)
return NULL;
for (; *p != '\0'; p++) {
if (*p == '\\' && p[1] != '\0') {
while (*p != '\0') {
if (*p == ';')
return p;
if (*p == '$' && p[1] == '$')
p += 2;
else if (*p == '$') {
const char *cp = p;
FStr value = Var_Parse(&cp, SCOPE_GLOBAL, VARE_PARSE);
FStr_Done(&value);
p += cp - p;
} else
p++;
continue;
}
if (*p == '$' && (p[1] == '(' || p[1] == '{'))
depth++;
else if (depth > 0 && (*p == ')' || *p == '}'))
depth--;
else if (depth == 0 && *p == ';')
break;
}
return p;
return NULL;
}
static void
@@ -2864,7 +2865,7 @@ ParseDependencyLine(char *line)
{
char *semicolon = FindSemicolon(line);
if (*semicolon != '\0') {
if (semicolon != NULL) {
/* Terminate the dependency list at the ';' */
*semicolon = '\0';
shellcmd = semicolon + 1;
+16 -4
View File
@@ -1,5 +1,17 @@
make: dep.mk:11: Inconsistent operator for only-colon
make: dep.mk:13: Inconsistent operator for only-colon
make: dep.mk:18: Inconsistent operator for only-colon
in make[1] in directory "<curdir>"
make: dep.mk:20: Inconsistent operator for only-colon
in make[1] in directory "<curdir>"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
make: stopped making "parse-only-colon" in unit-tests
sub exit status 1
Making renamed-parse-semicolon-in-source out of nothing.
Making parse-semicolon-in-source from renamed-parse-semicolon-in-source.
make: Malformed expression at "$$-rest"
in make[1] in directory "<curdir>"
semicolon-in-modifier.param: after semicolon
parentheses-in-modifier.1-12-23-3: after semicolon
var-semicolon.: after semicolon
double-dollar.$-rest: after semicolon
sub exit status 2
exit status 0
+46 -8
View File
@@ -1,8 +1,15 @@
# $NetBSD: dep.mk,v 1.4 2023/06/01 07:27:30 rillig Exp $
# $NetBSD: dep.mk,v 1.6 2026/06/09 08:27:08 rillig Exp $
#
# Tests for dependency declarations, such as "target: sources".
.MAIN: all
all: .PHONY
@${MAKE} -f ${MAKEFILE} parse-only-colon || echo "sub exit status $$?"
@${MAKE} -f ${MAKEFILE} parse-semicolon-in-source
@${MAKE} -f ${MAKEFILE} parse-semicolon || echo "sub exit status $$?"
.if make(parse-only-colon)
parse-only-colon: .PHONY
# As soon as a target is defined using one of the dependency operators, it is
# restricted to this dependency operator and cannot use the others anymore.
@@ -15,16 +22,47 @@ only-colon::
# would be another error message.
only-colon:
.endif
# Before parse.c 1.158 from 2009-10-07, the parser broke dependency lines at
# the first ';', without parsing expressions as such. It interpreted the
# first ';' as the separator between the dependency and its commands, and the
# '^' as a shell command.
all: for-subst
.for file in ${.PARSEFILE}
for-subst: ${file:S;^;./;g}
@echo ".for with :S;... OK"
.endfor
.if make(parse-semicolon-in-source)
parse-semicolon-in-source: .PHONY
. for file in parse-semicolon-in-source
parse-semicolon-in-source: ${file:S;^;renamed-;g}
@echo "Making ${.TARGET} from ${.ALLSRC}."
renamed-parse-semicolon-in-source:
@echo "Making ${.TARGET} out of nothing."
. endfor
.endif
all:
# Before parse.c 1.757 from 2026-06-09, the parser counted "$(" and "${" as
# opening a brace level, and ")" and "}" as closing it. It didn't count a
# plain "(" or "{" as opening, though. This simple counting resulted in
# parse errors on modifiers containing parentheses or braces, as well as
# semicolons.
.if make(parse-semicolon)
parse-semicolon: .PHONY
semicolon-in-modifier.${:Utarget:S;target;param;}:; @echo '$@: after semicolon'
parse-semicolon: semicolon-in-modifier.param
parentheses-in-modifier.${:U123:C;(.);\1-\1;g}:; @echo '$@: after semicolon'
parse-semicolon: parentheses-in-modifier.1-12-23-3
var-semicolon.$;:; @echo '$@: after semicolon'
parse-semicolon: var-semicolon.
# Using actual dollars in target names is still tricky and not recommended,
# due to multiple levels of expansion, that's where the 8 dollars come from.
# expect: make: Malformed expression at "$$-rest"
double-dollar.$$$;-$$$$-rest:; @echo '$@: after semicolon'
parse-semicolon: double-dollar.$$$$-$$$$$$$$-rest
.endif
+2 -2
View File
@@ -1,4 +1,4 @@
# $NetBSD: dir.mk,v 1.11 2023/12/19 19:33:40 rillig Exp $
# $NetBSD: dir.mk,v 1.12 2026/07/03 15:31:35 sjg Exp $
#
# Tests for dir.c.
@@ -21,7 +21,7 @@ all: {one,two,three}
.if target({one,two,three})
. error
.endif
.if ${.ALLTARGETS:M{one,two,three}} != "{one,two,three}"
.if ${.ALLTARGETS:M\{one,two,three\}} != "{one,two,three}"
. error
.endif
+11 -1
View File
@@ -1,4 +1,4 @@
# $NetBSD: varmod-match.mk,v 1.32 2025/06/29 09:40:13 rillig Exp $
# $NetBSD: varmod-match.mk,v 1.33 2026/07/03 15:31:35 sjg Exp $
#
# Tests for the ':M' modifier, which keeps only those words that match the
# given pattern.
@@ -388,3 +388,13 @@ WORDS= [x- x x- y yyyyy
.if ${:U:${:UM\\\:\\}}
. error
.endif
# :M supports alternation
.if ${/bin/sh ../Makefile.inc cat .../mk/sys.mk:L:M*{Makefile*,.mk}} != "../Makefile.inc .../mk/sys.mk"
. error
.endif
# :M supports alternation
.if ${{a} one and two {o} yes:L:M\{{a,e,i,o,u}\}} != "{a} {o}"
. error
.endif
+40 -12
View File
@@ -1,4 +1,4 @@
/* $NetBSD: var.c,v 1.1180 2026/04/06 17:13:55 rillig Exp $ */
/* $NetBSD: var.c,v 1.1181 2026/07/03 15:31:35 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -145,7 +145,7 @@
#endif
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
MAKE_RCSID("$NetBSD: var.c,v 1.1180 2026/04/06 17:13:55 rillig Exp $");
MAKE_RCSID("$NetBSD: var.c,v 1.1181 2026/07/03 15:31:35 sjg Exp $");
/*
* Variables are defined using one of the VAR=value assignments. Their
@@ -2822,7 +2822,7 @@ ParseModifier_Match(const char **pp, const ModChain *ch)
}
struct ModifyWord_MatchArgs {
const char *pattern;
StringList patterns;
bool neg;
bool error_reported;
};
@@ -2831,17 +2831,25 @@ static void
ModifyWord_Match(Substring word, SepBuf *buf, void *data)
{
struct ModifyWord_MatchArgs *args = data;
StringListNode *ln;
StrMatchResult res;
const char *pattern;
assert(word.end[0] == '\0'); /* assume null-terminated word */
res = Str_Match(word.start, args->pattern);
if (res.error != NULL && !args->error_reported) {
args->error_reported = true;
Parse_Error(PARSE_FATAL,
"%s in pattern \"%s\" of modifier \"%s\"",
res.error, args->pattern, args->neg ? ":N" : ":M");
for (ln = args->patterns.first; ln != NULL; ln = ln->next) {
pattern = ln->datum;
res = Str_Match(word.start, pattern);
if (res.error != NULL && !args->error_reported) {
args->error_reported = true;
Parse_Error(PARSE_FATAL,
"%s in pattern \"%s\" of modifier \"%s\"",
res.error, pattern, args->neg ? ":N" : ":M");
}
if (res.matched != args->neg) {
SepBuf_AddSubstring(buf, word);
break;
}
}
if (res.matched != args->neg)
SepBuf_AddSubstring(buf, word);
}
/* :Mpattern or :Npattern */
@@ -2855,10 +2863,30 @@ ApplyModifier_Match(const char **pp, ModChain *ch)
if (ModChain_ShouldEval(ch)) {
struct ModifyWord_MatchArgs args;
args.pattern = pattern;
const char *brace;
Lst_Init(&args.patterns);
if (mod == 'N')
brace = NULL; /* not supported */
else
for (brace = strchr(pattern, '{'); brace != NULL;
brace = strchr(++brace, '{')) {
if (brace == pattern
|| (brace[-1] != '\\' && brace[-1] != '$'))
break;
}
if (brace)
ExpandCurly(pattern, brace, NULL, &args.patterns);
else
Lst_Append(&args.patterns, pattern);
args.neg = mod == 'N';
args.error_reported = false;
ModifyWords(ch, ModifyWord_Match, &args, ch->oneBigWord);
if (brace)
Lst_DoneFree(&args.patterns);
else
Lst_Done(&args.patterns);
}
free(pattern);