summaryrefslogtreecommitdiffstats
path: root/contrib/bmake/meta.c
diff options
context:
space:
mode:
authorsjg <sjg@FreeBSD.org>2016-06-05 20:26:16 +0000
committersjg <sjg@FreeBSD.org>2016-06-05 20:26:16 +0000
commitb63d9399ea84c3d83a9ec4d646972ec9ecbbcbdd (patch)
tree5ed115fe90cf50ecbfbb79acaacf35e328d96103 /contrib/bmake/meta.c
parent0366f1b52787fc04c4e16927e2a5d2d9b9920673 (diff)
downloadFreeBSD-src-b63d9399ea84c3d83a9ec4d646972ec9ecbbcbdd.zip
FreeBSD-src-b63d9399ea84c3d83a9ec4d646972ec9ecbbcbdd.tar.gz
Import bmake-20160604
Performace improvements for meta mode.
Diffstat (limited to 'contrib/bmake/meta.c')
-rw-r--r--contrib/bmake/meta.c205
1 files changed, 123 insertions, 82 deletions
diff --git a/contrib/bmake/meta.c b/contrib/bmake/meta.c
index 3167807..4f54a00 100644
--- a/contrib/bmake/meta.c
+++ b/contrib/bmake/meta.c
@@ -1,4 +1,4 @@
-/* $NetBSD: meta.c,v 1.57 2016/05/12 20:28:34 sjg Exp $ */
+/* $NetBSD: meta.c,v 1.60 2016/06/04 22:17:14 sjg Exp $ */
/*
* Implement 'meta' mode.
@@ -73,6 +73,8 @@ static char *metaIgnorePathsStr; /* string storage for the list */
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 */
@@ -237,24 +239,13 @@ eat_dots(char *buf, size_t bufsz, int dots)
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.
@@ -264,7 +255,7 @@ meta_name(struct GNode *gn, char *mname, size_t mnamelen,
* basename as given to us.
*/
if ((cp = strrchr(tname, '/'))) {
- if (realpath(tname, buf)) {
+ if (cached_realpath(tname, buf)) {
if ((rp = strrchr(buf, '/'))) {
rp++;
cp++;
@@ -309,9 +300,6 @@ meta_name(struct GNode *gn, char *mname, size_t mnamelen,
}
}
free(tp);
- for (i--; i >= 0; i--) {
- free(p[i]);
- }
return (mname);
}
@@ -391,29 +379,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. */
@@ -426,48 +411,70 @@ 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 */
- if (realpath(dname, objdir))
+ if (cached_realpath(dname, objdir))
dname = objdir;
/* 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;
@@ -492,7 +499,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))
@@ -561,6 +568,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.
*/
@@ -583,17 +594,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)) {
/*
@@ -921,6 +928,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;
@@ -930,10 +939,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);
/*
@@ -944,7 +966,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))
@@ -957,7 +979,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;
@@ -996,13 +1017,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;
}
}
@@ -1014,7 +1035,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:
@@ -1239,7 +1260,7 @@ meta_oodate(GNode *gn, Boolean oodate)
* they are _expected_ to change.
*/
if (*p == '/') {
- realpath(p, fname1); /* clean it up */
+ cached_realpath(p, fname1); /* clean it up */
if (Lst_ForEach(metaIgnorePaths, prefix_match, fname1)) {
#ifdef DEBUG_META_MODE
if (DEBUG(META))
@@ -1324,7 +1345,7 @@ meta_oodate(GNode *gn, Boolean oodate)
oodate = TRUE;
} else if (S_ISDIR(fs.st_mode)) {
/* Update the latest directory. */
- realpath(p, latestdir);
+ cached_realpath(p, latestdir);
}
} else if (errno == ENOENT && *p == '/' &&
strncmp(p, cwd, cwdlen) != 0) {
@@ -1434,12 +1455,27 @@ meta_oodate(GNode *gn, Boolean oodate)
fname, (char *)Lst_Datum(Lst_First(missingFiles)));
oodate = TRUE;
}
- } else {
- if ((gn->type & OP_META)) {
+ if (!oodate && !have_filemon && filemonMissing) {
if (DEBUG(META))
- fprintf(debug_file, "%s: required but missing\n", fname);
+ fprintf(debug_file, "%s: missing filemon data\n", fname);
oodate = TRUE;
}
+ } else {
+ if (writeMeta && metaMissing) {
+ cp = NULL;
+
+ /* if target is in .CURDIR we do not need a meta file */
+ if (gn->path && (cp = strrchr(gn->path, '/')) && cp > gn->path) {
+ if (strncmp(curdir, gn->path, (cp - gn->path)) != 0) {
+ cp = NULL; /* not in .CURDIR */
+ }
+ }
+ if (!cp) {
+ if (DEBUG(META))
+ fprintf(debug_file, "%s: required but missing\n", fname);
+ oodate = TRUE;
+ }
+ }
}
Lst_Destroy(missingFiles, (FreeProc *)free);
@@ -1454,6 +1490,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;
}
OpenPOWER on IntegriCloud