summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--usr.bin/make/globals.h1
-rw-r--r--usr.bin/make/job.c49
-rw-r--r--usr.bin/make/job.h2
-rw-r--r--usr.bin/make/main.c202
-rw-r--r--usr.bin/make/make.145
-rw-r--r--usr.bin/make/make.h1
-rw-r--r--usr.bin/make/parse.c6
7 files changed, 279 insertions, 27 deletions
diff --git a/usr.bin/make/globals.h b/usr.bin/make/globals.h
index 4982a9f..465c4f3 100644
--- a/usr.bin/make/globals.h
+++ b/usr.bin/make/globals.h
@@ -77,6 +77,7 @@ extern Boolean beSilent; /* True if should print no commands */
extern Boolean beVerbose; /* True if should print extra cruft */
extern Boolean noExecute; /* True if should execute nothing */
extern Boolean allPrecious; /* True if every target is precious */
+extern Boolean is_posix; /* .POSIX target seen */
/* True if should continue on unaffected portions of the graph
* when have an error in one portion */
diff --git a/usr.bin/make/job.c b/usr.bin/make/job.c
index 7bb31cd..6136c6f 100644
--- a/usr.bin/make/job.c
+++ b/usr.bin/make/job.c
@@ -3070,7 +3070,7 @@ Compat_RunCommand(char *cmd, GNode *gn)
/*-
*-----------------------------------------------------------------------
- * CompatMake --
+ * Compat_Make --
* Make a target, given the parent, to abort if necessary.
*
* Side Effects:
@@ -3078,8 +3078,8 @@ Compat_RunCommand(char *cmd, GNode *gn)
*
*-----------------------------------------------------------------------
*/
-static int
-CompatMake(GNode *gn, GNode *pgn)
+int
+Compat_Make(GNode *gn, GNode *pgn)
{
LstNode *ln;
@@ -3099,7 +3099,7 @@ CompatMake(GNode *gn, GNode *pgn)
gn->made = BEINGMADE;
Suff_FindDeps(gn);
LST_FOREACH(ln, &gn->children)
- CompatMake(Lst_Datum(ln), gn);
+ Compat_Make(Lst_Datum(ln), gn);
if (!gn->make) {
gn->made = ABORTED;
pgn->make = FALSE;
@@ -3289,6 +3289,27 @@ CompatMake(GNode *gn, GNode *pgn)
}
/*-
+ * Install signal handlers for Compat_Run
+ */
+void
+Compat_InstallSignalHandlers(void)
+{
+
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
+ signal(SIGINT, CompatCatchSig);
+ }
+ if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
+ signal(SIGTERM, CompatCatchSig);
+ }
+ if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
+ signal(SIGHUP, CompatCatchSig);
+ }
+ if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) {
+ signal(SIGQUIT, CompatCatchSig);
+ }
+}
+
+/*-
*-----------------------------------------------------------------------
* Compat_Run --
* Start making again, given a list of target nodes.
@@ -3308,19 +3329,7 @@ Compat_Run(Lst *targs)
int error_cnt; /* Number of targets not remade due to errors */
LstNode *ln;
- if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
- signal(SIGINT, CompatCatchSig);
- }
- if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
- signal(SIGTERM, CompatCatchSig);
- }
- if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
- signal(SIGHUP, CompatCatchSig);
- }
- if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) {
- signal(SIGQUIT, CompatCatchSig);
- }
-
+ Compat_InstallSignalHandlers();
ENDNode = Targ_FindNode(".END", TARG_CREATE);
/*
* If the user has defined a .BEGIN target, execute the commands
@@ -3341,8 +3350,8 @@ Compat_Run(Lst *targs)
}
/*
- * For each entry in the list of targets to create, call CompatMake on
- * it to create the thing. CompatMake will leave the 'made' field of gn
+ * For each entry in the list of targets to create, call Compat_Make on
+ * it to create the thing. Compat_Make will leave the 'made' field of gn
* in one of several states:
* UPTODATE gn was already up-to-date
* MADE gn was recreated successfully
@@ -3353,7 +3362,7 @@ Compat_Run(Lst *targs)
error_cnt = 0;
while (!Lst_IsEmpty(targs)) {
gn = Lst_DeQueue(targs);
- CompatMake(gn, gn);
+ Compat_Make(gn, gn);
if (gn->made == UPTODATE) {
printf("`%s' is up to date.\n", gn->name);
diff --git a/usr.bin/make/job.h b/usr.bin/make/job.h
index 1ef4b66..a4c6620 100644
--- a/usr.bin/make/job.h
+++ b/usr.bin/make/job.h
@@ -72,6 +72,8 @@ void Proc_Init(void);
struct Buffer *Cmd_Exec(const char *, const char **);
+int Compat_Make(struct GNode *gn, struct GNode *pgn);
+void Compat_InstallSignalHandlers(void);
void Compat_Run(struct Lst *);
#endif /* job_h_4678dfd1 */
diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c
index 1c8acdc..8eceedf 100644
--- a/usr.bin/make/main.c
+++ b/usr.bin/make/main.c
@@ -80,6 +80,7 @@ __FBSDID("$FreeBSD$");
#include "config.h"
#include "dir.h"
#include "globals.h"
+#include "GNode.h"
#include "job.h"
#include "make.h"
#include "parse.h"
@@ -100,6 +101,9 @@ extern char **environ; /* XXX what header declares this variable? */
/* ordered list of makefiles to read */
static Lst makefiles = Lst_Initializer(makefiles);
+/* ordered list of source makefiles */
+static Lst source_makefiles = Lst_Initializer(source_makefiles);
+
/* list of variables to print */
static Lst variables = Lst_Initializer(variables);
@@ -108,6 +112,8 @@ static Boolean noBuiltins; /* -r flag */
static Boolean forceJobs; /* -j argument given */
static char *curdir; /* startup directory */
static char *objdir; /* where we chdir'ed to */
+static char **save_argv; /* saved argv */
+static char *save_makeflags;/* saved MAKEFLAGS */
/* (-E) vars to override from env */
Lst envFirstVars = Lst_Initializer(envFirstVars);
@@ -116,6 +122,7 @@ Lst envFirstVars = Lst_Initializer(envFirstVars);
Lst create = Lst_Initializer(create);
Boolean allPrecious; /* .PRECIOUS given on line by itself */
+Boolean is_posix; /* .POSIX target seen */
Boolean beSilent; /* -s flag */
Boolean beVerbose; /* -v flag */
Boolean compatMake; /* -B argument */
@@ -316,6 +323,31 @@ found:
}
/**
+ * Open and parse the given makefile.
+ * If open is successful add it to the list of makefiles.
+ *
+ * Results:
+ * TRUE if ok. FALSE if couldn't open file.
+ */
+static Boolean
+TryReadMakefile(const char p[])
+{
+ char *data;
+ LstNode *last = Lst_Last(&source_makefiles);
+
+ if (!ReadMakefile(p))
+ return (FALSE);
+
+ data = estrdup(p);
+ if (last == NULL) {
+ LstNode *first = Lst_First(&source_makefiles);
+ Lst_Insert(&source_makefiles, first, data);
+ } else
+ Lst_Append(&source_makefiles, last, estrdup(p));
+ return (TRUE);
+}
+
+/**
* MainParseArgs
* Parse a given argument vector. Called from main() and from
* Main_ParseArgLine() when the .MAKEFLAGS target is used.
@@ -502,7 +534,7 @@ rearg:
if (Main_ParseWarn(optarg, 1) != -1)
MFLAGS_append("-x", optarg);
break;
-
+
default:
case '?':
usage();
@@ -523,10 +555,12 @@ rearg:
for (; *argv != NULL; ++argv, --argc) {
if (Parse_IsVar(*argv)) {
char *ptr = MAKEFLAGS_quote(*argv);
+ char *v = estrdup(*argv);
Var_Append(".MAKEFLAGS", ptr, VAR_GLOBAL);
- Parse_DoVar(*argv, VAR_CMD);
+ Parse_DoVar(v, VAR_CMD);
free(ptr);
+ free(v);
} else if ((*argv)[0] == '-') {
if ((*argv)[1] == '\0') {
@@ -640,6 +674,149 @@ check_make_level(void)
}
/**
+ * Main_AddSourceMakefile
+ * Add a file to the list of source makefiles
+ */
+void
+Main_AddSourceMakefile(const char *name)
+{
+
+ Lst_AtEnd(&source_makefiles, estrdup(name));
+}
+
+/**
+ * Remake_Makefiles
+ * Remake all the makefiles
+ */
+static void
+Remake_Makefiles(void)
+{
+ LstNode *ln;
+ int error_cnt = 0;
+ int remade_cnt = 0;
+
+ Compat_InstallSignalHandlers();
+
+ LST_FOREACH(ln, &source_makefiles) {
+ LstNode *ln2;
+ struct GNode *gn;
+ const char *name = Lst_Datum(ln);
+ Boolean saveTouchFlag = touchFlag;
+ Boolean saveQueryFlag = queryFlag;
+ Boolean saveNoExecute = noExecute;
+
+ /*
+ * Create node
+ */
+ gn = Targ_FindNode(name, TARG_CREATE);
+ DEBUGF(MAKE, ("Checking %s...", gn->name));
+ Suff_FindDeps(gn);
+
+ /*
+ * ! dependencies as well as
+ * dependencies with .FORCE, .EXEC and .PHONY attributes
+ * are skipped to prevent infinite loops
+ */
+ if (gn->type & (OP_FORCE | OP_EXEC | OP_PHONY)) {
+ DEBUGF(MAKE, ("skipping (force, exec or phony).\n",
+ gn->name));
+ continue;
+ }
+
+ /*
+ * Skip :: targets that have commands and no children
+ * because such targets are always out-of-date
+ */
+ if ((gn->type & OP_DOUBLEDEP) &&
+ !Lst_IsEmpty(&gn->commands) &&
+ Lst_IsEmpty(&gn->children)) {
+ DEBUGF(MAKE, ("skipping (doubledep, no sources "
+ "and has commands).\n"));
+ continue;
+ }
+
+ /*
+ * Skip targets without sources and without commands
+ */
+ if (Lst_IsEmpty(&gn->commands) &&
+ Lst_IsEmpty(&gn->children)) {
+ DEBUGF(MAKE,
+ ("skipping (no sources and no commands).\n"));
+ continue;
+ }
+
+ DEBUGF(MAKE, ("\n"));
+
+ /*
+ * -t, -q and -n has no effect unless the makefile is
+ * specified as one of the targets explicitly in the
+ * command line
+ */
+ LST_FOREACH(ln2, &create) {
+ if (!strcmp(gn->name, Lst_Datum(ln2))) {
+ /* found as a target */
+ break;
+ }
+ }
+ if (ln2 == NULL) {
+ touchFlag = FALSE;
+ queryFlag = FALSE;
+ noExecute = FALSE;
+ }
+
+ /*
+ * Check and remake the makefile
+ */
+ Compat_Make(gn, gn);
+
+ /*
+ * Restore -t, -q and -n behaviour
+ */
+ touchFlag = saveTouchFlag;
+ queryFlag = saveQueryFlag;
+ noExecute = saveNoExecute;
+
+ /*
+ * Compat_Make will leave the 'made' field of gn
+ * in one of the following states:
+ * UPTODATE gn was already up-to-date
+ * MADE gn was recreated successfully
+ * ERROR An error occurred while gn was being created
+ * ABORTED gn was not remade because one of its inferiors
+ * could not be made due to errors.
+ */
+ if (gn->made == MADE)
+ remade_cnt++;
+ else if (gn->made == ERROR)
+ error_cnt++;
+ else if (gn->made == ABORTED) {
+ printf("`%s' not remade because of errors.\n",
+ gn->name);
+ error_cnt++;
+ }
+ }
+
+ if (error_cnt > 0)
+ Fatal("Failed to remake Makefiles.");
+ if (remade_cnt > 0) {
+ DEBUGF(MAKE, ("Restarting `%s'.\n", save_argv[0]));
+
+ /*
+ * Some of makefiles were remade -- restart from clean state
+ */
+ if (save_makeflags != NULL)
+ setenv("MAKEFLAGS", save_makeflags, 1);
+ else
+ unsetenv("MAKEFLAGS");
+ chdir(curdir);
+ if (execvp(save_argv[0], save_argv) < 0) {
+ Fatal("Can't restart `%s': %s.",
+ save_argv[0], strerror(errno));
+ }
+ }
+}
+
+/**
* main
* The main function, for obvious reasons. Initializes variables
* and a few modules, then parses the arguments give it in the
@@ -671,6 +848,11 @@ main(int argc, char **argv)
char cdpath[MAXPATHLEN];
char *cp = NULL, *start;
+ save_argv = argv;
+ save_makeflags = getenv("MAKEFLAGS");
+ if (save_makeflags != NULL)
+ save_makeflags = estrdup(save_makeflags);
+
/*
* Initialize file global variables.
*/
@@ -958,14 +1140,14 @@ main(int argc, char **argv)
LstNode *ln;
LST_FOREACH(ln, &makefiles) {
- if (!ReadMakefile(Lst_Datum(ln)))
+ if (!TryReadMakefile(Lst_Datum(ln)))
break;
}
if (ln != NULL)
Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
- } else if (!ReadMakefile("BSDmakefile"))
- if (!ReadMakefile("makefile"))
- ReadMakefile("Makefile");
+ } else if (!TryReadMakefile("BSDmakefile"))
+ if (!TryReadMakefile("makefile"))
+ TryReadMakefile("Makefile");
ReadMakefile(".depend");
@@ -1034,6 +1216,13 @@ main(int argc, char **argv)
*/
Lst targs = Lst_Initializer(targs);
+ if (!is_posix) {
+ /*
+ * Check if any of the makefiles are out-of-date.
+ */
+ Remake_Makefiles();
+ }
+
if (Lst_IsEmpty(&create))
Parse_MainName(&targs);
else
@@ -1072,6 +1261,7 @@ main(int argc, char **argv)
Lst_Destroy(&variables, free);
Lst_Destroy(&makefiles, free);
+ Lst_Destroy(&source_makefiles, free);
Lst_Destroy(&create, free);
/* print the graph now it's been processed if the user requested it */
diff --git a/usr.bin/make/make.1 b/usr.bin/make/make.1
index e77ec19..393e4f5 100644
--- a/usr.bin/make/make.1
+++ b/usr.bin/make/make.1
@@ -1465,6 +1465,51 @@ Several flags can be specified on a single
.Ic .WARN
target by seperating them with blanks.
.El
+.Sh REMAKING MAKEFILES
+After reading Makefile and all the files that are included using
+.Ic .include
+or
+.Ic .sinclude
+directives (source Makefiles)
+.Nm
+considers each source Makefile as a target and tries to rebuild it.
+Both explicit and implicit rules are checked and all source Makefiles
+are updated if necessary. If any of the source Makefiles were rebuilt,
+.Nm
+restarts from clean state.
+.Pp
+To prevent infinite loops the following source Makefile targets are ignored:
+.Bl -bullet
+.It
+.Ic ::
+targets that have no prerequisites but have commands
+.It
+.Ic !
+targets
+.It
+targets that have
+.Ic .PHONY
+or
+.Ic .EXEC
+attributes
+.It
+targets without prerequisites and without commands
+.El
+.Pp
+When remaking a source Makefile options
+.Ic -t
+(touch target),
+.Ic -q
+(query mode), and
+.Ic -n
+(no exec) do not take effect, unless source Makefile is specified
+explicitly as a target in
+.Nm
+command line.
+.Pp
+Additionally, system makefiles and
+.Ic .depend
+are not considered as a Makefiles that can be rebuilt.
.Sh ENVIRONMENT
The
.Nm
diff --git a/usr.bin/make/make.h b/usr.bin/make/make.h
index e8d5660..2386cd7 100644
--- a/usr.bin/make/make.h
+++ b/usr.bin/make/make.h
@@ -68,5 +68,6 @@ void Make_DoAllVar(struct GNode *);
Boolean Make_Run(struct Lst *);
void Main_ParseArgLine(char *, int);
int Main_ParseWarn(const char *, int);
+void Main_AddSourceMakefile(const char *);
#endif /* make_h_a91074b9 */
diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c
index c9c1dbf..f125b50 100644
--- a/usr.bin/make/parse.c
+++ b/usr.bin/make/parse.c
@@ -1070,6 +1070,7 @@ ParseDoDependency(char *line)
Path_Clear(Lst_Datum(ln));
break;
case Posix:
+ is_posix = TRUE;
Var_Set("%POSIX", "1003.2", VAR_GLOBAL);
break;
default:
@@ -2059,7 +2060,7 @@ ParseFinishLine(void)
}
/**
- * parse_include
+ * xparse_include
* Parse an .include directive and push the file onto the input stack.
* The input is the line minus the .include. A file spec is a string
* enclosed in <> or "". The former is looked for only in sysIncPath.
@@ -2184,9 +2185,12 @@ xparse_include(char *file, int sinclude)
*cp = endc;
if (!sinclude)
Parse_Error(PARSE_FATAL, "Could not find %s", file);
+ else
+ Main_AddSourceMakefile(file);
free(file);
return;
}
+ Main_AddSourceMakefile(fullname);
free(file);
/*
OpenPOWER on IntegriCloud