tech-toolchain archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

make: enhancements?



The patch below is part of a project we are doing here.
We believe they should be of interest to others as well.


--sjg

Add:

.error "message"
.warning "message"
        based on FreeBSD implementation.

.ERROR: a target to run on error.
        We pass the failing GNode to PrintOnError so it can set
        .ERROR_TARGET.

.MAKE.MAKEFILE_PREFERENCE
        As a means to control make's list of prefered makefile names.
        (Default: "makefile Makefile")

.MAKE.DEPENDFILE
        Names the file to read dependencies from 
        (Default ".depend")

Fix:

compat.c: Error code should not be sent to debug_file.
Make_DoAllVar: use DONE_ALLSRC to avoid processing a node multiple times.
ReadMakefile: we can simply use doing_depend to control setting MAKEFILE.
.NOTPARALLEL:  put make into compat mode, since maxJobs=1 is insufficient
               to fix missing dependencies.

Index: compat.c
===================================================================
RCS file: /cvsroot/src/usr.bin/make/compat.c,v
retrieving revision 1.76
diff -u -p -r1.76 compat.c
--- compat.c    22 Feb 2009 07:33:00 -0000      1.76
+++ compat.c    5 Apr 2010 18:52:37 -0000
@@ -407,7 +407,7 @@ again:
                        }
                        fprintf(debug_file, "\n");
                    }
