svn commit: r192701 - projects/jbuild/usr.bin/make

John Birrell jb at FreeBSD.org
Sun May 24 22:07:24 UTC 2009


Author: jb
Date: Sun May 24 22:07:23 2009
New Revision: 192701
URL: http://svn.freebsd.org/changeset/base/192701

Log:
  Merge build/jbuild changes from p4

Modified:
  projects/jbuild/usr.bin/make/cond.c
  projects/jbuild/usr.bin/make/dir.c
  projects/jbuild/usr.bin/make/dir.h
  projects/jbuild/usr.bin/make/globals.h
  projects/jbuild/usr.bin/make/job.c
  projects/jbuild/usr.bin/make/job.h
  projects/jbuild/usr.bin/make/main.c
  projects/jbuild/usr.bin/make/make.c
  projects/jbuild/usr.bin/make/parse.c
  projects/jbuild/usr.bin/make/pathnames.h
  projects/jbuild/usr.bin/make/proc.c
  projects/jbuild/usr.bin/make/proc.h
  projects/jbuild/usr.bin/make/util.c
  projects/jbuild/usr.bin/make/var.c

Modified: projects/jbuild/usr.bin/make/cond.c
==============================================================================
--- projects/jbuild/usr.bin/make/cond.c	Sun May 24 22:00:20 2009	(r192700)
+++ projects/jbuild/usr.bin/make/cond.c	Sun May 24 22:07:23 2009	(r192701)
@@ -148,7 +148,7 @@ static CondProc	*condDefProc;	/* default
 static char	*condExpr;	/* The expression to parse */
 static Token	condPushBack = None; /* Single push-back token in parsing */
 
-#define MAXIF	30	/* greatest depth of #if'ing */
+#define MAXIF	1024	/* greatest depth of #if'ing */
 
 static Boolean	condStack[MAXIF];	/* Stack of conditionals's values */
 static int	condLineno[MAXIF];	/* Line numbers of the opening .if */

Modified: projects/jbuild/usr.bin/make/dir.c
==============================================================================
--- projects/jbuild/usr.bin/make/dir.c	Sun May 24 22:00:20 2009	(r192700)
+++ projects/jbuild/usr.bin/make/dir.c	Sun May 24 22:07:23 2009	(r192701)
@@ -1152,3 +1152,15 @@ Path_Print(const struct Path *path)
 	TAILQ_FOREACH(p, path, link)
 		printf("%s ", p->dir->name);
 }
+
+#ifdef MAKE_IS_BUILD
+void
+Path_List(const struct Path *path, path_listcb_t *cbfunc, char *srctop,
+    size_t ssrctop)
+{
+	const struct PathElement *p;
+
+	TAILQ_FOREACH(p, path, link)
+		cbfunc(srctop, ssrctop, p->dir->name);
+}
+#endif

