Module Name:    src
Committed By:   sjg
Date:           Fri Jun  3 01:16:27 UTC 2016

Modified Files:
        src/usr.bin/make: make.1 meta.c

Log Message:
Refactor the logic for deciding when a .meta file is needed.

Both meta_create() and meta_oodate() now share meta_needed()
to indicate if a .meta file is needed.

This allows for deciding that missing .meta file is cause of out-of-date.
The new knob 'missing-meta' controlls this, and is off by default
since the side effect files of generators like yacc will typically need
.NOMETA to avoid problems.

This however makes it much easier for folk to switch back and forth
with meta mode (eg. FreeBSD's normal build can leverage meta mode for
improved reliablility without need to clean).

Also if .MAKE.MODE does not contain 'nofilemon', the knob
'missing-filemon' allows control as to whether missing filemon data
should cause the target to be out-of-date.
Again off by default.


To generate a diff of this commit:
cvs rdiff -u -r1.257 -r1.258 src/usr.bin/make/make.1
cvs rdiff -u -r1.57 -r1.58 src/usr.bin/make/meta.c

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/make.1
diff -u src/usr.bin/make/make.1:1.257 src/usr.bin/make/make.1:1.258
--- src/usr.bin/make/make.1:1.257	Tue May 10 23:45:45 2016
+++ src/usr.bin/make/make.1	Fri Jun  3 01:16:27 2016
@@ -1,4 +1,4 @@
-.\"	$NetBSD: make.1,v 1.257 2016/05/10 23:45:45 sjg Exp $
+.\"	$NetBSD: make.1,v 1.258 2016/06/03 01:16:27 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 10, 2016
+.Dd June 2, 2016
 .Dt MAKE 1
 .Os
 .Sh NAME
@@ -846,7 +846,7 @@ Can affect the mode that
 .Nm
 runs in.
 It can contain a number of keywords:
-.Bl -hang -width ignore-cmd
+.Bl -hang -width mising-filemon=bf.
 .It Pa compat
 Like
 .Fl B ,
@@ -870,6 +870,17 @@ will not create .meta files in
 This can be overridden by setting
 .Va bf
 to a value which represents True.
+.It Pa missing-meta= Ar bf
+If
+.Va bf
+is True, then a missing .meta file makes the target out-of-date.
+.It Pa missing-filemon= Ar bf
+If
+.Va bf
+is True, then missing filemon data makes the target out-of-date.
+.It Pa nofilemon
+Do not use
+.Xr filemon 4
 .It Pa env
 For debugging, it can be useful to include the environment
 in the .meta file.

Index: src/usr.bin/make/meta.c
diff -u src/usr.bin/make/meta.c:1.57 src/usr.bin/make/meta.c:1.58
--- src/usr.bin/make/meta.c:1.57	Thu May 12 20:28:34 2016
+++ src/usr.bin/make/meta.c	Fri Jun  3 01:16:27 2016
@@ -1,4 +1,4 @@
-/*      $NetBSD: meta.c,v 1.57 2016/05/12 20:28:34 sjg Exp $ */
+/*      $NetBSD: meta.c,v 1.58 2016/06/03 01:16:27 sjg Exp $ */
 
 /*
  * Implement 'meta' mode.
@@ -69,6 +69,8 @@ static char *metaIgnorePathsStr;	/* stri
 Boolean useMeta = FALSE;
 static Boolean useFilemon = FALSE;
 static Boolean writeMeta = FALSE;
+static Boolean metaMissing = FALSE;	/* oodate if missing */
+static Boolean filemonMissing = FALSE;	/* oodate if missing */
 static Boolean metaEnv = FALSE;		/* don't save env unless asked */
 static Boolean metaVerbose = FALSE;
 static Boolean metaIgnoreCMDs = FALSE;	/* ignore CMDs in .meta files */