-                   fprintf(debug_file, "*** Error code %d", status);
+                   printf("*** Error code %d", status);
                }
            } else {
                status = WTERMSIG(reason);              /* signaled */
@@ -574,7 +574,7 @@ Compat_Make(void *gnp, void *pgnp)
        } else if (keepgoing) {
            pgn->flags &= ~REMAKE;
        } else {
-           PrintOnError("\n\nStop.");
+           PrintOnError(gn, "\n\nStop.");
            exit(1);
        }
     } else if (gn->made == ERROR) {
@@ -665,7 +665,7 @@ Compat_Run(Lst targs)
        if (gn != NULL) {
            Compat_Make(gn, gn);
             if (gn->made == ERROR) {
-                PrintOnError("\n\nStop.");
+                PrintOnError(gn, "\n\nStop.");
                 exit(1);
             }
        }
@@ -706,7 +706,7 @@ Compat_Run(Lst targs)
     if (errors == 0) {
        Compat_Make(ENDNode, ENDNode);
        if (gn->made == ERROR) {
-           PrintOnError("\n\nStop.");
+           PrintOnError(gn, "\n\nStop.");
            exit(1);
        }
     }
Index: job.c
===================================================================
RCS file: /cvsroot/src/usr.bin/make/job.c,v
retrieving revision 1.146
diff -u -p -r1.146 job.c
--- job.c       26 Jun 2009 01:26:32 -0000      1.146
+++ job.c       5 Apr 2010 18:52:38 -0000
@@ -1225,8 +1225,8 @@ Job_CheckCommands(GNode *gn, void (*abor
            static const char msg[] = ": don't know how to make";
 
            if (gn->flags & FROM_DEPEND) {
-               fprintf(stdout, "%s: ignoring stale .depend for %s\n",
-                       progname, gn->name);
+               fprintf(stdout, "%s: ignoring stale %s for %s\n",
+                       progname, makeDependfile, gn->name);
                return TRUE;
            }
 
@@ -1897,7 +1897,7 @@ JobRun(GNode *targ)
 #else
     Compat_Make(targ, targ);
     if (targ->made == ERROR) {
-       PrintOnError("\n\nStop.");
+       PrintOnError(targ, "\n\nStop.");
        exit(1);
     }
 #endif
@@ -2227,7 +2227,7 @@ Job_Init(void)
     if (begin != NULL) {
        JobRun(begin);
        if (begin->made == ERROR) {
-           PrintOnError("\n\nStop.");
+           PrintOnError(begin, "\n\nStop.");
            exit(1);
        }
     }
Index: main.c
===================================================================
RCS file: /cvsroot/src/usr.bin/make/main.c,v
retrieving revision 1.175
diff -u -p -r1.175 main.c
--- main.c      4 Jan 2010 17:05:25 -0000       1.175
+++ main.c      5 Apr 2010 18:52:38 -0000
@@ -184,6 +184,7 @@ static Boolean              ignorePWD;      /* if we use 
 static char curdir[MAXPATHLEN + 1];    /* startup directory */
 static char objdir[MAXPATHLEN + 1];    /* where we chdir'ed to */
 char *progname;                                /* the program name */
+char *makeDependfile;
 
 Boolean forceJobs = FALSE;
 
@@ -680,6 +681,22 @@ ReadAllMakefiles(const void *p, const vo
        return (ReadMakefile(p, q) == 0);
 }
 
+static int
+str2Lst_Append (Lst lp, char *str, const char *sep)
+{
+    char *cp;
+    int n;
+
+    if (!sep)
+       sep = " \t";
+
+    for (n = 0, cp = strtok(str, sep); cp; cp = strtok(NULL, sep)) {
+       (void)Lst_AtEnd(lp, cp);
+       n++;
+    }
+    return (n);
+}
+
 #ifdef SIGINFO
 /*ARGSUSED*/
 static void
@@ -696,6 +713,24 @@ siginfo(int signo)
 }
 #endif
 
+void
+MakeMode (const char *mode)
+{
+    char *mp = NULL;
+
+    if (!mode)
+       mode = mp = Var_Subst(NULL, "${" MAKE_MODE ":tl}", VAR_GLOBAL, 0);
+
+    if (mode && *mode) {
+       if (strstr(mode, "compat")) {
+           compatMake = TRUE;
+           forceJobs = FALSE;
+       }
+    }
+    if (mp)
+       free(mp);
+}
+
 /*-
  * main --
  *     The main function, for obvious reasons. Initializes variables
@@ -813,6 +848,15 @@ main(int argc, char **argv)
        Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL, 0);
 #endif
        Var_Set(".newline", "\n", VAR_GLOBAL, 0); /* handy for :@ loops */
+       /*
+        * This is the traditional preference for makefiles.
+        */
+#ifndef MAKEFILE_PREFERENCE_LIST
+# define MAKEFILE_PREFERENCE_LIST "makefile Makefile"
+#endif
+       Var_Set(MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST,
+               VAR_GLOBAL, 0);
+       Var_Set(MAKE_DEPENDFILE, ".depend", VAR_GLOBAL, 0);
 
        create = Lst_Init(FALSE);
        makefiles = Lst_Init(FALSE);
@@ -1051,16 +1095,27 @@ main(int argc, char **argv)
                if (ln != NULL)
                        Fatal("%s: cannot open %s.", progname, 
                            (char *)Lst_Datum(ln));
-       } else if (ReadMakefile("makefile", NULL) != 0)
-               (void)ReadMakefile("Makefile", NULL);
+       } else {
+           p1 = Var_Subst(NULL, "${" MAKEFILE_PREFERENCE "}",
+                          VAR_CMD, 0);
+           if (p1) {
+               (void)str2Lst_Append(makefiles, p1, NULL);
+               (void)Lst_Find(makefiles, NULL, ReadMakefile);
+               free(p1);
+           }
+       }
 
        /* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
        if (!noBuiltins || !printVars) {
-               doing_depend = TRUE;
-               (void)ReadMakefile(".depend", NULL);
-               doing_depend = FALSE;
+           makeDependfile = Var_Subst(NULL, "${.MAKE.DEPENDFILE:T}",
+                                      VAR_CMD, 0);
+           doing_depend = TRUE;
+           (void)ReadMakefile(makeDependfile, NULL);
+           doing_depend = FALSE;
        }
 
+       MakeMode(NULL);
+
        Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
        if (p1)
            free(p1);
@@ -1219,14 +1274,11 @@ ReadMakefile(const void *p, const void *
        int fd;
        size_t len = MAXPATHLEN;
        char *name, *path = bmake_malloc(len);
-       int setMAKEFILE;
 
        if (!strcmp(fname, "-")) {
                Parse_File("(stdin)", dup(fileno(stdin)));
                Var_Set("MAKEFILE", "", VAR_GLOBAL, 0);
        } else {
-               setMAKEFILE = strcmp(fname, ".depend");
-
                /* if we've chdir'd, rebuild the path name */
                if (strcmp(curdir, objdir) && *fname != '/') {
                        size_t plen = strlen(curdir) + strlen(fname) + 2;
@@ -1273,7 +1325,7 @@ ReadMakefile(const void *p, const void *
                 * makefile specified, as it is set by SysV make.
                 */
 found:
-               if (setMAKEFILE)
+               if (!doing_depend)
                        Var_Set("MAKEFILE", fname, VAR_GLOBAL, 0);
                Parse_File(fname, fd);
        }
@@ -1666,7 +1718,7 @@ Fatal(const char *fmt, ...)
        (void)fprintf(stderr, "\n");
        (void)fflush(stderr);
 
-       PrintOnError(NULL);
+       PrintOnError(NULL, NULL);
 
        if (DEBUG(GRAPH2) || DEBUG(GRAPH3))
                Targ_PrintGraph(2);
@@ -1698,7 +1750,7 @@ Punt(const char *fmt, ...)
        (void)fprintf(stderr, "\n");
        (void)fflush(stderr);
 
-       PrintOnError(NULL);
+       PrintOnError(NULL, NULL);
 
        DieHorribly();
 }