Modified: projects/jbuild/usr.bin/make/dir.h
==============================================================================
--- projects/jbuild/usr.bin/make/dir.h	Sun May 24 22:00:20 2009	(r192700)
+++ projects/jbuild/usr.bin/make/dir.h	Sun May 24 22:07:23 2009	(r192701)
@@ -68,4 +68,9 @@ char *Path_FindFile(char *, struct Path 
 char *Path_MakeFlags(const char *, const struct Path *);
 void Path_Print(const struct Path *);
 
+#ifdef MAKE_IS_BUILD
+typedef void path_listcb_t(char *, size_t, const char *);
+void Path_List(const struct Path *, path_listcb_t *, char *, size_t);
+#endif
+
 #endif /* dir_h_6002e3b8 */

Modified: projects/jbuild/usr.bin/make/globals.h
==============================================================================
--- projects/jbuild/usr.bin/make/globals.h	Sun May 24 22:00:20 2009	(r192700)
+++ projects/jbuild/usr.bin/make/globals.h	Sun May 24 22:07:23 2009	(r192701)
@@ -69,6 +69,9 @@ extern struct Path parseIncPath;
 /* The system include path. */
 extern struct Path sysIncPath;
 
+/* The build include path. */
+extern struct Path bldIncPath;
+
 extern int	jobLimit;	/* -j argument: maximum number of jobs */
 extern int	makeErrors;	/* Number of targets not remade due to errors */
 extern Boolean	jobsRunning;	/* True if jobs are running */
@@ -95,6 +98,9 @@ extern Boolean	touchFlag;
  * when the shell exits */
 extern Boolean	usePipes;
 
+/* Gather meta data. */
+extern Boolean	use_meta;
+
 /* TRUE if we aren't supposed to really make anything, just see if the
  * targets are out-of-date */
 extern Boolean	queryFlag;

Modified: projects/jbuild/usr.bin/make/job.c
==============================================================================
--- projects/jbuild/usr.bin/make/job.c	Sun May 24 22:00:20 2009	(r192700)
+++ projects/jbuild/usr.bin/make/job.c	Sun May 24 22:07:23 2009	(r192701)
@@ -101,8 +101,10 @@ __FBSDID("$FreeBSD$");
  *			    thems as need creatin'
  */
 
+#include <sys/param.h>
 #include <sys/queue.h>
 #include <sys/types.h>
+#include <sys/ioccom.h>
 #include <sys/select.h>
 #include <sys/stat.h>
 #ifdef USE_KQUEUE
@@ -114,6 +116,7 @@ __FBSDID("$FreeBSD$");
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
+#include <libgen.h>
 #include <string.h>
 #include <signal.h>
 #include <stdlib.h>
@@ -136,9 +139,17 @@ __FBSDID("$FreeBSD$");
 #include "targ.h"
 #include "util.h"
 #include "var.h"
+#ifdef MAKE_IS_BUILD
+#include "jdirdep.h"
+#ifndef BUILDMON
+#include "filemon.h"
+#endif
+#endif
 
 #define	TMPPAT	"/tmp/makeXXXXXXXXXX"
 
+extern char **environ;
+
 #ifndef USE_KQUEUE
 /*
  * The SEL_ constants determine the maximum amount of time spent in select
@@ -165,6 +176,16 @@ typedef struct Job {
 	pid_t		pid;	/* The child's process ID */
 
 	struct GNode	*node;	/* The target the child is making */
+	char		cwd[MAXPATHLEN];
+
+#ifdef MAKE_IS_BUILD
+	char		mon_fname[MAXPATHLEN];
+#ifndef BUILDMON
+	int		filemon_fd;
+	int		mon_fd;
+#endif
+	FILE		*mfp;
+#endif
 
 	/*
 	 * A LstNode for the first command to be saved after the job completes.
@@ -264,6 +285,13 @@ TAILQ_HEAD(JobList, Job);
  * error handling variables
  */
 static int	aborting = 0;	/* why is the make aborting? */
+#ifdef MAKE_IS_BUILD
+static char	mon_fname[MAXPATHLEN];
+#ifndef BUILDMON
+static int	filemon_fd = -1;
+static int	mon_fd = -1;
+#endif
+#endif
 #define	ABORT_ERROR	1	/* Because of an error */
 #define	ABORT_INTERRUPT	2	/* Because it was interrupted */
 #define	ABORT_WAIT	3	/* Waiting for jobs to finish */
@@ -379,11 +407,283 @@ static int JobStart(GNode *, int, Job *)
 static void JobDoOutput(Job *, Boolean);
 static void JobInterrupt(int, int);
 static void JobRestartJobs(void);
-static int Compat_RunCommand(char *, struct GNode *);
+static int Compat_RunCommand(char *, struct GNode *, FILE *);
 
 static GNode	    *curTarg = NULL;
 static GNode	    *ENDNode;
 
+#ifdef MAKE_IS_BUILD
+static int n_meta_created = 0; /* Number of meta data files created. */
+
+void
+meta_exit(void)
+{
+	Boolean f = 0;
+	char *result;
+	char sharedobj[MAXPATHLEN];
+	const char *curdir;
+	const char *filedep_name;
+	const char *objdir;
+	const char *objroot;
+	const char *p_incmk;
+	const char *p_machine;
+	const char *p_machine_arch;
+	const char *srcrel;
+	const char *srctop;
+	size_t len = 0;
+
+	/*
+	 * If no meta data files were created, then there can be no change
+	 * to the dependencies.
+	 */
+	if (n_meta_created == 0)
+		return;
+
+	/*
+	 * If there is no include makefile list variable defined, then
+	 * we can't update dependencies.
+	 */
+	if ((p_incmk = Var_Value("INCMK", VAR_GLOBAL)) != NULL) {
+		/* Initialise the include makefile name list. */
+		jdirdep_incmk(Var_Value("INCMK", VAR_GLOBAL));
+
+		p_machine = Var_Value("MACHINE", VAR_GLOBAL);
+		p_machine_arch = Var_Value("MACHINE_ARCH", VAR_GLOBAL);
+
+		if ((result = Var_Parse(p_machine_arch, VAR_GLOBAL, TRUE, &len, &f)) != var_Error)
+			p_machine_arch = result;
+		else
+			p_machine_arch = NULL;
+
+		/*
+		 * Initialise the current machine and architecture.
+		 * Using this method, we only do one machine type at
+		 * a time.
+		 */
+		jdirdep_supmac_add(p_machine, p_machine_arch);
+
+		srctop = Var_Value(".SRCTOP", VAR_GLOBAL);
+		curdir = Var_Value(".CURDIR", VAR_GLOBAL);
+		srcrel = Var_Value(".SRCREL", VAR_GLOBAL);
+		objroot = Var_Value(".OBJROOT", VAR_GLOBAL);
+		objdir = Var_Value(".OBJDIR", VAR_GLOBAL);
+		filedep_name = Var_Value(".FILEDEP_NAME", VAR_GLOBAL);
+
+		snprintf(sharedobj, sizeof(sharedobj), "%s/../shared", objroot);
+
+		/* Add any new directory and/or source dependencies. */
+		jdirdep(srctop, curdir, srcrel, objroot, objdir, sharedobj, filedep_name,
+		    JDIRDEP_OPT_ADD | JDIRDEP_OPT_SOURCE | JDIRDEP_OPT_UPDATE);
+	}
+}
+
+/*
+ * Read the build monitor output file and write records to the target's
+ * metadata file.
+ */
+static void
+buildmon_read(FILE *mfp, const char *fname)
+{
+	FILE *fp;
+	char bufr[1024];
+	int done = 0;
+
+	/* Check if we're not writing to a meta data file.*/
+	if (mfp == NULL) {
+		/*
+		 * Delete the build monitor file since we have no need
+		 * for it.
+		 */
+		unlink(fname);
+		return;
+	}
+
+	if ((fp = fopen(fname, "r")) == NULL)
+		err(1, "Could not read build monitor file '%s'", fname);
+
+	fprintf(mfp, "-- buildmon acquired metadata --\n");
+
+	do {
+		if (fgets(bufr, sizeof(bufr), fp) != NULL) {
+			if (strncmp(bufr, "# Session completed", 19) == 0)
+				done = 1;
+
+			fprintf(mfp, "%s", bufr);
+		} else
+#ifdef BUILDMON
+			usleep(1000);
+#else
+			done = 1;
+#endif
+
+		clearerr(fp);
+	} while (!done);
+
+	fclose(fp);
+
+	/* Delete the build monitor file now we're done with it. */
+	unlink(fname);
+}
+
+#ifndef BUILDMON
+/*
+ * Open the filemon device.
+ */
+static void
+filemon_open(Job *job)
+{
+	int retry = 5;
+
+	strcpy(mon_fname, "filemon.XXXXXX");
+
+	while (retry > 0) {
+		if ((filemon_fd = open("/dev/filemon", O_RDWR)) >= 0)
+			break;
+
+		retry--;
+	}
+
+	if (filemon_fd < 0)
+			err(1, "Could not open filemon device!");
+	if ((mon_fd = mkstemp(mon_fname)) < 0)
+		err(1, "Could not create temporary file!");
+	else if (ioctl(filemon_fd, FILEMON_SET_FD, &mon_fd) < 0)
+		err(1, "Could not set filemon file descriptor!");
+
+	if (job != NULL) {
+		job->filemon_fd = filemon_fd;
+		job->mon_fd = mon_fd;
+		strlcpy(job->mon_fname, mon_fname, sizeof(job->mon_fname));
+	}
+}
+#endif
+
+char *
+meta_name(struct GNode *gn, char *mname, size_t mnamelen)
+{
+	char bufr[PATH_MAX];
+	char *p;
+	const char *dname = Var_Value(".OBJDIR", gn);
+	const char *tname = Var_Value(TARGET, gn);
+
+	/* Weed out relative paths from the target file name. */
+	tname = realpath(tname, bufr);
+
+	if (strcmp(dname, dirname(tname)) == 0)
+		snprintf(mname, mnamelen, "%s.meta", tname);
+	else {
+		snprintf(mname, mnamelen, "%s/%s.meta", dname, tname);
+
+		/*
+		 * Replace path separators in the file name after the
+		 * current object directory path.
+		 */
+		p = mname + strlen(dname) + 1;
+
+		while (*p != '\0') {
+			if (*p == '/')
+				*p = '_';
+			p++;
+		}
+	}
+
+	return (mname);
+}
+
+static FILE *
+meta_create(GNode *gn)
+{
+	FILE *fp;
+	LstNode	*ln;
+	char bufr[PATH_MAX];
+	char fname[MAXPATHLEN];
+	char **ptr;
+	const char *cname = Var_Value(".CURDIR", gn);
+	const char *dname = Var_Value(".OBJDIR", gn);
+	const char *p;
+	const char *tname = Var_Value(TARGET, gn);
+	int f_make = 0;
+	struct stat fs;
+
+	/* This may be a phony node which we don't want meta data for... */
+	if ((gn->type & OP_PHONY) != 0)
+		return (NULL);
+
+	/* The object directory may not exist. Check it.. */
+	if (stat(dname, &fs) != 0)
+		return (NULL);
+
+	/* Check if there are no commands to execute. */
+	if (gn->commands.firstPtr == NULL)
+		return (NULL);
+
+	/* If we aren't in the object directory, don't create a meta file. */
+	if (strcmp(cname, dname) == 0)
+		return (NULL);
+
+	LST_FOREACH(ln, &gn->commands) {
+		char *cp;
+		for (cp = Lst_Datum(ln); !f_make && *cp != '\0'; cp++) {
+			if (*cp == '$') {
+				Boolean f = 0;
+				size_t len = 0;
+				char *result;
+
+				if ((result = Var_Parse(cp, gn, TRUE,
+				    &len, &f)) != var_Error) {
+					if (len == 7 && strncmp(cp, "${MAKE}", 7) == 0)
+						f_make = 1;
+					if (f)
+						free(result);
+					cp += len - 1;
+				}
+			}
+		}
+	}
+
+	/* Check if a recusive 'make' reference was found. */
+	if (f_make)
+		/* Don't create meta data for recursive make commands. */
+		return (NULL);
+
+	/* Check if the target is in the current object directory. */
+	if ((p = strrchr(tname, '/')) == NULL) {
+		p = tname;
+		fprintf(stderr, "Building %s/%s\n", dname, p);
+	} else {
+		p++;
+		fprintf(stderr, "Building %s\n", realpath(tname, bufr));
+	}
+
+	fflush(stdout);
+
+	if (!use_meta)
+		/* Don't create meta data. */
+		return (NULL);
+
+	meta_name(gn, fname, sizeof(fname));
+
+	if ((fp = fopen(fname, "w")) == NULL)
+		err(1, "Could not open meta file '%s'", fname);
+
+	fprintf(fp, "# Meta data file %s\n", fname);
+
+	LST_FOREACH(ln, &gn->commands)
+		fprintf(fp, "CMD %s\n", Buf_Peel(Var_Subst(Lst_Datum(ln), gn, FALSE)));
+
+	fprintf(fp, "CWD %s\n", getcwd(bufr, sizeof(bufr)));
+
+	for (ptr = environ; *ptr != NULL; ptr++)
+		fprintf(fp, "ENV %s\n", *ptr);
+
+	fprintf(fp, "-- command output --\n");
+
+	n_meta_created++;
+
+	return (fp);
+}
+#endif
+
 /**
  * Create a fifo file with a uniq filename, and returns a file
  * descriptor to that fifo.
@@ -713,7 +1013,7 @@ JobPrintCommand(char *cmd, Job *job)
 				 * but this one needs to be - use compat mode
 				 * just for it.
 				 */
-				Compat_RunCommand(cmd, job->node);
+				Compat_RunCommand(cmd, job->node, NULL);
 				return (0);
 			}
 			break;
