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

Reply via email to