@@ -1819,15 +1871,29 @@ PrintAddr(void *a, void *b)
 
 
 void
-PrintOnError(const char *s)
+PrintOnError(GNode *gn, const char *s)
 {
+    GNode *en;
     char tmp[64];
     char *cp;
 
     if (s)
-           printf("%s", s);
+       printf("%s", s);
        
     printf("\n%s: stopped in %s\n", progname, curdir);
+
+    if (gn) {
+       /*
+        * We can print this even if there is no .ERROR target.
+        */
+       Var_Set(".ERROR_TARGET", gn->name, VAR_GLOBAL, 0);
+    }
+    en = Targ_FindNode(".ERROR", TARG_NOCREATE);
+    if (en) {
+       en->type |= OP_SPECIAL;
+       Compat_Make(en, en);
+    }
+    
     strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
            sizeof(tmp) - 1);
     cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
Index: make.1
===================================================================
RCS file: /cvsroot/src/usr.bin/make/make.1,v
retrieving revision 1.167
diff -u -p -r1.167 make.1
--- make.1      22 Feb 2010 19:20:33 -0000      1.167
+++ make.1      5 Apr 2010 18:52:38 -0000
@@ -29,7 +29,7 @@
 .\"
 .\"    from: @(#)make.1        8.4 (Berkeley) 3/19/94
 .\"
-.Dd November 15, 2009
+.Dd April 1, 2010
 .Dt MAKE 1
 .Os
 .Sh NAME
@@ -652,9 +652,21 @@ The preferred variable to use is the env
 because it is more compatible with other versions of
 .Nm
 and cannot be confused with the special target with the same name.
+.It Va .MAKE.DEPENDFILE
+Names the makefile (default 
+.Ql Pa .depend )
+from which generated dependencies are read.
 .It Va .MAKE.EXPORTED
 The list of variables exported by
 .Nm .
+.It Va .MAKE.MAKEFILE_PREFERENCE
+The ordered list of makefile names 
+(default
+.Ql Pa makefile ,
+.Ql Pa Makefile )
+that
+.Nm
+will look for.
 .It Va .MAKE.MAKEFILES
 The list of makefiles read by
 .Nm ,
@@ -1274,6 +1286,11 @@ Conditional expressions are also precede
 character of a line.
 The possible conditionals are as follows:
 .Bl -tag -width Ds
