Module Name: src Committed By: sjg Date: Thu Jan 27 06:02:59 UTC 2022
Modified Files: src/usr.bin/make: main.c make.1 make.h meta.c parse.c var.c src/usr.bin/make/unit-tests: meta-cmd-cmp.exp meta-cmd-cmp.mk Log Message: Allow local variable assignments in dependency lines The variable is set in the context of the target. This syntax has been supported by gmake for ~ever. If necessary a makefile can set .MAKE.TARGET_LOCAL_VARIABLES=false to disable this. Expose GetBooleanExpr so parse.c can use it. To generate a diff of this commit: cvs rdiff -u -r1.575 -r1.576 src/usr.bin/make/main.c cvs rdiff -u -r1.301 -r1.302 src/usr.bin/make/make.1 cvs rdiff -u -r1.290 -r1.291 src/usr.bin/make/make.h cvs rdiff -u -r1.194 -r1.195 src/usr.bin/make/meta.c cvs rdiff -u -r1.655 -r1.656 src/usr.bin/make/parse.c cvs rdiff -u -r1.1005 -r1.1006 src/usr.bin/make/var.c cvs rdiff -u -r1.2 -r1.3 src/usr.bin/make/unit-tests/meta-cmd-cmp.exp cvs rdiff -u -r1.3 -r1.4 src/usr.bin/make/unit-tests/meta-cmd-cmp.mk Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/make/main.c diff -u src/usr.bin/make/main.c:1.575 src/usr.bin/make/main.c:1.576 --- src/usr.bin/make/main.c:1.575 Sat Jan 22 18:59:23 2022 +++ src/usr.bin/make/main.c Thu Jan 27 06:02:59 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.575 2022/01/22 18:59:23 rillig Exp $ */ +/* $NetBSD: main.c,v 1.576 2022/01/27 06:02:59 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -111,7 +111,7 @@ #include "trace.h" /* "@(#)main.c 8.3 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: main.c,v 1.575 2022/01/22 18:59:23 rillig Exp $"); +MAKE_RCSID("$NetBSD: main.c,v 1.576 2022/01/27 06:02:59 sjg Exp $"); #if defined(MAKE_NATIVE) && !defined(lint) __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 " "The Regents of the University of California. " @@ -842,7 +842,7 @@ PrintVar(const char *varname, bool expan * If set, anything that looks or smells like "No", "False", "Off", "0", etc. * is false, otherwise true. */ -static bool +bool GetBooleanExpr(const char *expr, bool fallback) { char *value; Index: src/usr.bin/make/make.1 diff -u src/usr.bin/make/make.1:1.301 src/usr.bin/make/make.1:1.302 --- src/usr.bin/make/make.1:1.301 Thu Jan 13 04:51:50 2022 +++ src/usr.bin/make/make.1 Thu Jan 27 06:02:59 2022 @@ -1,4 +1,4 @@ -.\" $NetBSD: make.1,v 1.301 2022/01/13 04:51:50 sjg Exp $ +.\" $NetBSD: make.1,v 1.302 2022/01/27 06:02:59 sjg Exp $ .\" .\" Copyright (c) 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" from: @(#)make.1 8.4 (Berkeley) 3/19/94 .\" -.Dd January 12, 2022 +.Dd January 21, 2022 .Dt MAKE 1 .Os .Sh NAME @@ -691,10 +691,27 @@ Variables defined as part of the command Variables that are defined specific to a certain target. .El .Pp -Local variables are all built in and their values vary magically from -target to target. -It is not currently possible to define new local variables. -The seven local variables are as follows: +Local variables can be set on a dependency line, if +.Va .MAKE.TARGET_LOCAL_VARIABLES , +is not set to +.Ql false . +The rest of the line +(which will already have had Global variables expanded), +is the variable value. +For example: +.Bd -literal -offset indent +COMPILER_WRAPPERS+= ccache distcc icecc + +${OBJS}: .MAKE.META.CMP_FILTER=${COMPILER_WRAPPERS:S,^,N,} +.Ed +.Pp +Only the targets +.Ql ${OBJS} +will be impacted by that filter (in "meta" mode) and +simply enabling/disabling any of the wrappers will not render all +of those targets out-of-date. +.Pp +The seven built-in local variables are as follows: .Bl -tag -width ".ARCHIVE" -offset indent .It Va .ALLSRC The list of all sources for this target; also known as @@ -846,6 +863,11 @@ For example: would produce tokens like .Ql ---make[1234] target --- making it easier to track the degree of parallelism being achieved. +.It .MAKE.TARGET_LOCAL_VARIABLES +If set to +.Ql false , +apparent variable assignments in dependency lines are +treated as normal sources. .It Ev MAKEFLAGS The environment variable .Ql Ev MAKEFLAGS Index: src/usr.bin/make/make.h diff -u src/usr.bin/make/make.h:1.290 src/usr.bin/make/make.h:1.291 --- src/usr.bin/make/make.h:1.290 Sun Jan 23 22:12:16 2022 +++ src/usr.bin/make/make.h Thu Jan 27 06:02:59 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: make.h,v 1.290 2022/01/23 22:12:16 rillig Exp $ */ +/* $NetBSD: make.h,v 1.291 2022/01/27 06:02:59 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -826,6 +826,7 @@ void execDie(const char *, const char *) char *getTmpdir(void) MAKE_ATTR_USE; bool ParseBoolean(const char *, bool) MAKE_ATTR_USE; const char *cached_realpath(const char *, char *); +bool GetBooleanExpr(const char *, bool); /* parse.c */ void Parse_Init(void); Index: src/usr.bin/make/meta.c diff -u src/usr.bin/make/meta.c:1.194 src/usr.bin/make/meta.c:1.195 --- src/usr.bin/make/meta.c:1.194 Wed Jan 26 12:41:26 2022 +++ src/usr.bin/make/meta.c Thu Jan 27 06:02:59 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: meta.c,v 1.194 2022/01/26 12:41:26 rillig Exp $ */ +/* $NetBSD: meta.c,v 1.195 2022/01/27 06:02:59 sjg Exp $ */ /* * Implement 'meta' mode. @@ -1060,14 +1060,14 @@ meta_filter_cmd(Buffer *buf, GNode *gn, } static int -meta_cmd_cmp(GNode *gn, char *a, char *b) +meta_cmd_cmp(GNode *gn, char *a, char *b, bool filter) { static bool once = false; static Buffer buf; int rc; rc = strcmp(a, b); - if (rc == 0 || !metaCmpFilter) + if (rc == 0 || !filter) return rc; if (!once) { once = true; @@ -1105,6 +1105,7 @@ meta_oodate(GNode *gn, bool oodate) bool needOODATE = false; StringList missingFiles; bool have_filemon = false; + bool cmp_filter; if (oodate) return oodate; /* we're done */ @@ -1164,6 +1165,9 @@ meta_oodate(GNode *gn, bool oodate) /* we want to track all the .meta we read */ Global_Append(".MAKE.META.FILES", fname); + cmp_filter = metaCmpFilter ? metaCmpFilter : + Var_Exists(gn, MAKE_META_CMP_FILTER); + cmdNode = gn->commands.first; while (!oodate && (x = fgetLine(&buf, &bufsz, 0, fp)) > 0) { lineno++; @@ -1556,7 +1560,7 @@ meta_oodate(GNode *gn, bool oodate) if (p != NULL && !hasOODATE && !(gn->type & OP_NOMETA_CMP) && - (meta_cmd_cmp(gn, p, cmd) != 0)) { + (meta_cmd_cmp(gn, p, cmd, cmp_filter) != 0)) { DEBUG4(META, "%s: %d: a build command has changed\n%s\nvs\n%s\n", fname, lineno, p, cmd); if (!metaIgnoreCMDs) Index: src/usr.bin/make/parse.c diff -u src/usr.bin/make/parse.c:1.655 src/usr.bin/make/parse.c:1.656 --- src/usr.bin/make/parse.c:1.655 Sat Jan 22 18:59:23 2022 +++ src/usr.bin/make/parse.c Thu Jan 27 06:02:59 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: parse.c,v 1.655 2022/01/22 18:59:23 rillig Exp $ */ +/* $NetBSD: parse.c,v 1.656 2022/01/27 06:02:59 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -106,7 +106,7 @@ #include "pathnames.h" /* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: parse.c,v 1.655 2022/01/22 18:59:23 rillig Exp $"); +MAKE_RCSID("$NetBSD: parse.c,v 1.656 2022/01/27 06:02:59 sjg Exp $"); /* * A file being read. @@ -172,6 +172,24 @@ typedef enum ParseSpecial { typedef List SearchPathList; typedef ListNode SearchPathListNode; + +typedef enum VarAssignOp { + VAR_NORMAL, /* = */ + VAR_APPEND, /* += */ + VAR_DEFAULT, /* ?= */ + VAR_SUBST, /* := */ + VAR_SHELL /* != or :sh= */ +} VarAssignOp; + +typedef struct VarAssign { + char *varname; /* unexpanded */ + VarAssignOp op; + const char *value; /* unexpanded */ +} VarAssign; + +static bool Parse_IsVar(const char *, VarAssign *); +static void Parse_Var_Keep(VarAssign *, GNode *); + /* * The target to be made if no targets are specified in the command line. * This is the first target defined in any of the makefiles. @@ -1263,12 +1281,48 @@ ParseDependencySourcesSpecial(char *star } } +static void +LinkSourceVar(GNode *pgn, VarAssign *var) +{ + Parse_Var_Keep(var, pgn); +} + +static void +LinkVarToTargets(VarAssign *var) +{ + GNodeListNode *ln; + + for (ln = targets->first; ln != NULL; ln = ln->next) + LinkSourceVar(ln->datum, var); + +} + static bool ParseDependencySourcesMundane(char *start, ParseSpecial special, GNodeType targetAttr) { while (*start != '\0') { char *end = start; + VarAssign var; + + /* + * Check for local variable assignment, + * rest of the line is the value. + */ + if (Parse_IsVar(start, &var)) { + /* + * Check if this makefile has disabled + * setting local variables. + */ + bool target_vars = GetBooleanExpr("${.MAKE.TARGET_LOCAL_VARIABLES}", true); + + if (target_vars) + LinkVarToTargets(&var); + free(var.varname); + if (target_vars) + return true; + } + /* * The targets take real sources, so we must beware of archive * specifications (i.e. things with left parentheses in them) @@ -1421,20 +1475,6 @@ out: Lst_Free(paths); } -typedef enum VarAssignOp { - VAR_NORMAL, /* = */ - VAR_APPEND, /* += */ - VAR_DEFAULT, /* ?= */ - VAR_SUBST, /* := */ - VAR_SHELL /* != or :sh= */ -} VarAssignOp; - -typedef struct VarAssign { - char *varname; /* unexpanded */ - VarAssignOp op; - const char *value; /* unexpanded */ -} VarAssign; - /* * Determine the assignment operator and adjust the end of the variable * name accordingly. @@ -1685,7 +1725,7 @@ VarAssignSpecial(const char *name, const /* Perform the variable assignment in the given scope. */ static void -Parse_Var(VarAssign *var, GNode *scope) +Parse_Var_Keep(VarAssign *var, GNode *scope) { FStr avalue; /* actual value (maybe expanded) */ @@ -1694,7 +1734,12 @@ Parse_Var(VarAssign *var, GNode *scope) VarAssignSpecial(var->varname, avalue.str); FStr_Done(&avalue); } - +} + +static void +Parse_Var(VarAssign *var, GNode *scope) +{ + Parse_Var_Keep(var, scope); free(var->varname); } Index: src/usr.bin/make/var.c diff -u src/usr.bin/make/var.c:1.1005 src/usr.bin/make/var.c:1.1006 --- src/usr.bin/make/var.c:1.1005 Mon Jan 24 22:59:49 2022 +++ src/usr.bin/make/var.c Thu Jan 27 06:02:59 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: var.c,v 1.1005 2022/01/24 22:59:49 rillig Exp $ */ +/* $NetBSD: var.c,v 1.1006 2022/01/27 06:02:59 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -139,7 +139,7 @@ #include "metachar.h" /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: var.c,v 1.1005 2022/01/24 22:59:49 rillig Exp $"); +MAKE_RCSID("$NetBSD: var.c,v 1.1006 2022/01/27 06:02:59 sjg Exp $"); /* * Variables are defined using one of the VAR=value assignments. Their @@ -315,7 +315,8 @@ static bool save_dollars = true; * be simpler or more complex than the current implementation. * * Each target has its own scope, containing the 7 target-local variables - * .TARGET, .ALLSRC, etc. No other variables are in these scopes. + * .TARGET, .ALLSRC, etc. Variables set on dependency lines also go in + * this scope. */ GNode *SCOPE_CMDLINE; Index: src/usr.bin/make/unit-tests/meta-cmd-cmp.exp diff -u src/usr.bin/make/unit-tests/meta-cmd-cmp.exp:1.2 src/usr.bin/make/unit-tests/meta-cmd-cmp.exp:1.3 --- src/usr.bin/make/unit-tests/meta-cmd-cmp.exp:1.2 Fri Jan 14 19:31:44 2022 +++ src/usr.bin/make/unit-tests/meta-cmd-cmp.exp Thu Jan 27 06:02:59 2022 @@ -47,4 +47,7 @@ Skipping meta for .END: .SPECIAL filter2: `.meta-cmd-cmp.filter' is up to date. Skipping meta for .END: .SPECIAL +filter3: +`.meta-cmd-cmp.filter' is up to date. +Skipping meta for .END: .SPECIAL exit status 0 Index: src/usr.bin/make/unit-tests/meta-cmd-cmp.mk diff -u src/usr.bin/make/unit-tests/meta-cmd-cmp.mk:1.3 src/usr.bin/make/unit-tests/meta-cmd-cmp.mk:1.4 --- src/usr.bin/make/unit-tests/meta-cmd-cmp.mk:1.3 Fri Jan 14 19:31:44 2022 +++ src/usr.bin/make/unit-tests/meta-cmd-cmp.mk Thu Jan 27 06:02:59 2022 @@ -1,4 +1,4 @@ -# $NetBSD: meta-cmd-cmp.mk,v 1.3 2022/01/14 19:31:44 sjg Exp $ +# $NetBSD: meta-cmd-cmp.mk,v 1.4 2022/01/27 06:02:59 sjg Exp $ # # Tests META_MODE command line comparison # @@ -9,7 +9,7 @@ tf:= .${.PARSEFILE:R} .if ${.TARGETS:Nall} == "" -all: prep one two change1 change2 filter0 filter1 filter2 post +all: prep one two change1 change2 filter0 filter1 filter2 filter3 post CLEANFILES= ${tf}* @@ -36,13 +36,18 @@ ${tf}.cmp2: @echo FLAGS2=${FLAGS2:Uempty} > $@ @echo This line not compared FLAGS=${FLAGS:Uempty} ${.OODATE:MNOMETA_CMP} -CCACHE= ccache +COMPILER_WRAPPERS+= ccache distcc icecc +WRAPPER?= ccache .ifdef WITH_CMP_FILTER -.MAKE.META.CMP_FILTER += Nccache Ndistcc +.MAKE.META.CMP_FILTER+= ${COMPILER_WRAPPERS:S,^,N,} +.endif +.ifdef WITH_LOCAL_CMP_FILTER +# local variable +${tf}.filter: .MAKE.META.CMP_FILTER= ${COMPILER_WRAPPERS:S,^,N,} .endif ${tf}.filter: - @echo ${CCACHE} cc -c foo.c > $@ + @echo ${WRAPPER} cc -c foo.c > $@ # these do the same one two: .PHONY @@ -63,12 +68,17 @@ filter0: .PHONY filter1: .PHONY @echo $@: - @${.MAKE} -dM -r -C ${.CURDIR} -f ${MAKEFILE} CCACHE= ${filter_tests} + @${.MAKE} -dM -r -C ${.CURDIR} -f ${MAKEFILE} WRAPPER= ${filter_tests} filter2: .PHONY @echo $@: @${.MAKE} -dM -r -C ${.CURDIR} -f ${MAKEFILE} -DWITH_CMP_FILTER \ - CCACHE=distcc ${filter_tests} + WRAPPER=distcc ${filter_tests} + +filter3: .PHONY + @echo $@: + @${.MAKE} -dM -r -C ${.CURDIR} -f ${MAKEFILE} -DWITH_LOCAL_CMP_FILTER \ + WRAPPER=icecc ${filter_tests} # don't let gcov mess up the results .MAKE.META.IGNORE_PATTERNS+= *.gcda