@@ -959,6 +1259,15 @@ JobFinish(Job *job, int *status)
 					MESSAGE(out, job->node);
 					lastNode = job->node;
 				}
+#ifdef MAKE_IS_BUILD
+				if (job->mfp != NULL)
+					fprintf(job->mfp, "*** Error code %d%s\n",
+						WEXITSTATUS(*status),
+						(job->flags & JOB_IGNERR) ?
+						"(ignored)" : "");
+#endif
+				fprintf(out, "Error building '%s'\nin directory %s\n",
+				    job->node->path, job->cwd);
 				fprintf(out, "*** Error code %d%s\n",
 					WEXITSTATUS(*status),
 					(job->flags & JOB_IGNERR) ?
@@ -1118,6 +1427,23 @@ JobFinish(Job *job, int *status)
 			    Buf_Peel(
 				Var_Subst(Lst_Datum(ln), job->node, FALSE)));
 		}
+#ifdef MAKE_IS_BUILD
+		if (job->mfp != NULL) {
+#ifndef BUILDMON
+			close(job->filemon_fd);
+			close(job->mon_fd);
+#endif
+
+			/* Process the build monitor file. */
+			buildmon_read(job->mfp, job->mon_fname);
+
+			/*
+			 * Close the meta file now that the target has been
+			 * made.
+			 */
+			fclose(job->mfp);
+		}
+#endif
 
 		job->node->made = MADE;
 		Make_Update(job->node);