+.It Ic .error Ar message
+The message is printed along with the name of the makefile and line number,
+then
+.Nm
+will exit.
 .It Ic .export Ar variable ...
 Export the specified global variable.
 If no variable list is provided, all globals are exported
@@ -1325,6 +1342,8 @@ will also be pushed into the new environ
 .It Ic .undef Ar variable
 Un-define the specified global variable.
 Only global variables may be un-defined.
+.It Ic .warning Ar message
+The message is printed along with the name of the makefile and line number.
 .It Ic \&.if Oo \&! Oc Ns Ar expression Op Ar operator expression ...
 Test the value of an expression.
 .It Ic .ifdef Oo \&! Oc Ns Ar variable Op Ar operator variable ...
@@ -1627,6 +1646,13 @@ to the target's own name.
 .It Ic .END
 Any command lines attached to this target are executed after everything
 else is done.
+.It Ic .ERROR
+Any command lines attached to this target are executed when another target 
fails.
+The
+.Ic .ERROR_TARGET
+variable is set to the target that failed.
+See also 
+.Ic MAKE_PRINT_VAR_ON_ERROR .
 .It Ic .IGNORE
 Mark each of the sources with the
 .Ic .IGNORE
@@ -1661,6 +1687,9 @@ Apply the
 attribute to any specified sources.
 .It Ic .NOTPARALLEL
 Disable parallel mode.
+Puts
+.Nm
+into compatability mode.
 .It Ic .NO_PARALLEL
 Synonym for
 .Ic .NOTPARALLEL ,
Index: make.c
===================================================================
RCS file: /cvsroot/src/usr.bin/make/make.c,v
retrieving revision 1.78
diff -u -p -r1.78 make.c
--- make.c      23 Jan 2009 21:26:30 -0000      1.78
+++ make.c      5 Apr 2010 18:52:39 -0000
@@ -958,6 +958,9 @@ MakeAddAllSrc(void *cgnp, void *pgnp)
 void
 Make_DoAllVar(GNode *gn)
 {
+    if (gn->flags & DONE_ALLSRC)
+       return;
+    
     Lst_ForEach(gn->children, MakeUnmark, gn);
     Lst_ForEach(gn->children, MakeAddAllSrc, gn);
 
@@ -974,6 +977,7 @@ Make_DoAllVar(GNode *gn)
        if (p1)
            free(p1);
     }
+    gn->flags |= DONE_ALLSRC;
 }
 
 /*-
Index: make.h
===================================================================
RCS file: /cvsroot/src/usr.bin/make/make.h,v
retrieving revision 1.79
diff -u -p -r1.79 make.h
--- make.h      8 Sep 2009 17:29:20 -0000       1.79
+++ make.h      5 Apr 2010 18:52:39 -0000
@@ -164,6 +164,7 @@ typedef struct GNode {
 #define DONE_WAIT      0x8     /* Set by Make_ProcessWait() */
 #define DONE_ORDER     0x10    /* Build requested by .ORDER processing */
 #define FROM_DEPEND    0x20    /* Node created from .depend */
