On Tue, Aug 08, 2023 at 12:51:43PM +0200, Marc Espie wrote: > Here's a revised diff (reordered plus actual use of the boolean) > plus concrete example use for bsd.port.mk (disregarding the fact > _ALL_VARIABLES would have to move *after* all MASTER_SITES have been defined.
I tested this on a small scale and it looks okay to me. ok thfr@ for var.c part; see other email for the bsd.port.mk part. > Index: var.c > =================================================================== > RCS file: /cvs/src/usr.bin/make/var.c,v > retrieving revision 1.104 > diff -u -p -r1.104 var.c > --- var.c 9 Jun 2022 13:13:14 -0000 1.104 > +++ var.c 8 Aug 2023 10:48:05 -0000 > @@ -104,6 +104,8 @@ static char varNoError[] = ""; > bool errorIsOkay; > static bool checkEnvFirst; /* true if environment should be searched for > * variables before the global context */ > + /* do we need to recompute varname_list */ > +static bool varname_list_changed = true; > > void > Var_setCheckEnvFirst(bool yes) > @@ -222,6 +224,7 @@ typedef struct Var_ { > #define VAR_FROM_ENV 8 /* Special source: environment */ > #define VAR_SEEN_ENV 16 /* No need to go look up environment again */ > #define VAR_IS_SHELL 32 /* Magic behavior */ > +#define VAR_IS_NAMES 1024 /* Very expensive, only defined when needed */ > /* XXX there are also some flag values which are part of the visible API > * and thus defined inside var.h, don't forget to look there if you want > * to define some new flags ! > @@ -231,6 +234,8 @@ typedef struct Var_ { > char name[1]; /* the variable's name */ > } Var; > > +/* for GNU make compatibility */ > +#define VARNAME_LIST ".VARIABLES" > > static struct ohash_info var_info = { > offsetof(Var, name), > @@ -245,10 +250,11 @@ static void fill_from_env(Var *); > static Var *create_var(const char *, const char *); > static void var_set_initial_value(Var *, const char *); > static void var_set_value(Var *, const char *); > -#define var_get_value(v) ((v)->flags & VAR_EXEC_LATER ? \ > - var_exec_cmd(v) : \ > - Buf_Retrieve(&((v)->val))) > -static char *var_exec_cmd(Var *); > +static char *var_get_value(Var *); > +static void var_exec_cmd(Var *); > +static void varname_list_retrieve(Var *); > + > + > static void var_append_value(Var *, const char *); > static void poison_check(Var *); > static void var_set_append(const char *, const char *, const char *, int, > bool); > @@ -423,6 +429,7 @@ var_set_initial_value(Var *v, const char > len = strlen(val); > Buf_Init(&(v->val), len+1); > Buf_AddChars(&(v->val), len, val); > + varname_list_changed = true; > } > > /* Normal version of var_set_value(), to be called after variable is fully > @@ -440,6 +447,16 @@ var_set_value(Var *v, const char *val) > } > } > > +static char * > +var_get_value(Var *v) > +{ > + if (v->flags & VAR_IS_NAMES) > + varname_list_retrieve(v); > + else if (v->flags & VAR_EXEC_LATER) > + var_exec_cmd(v); > + return Buf_Retrieve(&(v->val)); > +} > + > /* Add to a variable, insert a separating space if the variable was already > * defined. > */ > @@ -628,6 +645,7 @@ Var_Deletei(const char *name, const char > > ohash_remove(&global_variables, slot); > delete_var(v); > + varname_list_changed = true; > } > > /* Set or add a global variable, either to VAR_CMD or VAR_GLOBAL. > @@ -687,7 +705,7 @@ Var_Appendi_with_ctxt(const char *name, > var_set_append(name, ename, val, ctxt, true); > } > > -static char * > +static void > var_exec_cmd(Var *v) > { > char *arg = Buf_Retrieve(&(v->val)); > @@ -699,7 +717,30 @@ var_exec_cmd(Var *v) > var_set_value(v, res1); > free(res1); > v->flags &= ~VAR_EXEC_LATER; > - return Buf_Retrieve(&(v->val)); > +} > + > +static void > +varname_list_retrieve(Var *v) > +{ > + unsigned int i; > + void *e; > + bool first = true; > + > + if (!varname_list_changed) > + return; > + for (e = ohash_first(&global_variables, &i); e != NULL; > + e = ohash_next(&global_variables, &i)) { > + Var *v2 = e; > + if (v2->flags & VAR_DUMMY) > + continue; > + > + if (first) > + var_set_value(v, v2->name); > + else > + var_append_value(v, v2->name); > + first = false; > + } > + varname_list_changed = false; > } > > /* XXX different semantics for Var_Valuei() and Var_Definedi(): > @@ -1339,6 +1380,19 @@ set_magic_shell_variable() > v->flags = VAR_IS_SHELL | VAR_SEEN_ENV; > } > > +static void > +set_magic_name_list_variable() > +{ > + const char *name = VARNAME_LIST; > + const char *ename = NULL; > + uint32_t k; > + Var *v; > + > + k = ohash_interval(name, &ename); > + v = find_global_var_without_env(name, ename, k); > + var_set_initial_value(v, ""); > + v->flags = VAR_IS_NAMES; > +} > /* > * Var_Init > * Initialize the module > @@ -1348,11 +1402,10 @@ Var_Init(void) > { > ohash_init(&global_variables, 10, &var_info); > set_magic_shell_variable(); > - > + set_magic_name_list_variable(); > > errorIsOkay = true; > Var_setCheckEnvFirst(false); > - > VarModifiers_Init(); > Buf_Init(&subst_buffer, MAKE_BSIZE); > } > > > > bsd.port.mk POC: > > Index: bsd.port.mk > =================================================================== > RCS file: /cvs/ports/infrastructure/mk/bsd.port.mk,v > retrieving revision 1.1592 > diff -u -p -r1.1592 bsd.port.mk > --- bsd.port.mk 13 Jun 2023 10:28:40 -0000 1.1592 > +++ bsd.port.mk 8 Aug 2023 10:49:14 -0000 > @@ -118,9 +118,8 @@ _ALL_VARIABLES_PER_ARCH = > # consumers of (dump-vars) include sqlports generation and dpb > # dpb doesn't need everything, those are speed optimizations > .if ${DPB:L:Mfetch} || ${DPB:L:Mall} > -_ALL_VARIABLES += DISTFILES PATCHFILES SUPDISTFILES DIST_SUBDIR MASTER_SITES > \ > - MASTER_SITES0 MASTER_SITES1 MASTER_SITES2 MASTER_SITES3 MASTER_SITES4 \ > - MASTER_SITES5 MASTER_SITES6 MASTER_SITES7 MASTER_SITES8 MASTER_SITES9 \ > +_ALL_VARIABLES += DISTFILES PATCHFILES SUPDISTFILES DIST_SUBDIR \ > + ${.VARIABLES:MMASTER_SITES*:NMASTER_SITES_*} \ > CHECKSUM_FILE FETCH_MANUALLY MISSING_FILES PERMIT_DISTFILES > .endif > .if ${DPB:L:Mtest} || ${DPB:L:Mall}