@@ -1299,6 +1625,11 @@ static void
 JobExec(Job *job, char **argv)
 {
 	ProcStuff	ps;
+#ifdef MAKE_IS_BUILD
+#ifdef BUILDMON
+	ssize_t num;
+#endif
+#endif
 
 	if (DEBUG(JOB)) {
 		int	  i;
@@ -1347,6 +1678,19 @@ JobExec(Job *job, char **argv)
 	ps.argv = argv;
 	ps.argv_free = 0;
 
+#ifdef MAKE_IS_BUILD
+	ps.mfp = job->mfp;
+
+#ifdef BUILDMON
+	if (job->mfp != NULL && pipe(ps.pipe_fds) < 0)
+		errx(1, "Could not create pipe for child/parent comms");
+#else
+	if (job->mfp != NULL)
+		/* Open the filemon device. */
+		filemon_open(job);
+#endif
+#endif
+
 	/*
 	 * Fork.  Warning since we are doing vfork() instead of fork(),
 	 * do not allocate memory in the child process!
@@ -1362,6 +1706,14 @@ JobExec(Job *job, char **argv)
 		if (fifoFd >= 0)
 			close(fifoFd);
 
+#ifdef MAKE_IS_BUILD
+#ifdef BUILDMON
+		if (job->mfp != NULL)
+			/* Close the read end of the pipe. */
+			close(ps.pipe_fds[0]);
+#endif
+#endif
+
 		Proc_Exec(&ps);
 		/* NOTREACHED */
 	}
@@ -1371,6 +1723,29 @@ JobExec(Job *job, char **argv)
 	 */
 	job->pid = ps.child_pid;
 
+#ifdef MAKE_IS_BUILD
+	if (job->mfp != NULL) {
+#ifdef BUILDMON
+		/* Close the write end of the pipe. */
+		close(ps.pipe_fds[1]);
+
+		if ((num = read(ps.pipe_fds[0], job->mon_fname,
+		    sizeof(job->mon_fname))) <= 0)
+			err(1, "Error reading buildmon file name from pipe");
+
+		/* Close the read end of the pipe. */
+		close(ps.pipe_fds[0]);
+#else
+		/*
+		 * Now that the child's pid is known update the filemon to
+		 * monitor just it.
+		 */
+		if (ioctl(job->filemon_fd, FILEMON_SET_PID, &ps.child_pid) < 0)
+			err(1, "Could not set filemon pid!");
+#endif
+	}
+#endif
+
 	if (usePipes && (job->flags & JOB_FIRST)) {
 		/*
 		 * The first time a job is run for a node, we set the
@@ -1593,6 +1968,7 @@ JobStart(GNode *gn, int flags, Job *prev
 
 	job->node = gn;
 	job->tailCmds = NULL;
+	getcwd(job->cwd, sizeof(job->cwd));
 
 	/*
 	 * Set the initial value of the flags for this job based on the global
@@ -1693,6 +2069,9 @@ JobStart(GNode *gn, int flags, Job *prev
 			 * We can do all the commands at once. hooray for sanity
 			 */
 			numCommands = 0;
+#ifdef MAKE_IS_BUILD
+			job->mfp = meta_create(gn);
+#endif
 			LST_FOREACH(ln, &gn->commands) {
 				if (JobPrintCommand(Lst_Datum(ln), job))
 					break;
@@ -2022,6 +2401,12 @@ JobDoOutput(Job *job, Boolean finish)
 						MESSAGE(stdout, job->node);
 						lastNode = job->node;
 					}
+#ifdef MAKE_IS_BUILD
+					if (job->mfp != NULL &&
+					    strncmp(cp, "Building", 8) != 0)
+						fprintf(job->mfp, "%s%s", cp,
+						    gotNL ? "\n" : "");
+#endif
 					fprintf(stdout, "%s%s", cp,
 					    gotNL ? "\n" : "");
 					fflush(stdout);
@@ -2706,6 +3091,10 @@ Cmd_Exec(const char *cmd, const char **e
 	ps.argv[3] = NULL;
 	ps.argv_free = 1;
 
+#ifdef MAKE_IS_BUILD
+	ps.mfp = NULL;
+#endif
+
 	/*
 	 * Fork.  Warning since we are doing vfork() instead of fork(),
 	 * do not allocate memory in the child process!
@@ -2718,6 +3107,16 @@ Cmd_Exec(const char *cmd, const char **e
   		/*
 		 * Child
   		 */
+#ifdef MAKE_IS_BUILD
+#ifdef BUILDMON
+		/* Close the read end of the pipe. */
+		close(ps.pipe_fds[0]);
+#else
+		/* Close the write end of the pipe. */
+		close(ps.pipe_fds[1]);
+#endif
+#endif
+
 		Proc_Exec(&ps);
 		/* NOTREACHED */
 	}
@@ -2813,7 +3212,7 @@ CompatInterrupt(int signo)
 		gn = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);
 		if (gn != NULL) {
 			LST_FOREACH(ln, &gn->commands) {
-				if (Compat_RunCommand(Lst_Datum(ln), gn))
+				if (Compat_RunCommand(Lst_Datum(ln), gn, NULL))
 					break;
 			}
 		}
@@ -2888,7 +3287,7 @@ shellneed(ArgArray *aa, char *cmd)
  *	The node's 'made' field may be set to ERROR.
  */
 static int
-Compat_RunCommand(char *cmd, GNode *gn)
+Compat_RunCommand(char *cmd, GNode *gn, FILE *mfp)
 {
 	ArgArray	aa;
 	char		*cmdStart;	/* Start of expanded command */
@@ -2995,21 +3394,67 @@ Compat_RunCommand(char *cmd, GNode *gn)
 	}
 	ps.errCheck = errCheck;
 
+#ifdef MAKE_IS_BUILD
+	ps.mfp = mfp;
+
+#ifdef BUILDMON
+	if (mfp != NULL && pipe(ps.pipe_fds) < 0)
+		errx(1, "Could not create pipe for child/parent comms");
+#else
+	if (mfp != NULL)
+		/* Open the filemon device. */
+		filemon_open(NULL);
+#endif
+#endif
+
 	/*
 	 * Warning since we are doing vfork() instead of fork(),
 	 * do not allocate memory in the child process!
 	 */
 	if ((ps.child_pid = vfork()) == -1) {
-		Fatal("Could not fork");
+		Fatal("Cannot fork");
 
 	} else if (ps.child_pid == 0) {
 		/*
 		 * Child
 		 */
+#ifdef MAKE_IS_BUILD
+#ifdef BUILDMON
+		/* Close the read end of the pipe. */
+		close(ps.pipe_fds[0]);
+#endif
+#endif
+
 		Proc_Exec(&ps);
-  		/* NOTREACHED */
 
+		_exit(1);
 	} else {
+#ifdef MAKE_IS_BUILD
+#ifdef BUILDMON
+		char bufr[MAXPATHLEN];
+		if (mfp != NULL) {
+			ssize_t num;
+
+			/* Close the write end of the pipe. */
+			close(ps.pipe_fds[1]);
+
+			if ((num = read(ps.pipe_fds[0], bufr, sizeof(bufr))) <= 0)
+				err(1, "Error reading buildmon file name from pipe");
+
+			/* Close the read end of the pipe. */
+			close(ps.pipe_fds[0]);
+		}
+#else
+		if (mfp != NULL)
+			/*
+			 * Now that the child's pid is known update the
+			 * filemon to monitor just it.
+			 */
+			if (ioctl(filemon_fd, FILEMON_SET_PID, &ps.child_pid) < 0)
+				err(1, "Could not set filemon pid!");
+#endif
+#endif
+
 		if (ps.argv_free) {
 			free(ps.argv[2]);
 			free(ps.argv[1]);
@@ -3034,6 +3479,17 @@ Compat_RunCommand(char *cmd, GNode *gn)
 		 */
 		reason = ProcWait(&ps);
 
+#ifdef MAKE_IS_BUILD
+		if (mfp != NULL) {
+#ifndef BUILDMON
+			close(filemon_fd);
+			close(mon_fd);
+#endif
+			/* Process the build monitor file. */
+			buildmon_read(mfp, mon_fname);
+		}
+#endif
+
 		if (interrupted)
 			CompatInterrupt(interrupted);
   
@@ -3047,12 +3503,20 @@ Compat_RunCommand(char *cmd, GNode *gn)
 				return (0);
   			} else {
 				printf("*** Error code %d", status);
+#ifdef MAKE_IS_BUILD
+				if (mfp != NULL)
+					fprintf(mfp, "*** Error code %d", status);
+#endif
   			}
 		} else if (WIFSTOPPED(reason)) {
 			status = WSTOPSIG(reason);
 		} else {
 			status = WTERMSIG(reason);
 			printf("*** Signal %d", status);
+#ifdef MAKE_IS_BUILD
+			if (mfp != NULL)
+				fprintf(mfp, "*** Signal %d", status);
+#endif
   		}
   
 		if (ps.errCheck) {
@@ -3064,6 +3528,10 @@ Compat_RunCommand(char *cmd, GNode *gn)
 				 * others continue.
 				 */
 				printf(" (continuing)\n");
+#ifdef MAKE_IS_BUILD
+				if (mfp != NULL)
+					fprintf(mfp, " (continuing)\n");
+#endif
 			}
 			return (status);
 		} else {
@@ -3074,6 +3542,10 @@ Compat_RunCommand(char *cmd, GNode *gn)
 			 * happen...
 			 */
 			printf(" (ignored)\n");
+#ifdef MAKE_IS_BUILD
+			if (mfp != NULL)
+				fprintf(mfp, " (ignored)\n");
+#endif
 			return (0);
 		}
 	}