@@ -233,24 +235,13 @@ eat_dots(char *buf, size_t bufsz, int do
 static char *
 meta_name(struct GNode *gn, char *mname, size_t mnamelen,
 	  const char *dname,
-	  const char *tname)
+	  const char *tname,
+	  const char *cwd)
 {
     char buf[MAXPATHLEN];
-    char cwd[MAXPATHLEN];
     char *rp;
     char *cp;
     char *tp;
-    char *p[4];				/* >= number of possible uses */
-    int i;
-
-    i = 0;
-    if (!dname)
-	dname = Var_Value(".OBJDIR", gn, &p[i++]);
-    if (!tname)
-	tname = Var_Value(TARGET, gn, &p[i++]);
-
-    if (realpath(dname, cwd))
-	dname = cwd;
 
     /*
      * Weed out relative paths from the target file name.
@@ -305,9 +296,6 @@ meta_name(struct GNode *gn, char *mname,
 	}
     }
     free(tp);
-    for (i--; i >= 0; i--) {
-	free(p[i]);
-    }
     return (mname);
 }
 
@@ -387,29 +375,26 @@ printCMD(void *cmdp, void *mfpp)
  */
 #define SKIP_META_TYPE(_type) do { \
     if ((gn->type & __CONCAT(OP_, _type))) {	\
-	if (DEBUG(META)) { \
+	if (verbose) { \
 	    fprintf(debug_file, "Skipping meta for %s: .%s\n", \
 		    gn->name, __STRING(_type));		       \
 	} \
-	return (NULL); \
+	return FALSE; \
     } \
 } while (0)
 
-static FILE *
-meta_create(BuildMon *pbm, GNode *gn)
+
+/*
+ * Do we need/want a .meta file ?
+ */
+static Boolean
+meta_needed(GNode *gn, const char *dname, const char *tname,
+	     char *objdir, int verbose)
 {
-    meta_file_t mf;
-    char buf[MAXPATHLEN];
-    char objdir[MAXPATHLEN];
-    char **ptr;
-    const char *dname;
-    const char *tname;
-    char *fname;
-    const char *cp;
-    char *p[4];				/* >= possible uses */
-    int i;
     struct stat fs;
 
+    if (verbose)
+	verbose = DEBUG(META);
     
     /* This may be a phony node which we don't want meta data for... */
     /* Skip .meta for .BEGIN, .END, .ERROR etc as well. */
@@ -422,26 +407,29 @@ meta_create(BuildMon *pbm, GNode *gn)
 	SKIP_META_TYPE(MAKE);
     }
 
-    mf.fp = NULL;
-    
-    i = 0;
-    
-    dname = Var_Value(".OBJDIR", gn, &p[i++]);
-    tname = Var_Value(TARGET, gn, &p[i++]);
-    
-    /* The object directory may not exist. Check it.. */
-    if (stat(dname, &fs) != 0) {
-	if (DEBUG(META))
-	    fprintf(debug_file, "Skipping meta for %s: no .OBJDIR\n",
-		    gn->name);
-	goto out;
-    }
     /* Check if there are no commands to execute. */
     if (Lst_IsEmpty(gn->commands)) {
-	if (DEBUG(META))
+	if (verbose)
 	    fprintf(debug_file, "Skipping meta for %s: no commands\n",
 		    gn->name);
-	goto out;
+	return FALSE;
+    }
+    if ((gn->type & (OP_META|OP_SUBMAKE)) == OP_SUBMAKE) {
+	/* OP_SUBMAKE is a bit too aggressive */
+	if (Lst_ForEach(gn->commands, is_submake, gn)) {
+	    if (DEBUG(META))
+		fprintf(debug_file, "Skipping meta for %s: .SUBMAKE\n",
+			gn->name);
+	    return FALSE;
+	}
+    }
+
+    /* The object directory may not exist. Check it.. */
+    if (stat(dname, &fs) != 0) {
+	if (verbose)
+	    fprintf(debug_file, "Skipping meta for %s: no .OBJDIR\n",
+		    gn->name);
+	return FALSE;
     }
 
     /* make sure these are canonical */
@@ -450,20 +438,39 @@ meta_create(BuildMon *pbm, GNode *gn)
 
     /* If we aren't in the object directory, don't create a meta file. */
     if (!metaCurdirOk && strcmp(curdir, dname) == 0) {
-	if (DEBUG(META))
+	if (verbose)
 	    fprintf(debug_file, "Skipping meta for %s: .OBJDIR == .CURDIR\n",
 		    gn->name);
-	goto out;
-    }
-    if (!(gn->type & OP_META)) {
-	/* We do not generate .meta files for sub-makes */
-	if (Lst_ForEach(gn->commands, is_submake, gn)) {
-	    if (DEBUG(META))
-		fprintf(debug_file, "Skipping meta for %s: .MAKE\n",
-			gn->name);
-	    goto out;
-	}
+	return FALSE;
     }
+    return TRUE;
+}
+
+    
+static FILE *
+meta_create(BuildMon *pbm, GNode *gn)
+{
+    meta_file_t mf;
+    char buf[MAXPATHLEN];
+    char objdir[MAXPATHLEN];
+    char **ptr;
+    const char *dname;
+    const char *tname;
+    char *fname;
+    const char *cp;
+    char *p[4];				/* >= possible uses */
+    int i;
+
+    mf.fp = NULL;
+    i = 0;
+
+    dname = Var_Value(".OBJDIR", gn, &p[i++]);
+    tname = Var_Value(TARGET, gn, &p[i++]);
+
+    /* if this succeeds objdir is realpath of dname */
+    if (!meta_needed(gn, dname, tname, objdir, TRUE))
+	goto out;
+    dname = objdir;
 
     if (metaVerbose) {
 	char *mp;
@@ -488,7 +495,7 @@ meta_create(BuildMon *pbm, GNode *gn)
 	goto out;
 
     fname = meta_name(gn, pbm->meta_fname, sizeof(pbm->meta_fname),
-		      dname, tname);
+		      dname, tname, objdir);
 
 #ifdef DEBUG_META_MODE
     if (DEBUG(META))
@@ -557,6 +564,10 @@ meta_init(void)
 }
 
 