+#define DONE_ALLSRC    0x40    /* We do it once only */
 #define CYCLE          0x1000  /* Used by MakePrintStatus */
 #define DONECYCLE      0x2000  /* Used by MakePrintStatus */
     enum enum_made {
@@ -392,6 +393,7 @@ extern Lst  sysIncPath;     /* The system inc
 extern Lst     defIncPath;     /* The default include path. */
 
 extern char    *progname;      /* The program name */
+extern char    *makeDependfile; /* .depend */
 
 #define        MAKEFLAGS       ".MAKEFLAGS"
 #define        MAKEOVERRIDES   ".MAKEOVERRIDES"
@@ -399,6 +401,9 @@ extern char *progname;      /* The program na
 #define        MAKE_EXPORTED   ".MAKE.EXPORTED"   /* variables we export */
 #define        MAKE_MAKEFILES  ".MAKE.MAKEFILES"  /* all the makefiles we read 
*/
 #define        MAKE_LEVEL      ".MAKE.LEVEL"      /* recursion level */
+#define MAKEFILE_PREFERENCE ".MAKE.MAKEFILE_PREFERENCE"
+#define MAKE_DEPENDFILE        ".MAKE.DEPENDFILE" /* .depend */
+#define MAKE_MODE      ".MAKE.MODE"
 
 /*
  * debug control:
@@ -442,7 +447,7 @@ void Make_DoAllVar(GNode *);
 Boolean Make_Run(Lst);
 char * Check_Cwd_Cmd(const char *);
 void Check_Cwd(const char **);
-void PrintOnError(const char *);
+void PrintOnError(GNode *, const char *);
 void Main_ExportMAKEFLAGS(Boolean);
 Boolean Main_SetObjdir(const char *);
 
Index: nonints.h
===================================================================
RCS file: /cvsroot/src/usr.bin/make/nonints.h,v
retrieving revision 1.57
diff -u -p -r1.57 nonints.h
--- nonints.h   19 Nov 2009 00:30:24 -0000      1.57
+++ nonints.h   5 Apr 2010 18:52:39 -0000
@@ -108,6 +108,7 @@ void For_Run(int);
 
 /* main.c */
 void Main_ParseArgLine(const char *);
+void MakeMode(const char *);
 int main(int, char **);
 char *Cmd_Exec(const char *, const char **);
 void Error(const char *, ...) __attribute__((__format__(__printf__, 1, 2)));
Index: parse.c
===================================================================
RCS file: /cvsroot/src/usr.bin/make/parse.c,v
retrieving revision 1.160
diff -u -p -r1.160 parse.c
--- parse.c     19 Nov 2009 00:30:25 -0000      1.160
+++ parse.c     5 Apr 2010 18:52:39 -0000
@@ -497,6 +497,37 @@ Parse_Error(int type, const char *fmt, .
        }
 }
 
+
+/*
+ * ParseMessage
+ *     Parse a .warning or .error directive
+ *
+ *     The input is the line minus the ".error"/".warning".  We substitute
+ *     variables, print the message and exit(1) (for .error) or just print
+ *     a warning if the directive is malformed.
+ */
+static void
+ParseMessage(char *line, int iserror)
+{
+    if (!isspace((u_char)*line)) {
+       Parse_Error(PARSE_WARNING, "invalid syntax: \".%s%s\"",
+                   iserror ? "error" : "warning", line);
+       return;
+    }
+
+    while (isspace((u_char)*line))
+       line++;
+
+    line = Var_Subst(NULL, line, VAR_CMD, 0);
+    Parse_Error(iserror ? PARSE_FATAL : PARSE_WARNING, "%s", line);
+    free(line);
+
+    if (iserror) {
+       /* Terminate immediately. */
+       exit(1);
+    }
+}
+
 /*-
  *---------------------------------------------------------------------
  * ParseLinkSrc  --
@@ -1005,6 +1036,7 @@ ParseDoDependency(char *line)
                        DEFAULT = gn;
                        break;
                    case NotParallel:
+                       MakeMode("compat");
                        maxJobs = 1;
                        break;
                    case SingleShell:
@@ -2513,7 +2545,13 @@ Parse_File(const char *name, int fd)
                } else if (strncmp(cp, "unexport", 8) == 0) {
                    Var_UnExport(cp);
                    continue;
-               }
+               } else if (strncmp(cp, "error", 5) == 0) {
+                   ParseMessage(line + 6, 1);
+                   continue;
+               } else if (strncmp(cp, "warning", 7) == 0) {
+                   ParseMessage(line + 8, 0);
+                   continue;
+               }                   
            }
 
            if (*line == '\t') {
@@ -2661,7 +2699,7 @@ Parse_File(const char *name, int fd)
        (void)fprintf(stderr,
            "%s: Fatal errors encountered -- cannot continue\n",
            progname);
-       PrintOnError(NULL);
+       PrintOnError(NULL, NULL);
        exit(1);
     }
 }


Home | Main Index | Thread Index | Old Index