@@ -3117,10 +3589,27 @@ Compat_Make(GNode *gn, GNode *pgn)
 			return (0);
 		}
 
+#ifdef MAKE_IS_BUILD
+		if (strcmp(gn->name, ".depend") == 0) {
+			gn->made = UPTODATE;
+			return (0);
+		}
+#endif
+
 		if (Lst_Member(&gn->iParents, pgn) != NULL) {
 			Var_Set(IMPSRC, Var_Value(TARGET, gn), pgn);
 		}
 
+#ifdef MAKE_IS_BUILD
+		/*
+		 * We need to check if the target is out-of-date. This includes
+		 * checking if the expanded command has changed. This in turn
+		 * requires that all variables are set in the same way that they
+		 * would be if the target needs to be re-built.
+		 */
+		Make_DoAllVar(gn);
+#endif
+
 		/*
 		 * All the children were made ok. Now cmtime contains the
 		 * modification time of the newest child, we need to find out
@@ -3144,12 +3633,14 @@ Compat_Make(GNode *gn, GNode *pgn)
 			exit(1);
 		}
 
+#ifndef MAKE_IS_BUILD
 		/*
 		 * We need to be re-made. We also have to make sure we've got
 		 * a $? variable. To be nice, we also define the $> variable
 		 * using Make_DoAllVar().
 		 */
 		Make_DoAllVar(gn);
