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