+#define get_mode_bf(bf, token) \
+    if ((cp = strstr(make_mode, token))) \
+	bf = boolValue(&cp[sizeof(token) - 1])
+
 /*
  * Initialization we need after reading makefiles.
  */
@@ -579,17 +590,13 @@ meta_mode_init(const char *make_mode)
 	    writeMeta = FALSE;
 	if (strstr(make_mode, "nofilemon"))
 	    useFilemon = FALSE;
-	if ((cp = strstr(make_mode, "curdirok="))) {
-	    metaCurdirOk = boolValue(&cp[9]);
-	}
-	if ((cp = strstr(make_mode, "silent="))) {
-	    metaSilent = boolValue(&cp[7]);
-	}
 	if (strstr(make_mode, "ignore-cmd"))
 	    metaIgnoreCMDs = TRUE;
-	/* for backwards compatability */
-	Var_Set(".MAKE.META_CREATED", "${.MAKE.META.CREATED}", VAR_GLOBAL, 0);
-	Var_Set(".MAKE.META_FILES", "${.MAKE.META.FILES}", VAR_GLOBAL, 0);
+	if (useFilemon)
+	    get_mode_bf(filemonMissing, "missing-filemon=");
+	get_mode_bf(metaCurdirOk, "curdirok=");
+	get_mode_bf(metaMissing, "missing-meta=");
+	get_mode_bf(metaSilent, "silent=");
     }
     if (metaVerbose && !Var_Exists(MAKE_META_PREFIX, VAR_GLOBAL)) {
 	/*
@@ -917,6 +924,8 @@ meta_oodate(GNode *gn, Boolean oodate)
     char fname1[MAXPATHLEN];
     char fname2[MAXPATHLEN];
     char fname3[MAXPATHLEN];
+    const char *dname;
+    const char *tname;
     char *p;
     char *cp;
     char *link_src;
@@ -926,10 +935,23 @@ meta_oodate(GNode *gn, Boolean oodate)
     FILE *fp;
     Boolean needOODATE = FALSE;
     Lst missingFiles;
-    
+    char *pa[4];			/* >= possible uses */
+    int i;
+    int have_filemon = FALSE;
+
     if (oodate)
 	return oodate;		/* we're done */
 
+    i = 0;
+
+    dname = Var_Value(".OBJDIR", gn, &pa[i++]);
+    tname = Var_Value(TARGET, gn, &pa[i++]);
+
+    /* if this succeeds fname3 is realpath of dname */
+    if (!meta_needed(gn, dname, tname, fname3, FALSE))
+	goto oodate_out;
+    dname = fname3;
+
     missingFiles = Lst_Init(FALSE);
 
     /*
@@ -940,7 +962,7 @@ meta_oodate(GNode *gn, Boolean oodate)
      */
     Make_DoAllVar(gn);
 
-    meta_name(gn, fname, sizeof(fname), NULL, NULL);
+    meta_name(gn, fname, sizeof(fname), dname, tname, dname);
 
 #ifdef DEBUG_META_MODE
     if (DEBUG(META))
@@ -953,7 +975,6 @@ meta_oodate(GNode *gn, Boolean oodate)
 	int lineno = 0;
 	int lastpid = 0;
 	int pid;
-	int f = 0;
 	int x;
 	LstNode ln;
 	struct stat fs;
@@ -992,13 +1013,13 @@ meta_oodate(GNode *gn, Boolean oodate)
 	    link_src = NULL;
 	    move_target = NULL;
 	    /* Find the start of the build monitor section. */
-	    if (!f) {
+	    if (!have_filemon) {
 		if (strncmp(buf, "-- filemon", 10) == 0) {
-		    f = 1;
+		    have_filemon = TRUE;
 		    continue;
 		}
 		if (strncmp(buf, "# buildmon", 10) == 0) {
-		    f = 1;
+		    have_filemon = TRUE;
 		    continue;
 		}
 	    }		    
@@ -1010,7 +1031,7 @@ meta_oodate(GNode *gn, Boolean oodate)
 		fprintf(debug_file, "%s: %d: %s\n", fname, lineno, buf);
 #endif
 	    strsep(&p, " ");
-	    if (f) {
+	    if (have_filemon) {
 		/*
 		 * We are in the 'filemon' output section.
 		 * Each record from filemon follows the general form:
@@ -1431,13 +1452,19 @@ meta_oodate(GNode *gn, Boolean oodate)
 	    oodate = TRUE;
 	}
     } else {
-	if ((gn->type & OP_META)) {
+	if (writeMeta && metaMissing) {
 	    if (DEBUG(META))
 		fprintf(debug_file, "%s: required but missing\n", fname);
 	    oodate = TRUE;
 	}
     }
 
+    if (!oodate && !have_filemon && filemonMissing) {
+	if (DEBUG(META))
+	    fprintf(debug_file, "%s: missing filemon data\n", fname);
+	oodate = TRUE;
+    }
+
     Lst_Destroy(missingFiles, (FreeProc *)free);
 
     if (oodate && needOODATE) {
@@ -1450,6 +1477,11 @@ meta_oodate(GNode *gn, Boolean oodate)
 	Var_Set(OODATE, Var_Value(ALLSRC, gn, &cp), gn, 0);
 	free(cp);
     }
+
+ oodate_out:
+    for (i--; i >= 0; i--) {
+	free(pa[i]);
+    }
     return oodate;
 }
 

Reply via email to