+#endif
 
 		/*
 		 * Alter our type to tell if errors should be ignored or things
@@ -3171,7 +3662,7 @@ Compat_Make(GNode *gn, GNode *pgn)
 				curTarg = gn;
 				LST_FOREACH(ln, &gn->commands) {
 					if (Compat_RunCommand(Lst_Datum(ln),
-					    gn))
+					    gn, NULL))
 						break;
 				}
 				curTarg = NULL;
@@ -3348,8 +3839,13 @@ Compat_Run(Lst *targs)
 	if (!queryFlag) {
 		gn = Targ_FindNode(".BEGIN", TARG_NOCREATE);
 		if (gn != NULL) {
+#ifdef MAKE_IS_BUILD
+			fprintf(stderr, "Building %s/%s\n", Var_Value(".OBJDIR", gn),
+			    Var_Value(TARGET, gn));
+			fflush(stdout);
+#endif
 			LST_FOREACH(ln, &gn->commands) {
-				if (Compat_RunCommand(Lst_Datum(ln), gn))
+				if (Compat_RunCommand(Lst_Datum(ln), gn, NULL))
 					break;
 			}
 			if (gn->made == ERROR) {
@@ -3387,9 +3883,14 @@ Compat_Run(Lst *targs)
 	 * If the user has defined a .END target, run its commands.
 	 */
 	if (makeErrors == 0) {
+#ifdef MAKE_IS_BUILD
+		fprintf(stderr, "Building %s/%s\n", Var_Value(".OBJDIR", gn),
+		    Var_Value(TARGET, gn));
+#endif
 		LST_FOREACH(ln, &ENDNode->commands) {
-			if (Compat_RunCommand(Lst_Datum(ln), ENDNode))
+			if (Compat_RunCommand(Lst_Datum(ln), ENDNode, NULL))
 				break;
 		}
 	}
 }
+

Modified: projects/jbuild/usr.bin/make/job.h
==============================================================================
--- projects/jbuild/usr.bin/make/job.h	Sun May 24 22:00:20 2009	(r192700)
+++ projects/jbuild/usr.bin/make/job.h	Sun May 24 22:07:23 2009	(r192701)
@@ -77,4 +77,9 @@ int Compat_Make(struct GNode *gn, struct
 void Compat_InstallSignalHandlers(void);
 void Compat_Run(struct Lst *);
 
+#ifdef MAKE_IS_BUILD
+char *meta_name(struct GNode *, char *, size_t);
+void meta_exit(void);
+#endif
+
 #endif /* job_h_4678dfd1 */

Modified: projects/jbuild/usr.bin/make/main.c
==============================================================================
--- projects/jbuild/usr.bin/make/main.c	Sun May 24 22:00:20 2009	(r192700)
+++ projects/jbuild/usr.bin/make/main.c	Sun May 24 22:07:23 2009	(r192701)
@@ -114,6 +114,13 @@ static char	*curdir;	/* startup director
 static char	*objdir;	/* where we chdir'ed to */
 static char	**save_argv;	/* saved argv */
 static char	*save_makeflags;/* saved MAKEFLAGS */
+#ifdef MAKE_IS_BUILD
+static char	*save_mklvl;	/* saved __MKLVL__ */
+static char	*save_path;	/* saved PATH */
+static char	*clean_environ[2];
+static char	*default_machine = NULL;
+#endif
+static struct utsname utsname;
 
 /* (-E) vars to override from env */
 Lst envFirstVars = Lst_Initializer(envFirstVars);
@@ -140,6 +147,9 @@ Boolean		printGraphOnly;	/* -p flag */
 Boolean		queryFlag;	/* -q flag */
 Boolean		touchFlag;	/* -t flag */
 Boolean		usePipes;	/* !-P flag */
+#ifdef MAKE_IS_BUILD
+Boolean		use_meta;	/* !-Q flag */
+#endif
 uint32_t	warn_cmd;	/* command line warning flags */
 uint32_t	warn_flags;	/* actual warning flags */
 uint32_t	warn_nocmd;	/* command line no-warning flags */
@@ -154,7 +164,8 @@ static void
 usage(void)
 {
 	fprintf(stderr,
-	    "usage: make [-BPSXeiknpqrstv] [-C directory] [-D variable]\n"
+	    "usage: make [-BPQSXeiknpqrstv] [-C directory] [-D variable]\n"
+	    "\t[-b directory]\n"
 	    "\t[-d flags] [-E variable] [-f makefile] [-I directory]\n"
 	    "\t[-j max_jobs] [-m directory] [-V variable]\n"
 	    "\t[variable=value] [target ...]\n");
@@ -459,6 +470,10 @@ rearg:
 			Lst_AtEnd(&envFirstVars, estrdup(optarg));
 			MFLAGS_append("-E", optarg);
 			break;
+		case 'b':
+			Path_AddDir(&bldIncPath, optarg);
+			MFLAGS_append("-b", optarg);
+			break;
 		case 'e':
 			checkEnvFirst = TRUE;
 			MFLAGS_append("-e", NULL);
@@ -510,6 +525,9 @@ rearg:
 		case 'Q':
 			beQuiet = TRUE;
 			beVerbose = FALSE;
+#ifdef MAKE_IS_BUILD
+			use_meta = FALSE;
+#endif
 			MFLAGS_append("-Q", NULL);
 			break;
 		case 'q':
@@ -526,7 +544,11 @@ rearg:
 			MFLAGS_append("-S", NULL);
 			break;
 		case 's':
+#ifdef MAKE_IS_BUILD
+			beSilent = FALSE;
+#else
 			beSilent = TRUE;
+#endif
 			MFLAGS_append("-s", NULL);
 			break;
 		case 't':
@@ -572,6 +594,11 @@ rearg:
 			char *ptr = MAKEFLAGS_quote(*argv);
 			char *v = estrdup(*argv);
 
+#ifdef MAKE_IS_BUILD
+			if (strncmp(v, "MACHINE=", 8) == 0)
+				default_machine = utsname.machine;
+#endif
+
 			Var_Append(".MAKEFLAGS", ptr, VAR_GLOBAL);
 			Parse_DoVar(v, VAR_CMD);
 			free(ptr);
@@ -671,7 +698,11 @@ static void
 check_make_level(void)
 {
 #ifdef WANT_ENV_MKLVL
+#ifdef MAKE_IS_BUILD
+	char	*value = save_mklvl;
+#else
 	char	*value = getenv(MKLVL_ENVVAR);
+#endif
 	int	level = (value == NULL) ? 0 : atoi(value);
 
 	if (level < 0) {
@@ -685,6 +716,15 @@ check_make_level(void)
 		sprintf(new_value, "%d", level + 1);
 		setenv(MKLVL_ENVVAR, new_value, 1);
 	}
+
+#ifdef MAKE_IS_BUILD
+	/*
+	 * Register a function to call on exit for child build processes so
+	 * that dependency hooks can be activated.
+	 */
+	if (level > 0)
+		atexit(meta_exit);
+#endif
 #endif /* WANT_ENV_MKLVL */
 }
 
@@ -833,6 +873,57 @@ Remake_Makefiles(void)
 	}
 }
 
+#ifdef MAKE_IS_BUILD
+static void
+make_objdir(char *path)
+{
+	struct stat fs;
+
+	while (stat(path, &fs) != 0) {
+		char bufr[MAXPATHLEN];
+		char *p;
+
+		strcpy(bufr, path);
+
+		if ((p = strrchr(bufr, '/')) == NULL)
+			err(1, "Missing '/' in directory path");
+		else {
+			*p = '\0';
+
+			make_objdir(bufr);
+		}
+
+		if (mkdir(path, 0775) != 0 && errno != EEXIST)
+			err(1, "Could not make directory '%s'", path);
+	}
+}
+
+static void
+mk_path_init(char *srctop, size_t ssrctop, const char *p)
+{
+	char path[MAXPATHLEN];
+	const char *mk_path_rel = "/bld";
+	size_t len;
+	size_t len1 = strlen(mk_path_rel);
+
+	if (*srctop != '\0' || ssrctop == 0)
+		return;
+
+	if (realpath(p, path) == NULL)
+		return;
+
+	if ((len = strlen(path)) < len1)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-projects mailing list