diff --git a/usr.bin/make/compat.c b/usr.bin/make/compat.c index 1abcb844668b..c6ff7118b629 100644 --- a/usr.bin/make/compat.c +++ b/usr.bin/make/compat.c @@ -1,4 +1,4 @@ -/* $NetBSD: compat.c,v 1.76 2009/02/22 07:33:00 dholland Exp $ */ +/* $NetBSD: compat.c,v 1.77 2010/04/07 00:11:27 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -70,14 +70,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: compat.c,v 1.76 2009/02/22 07:33:00 dholland Exp $"; +static char rcsid[] = "$NetBSD: compat.c,v 1.77 2010/04/07 00:11:27 sjg Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)compat.c 8.2 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: compat.c,v 1.76 2009/02/22 07:33:00 dholland Exp $"); +__RCSID("$NetBSD: compat.c,v 1.77 2010/04/07 00:11:27 sjg Exp $"); #endif #endif /* not lint */ #endif @@ -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); } } diff --git a/usr.bin/make/job.c b/usr.bin/make/job.c index 24c77afdee04..323f2af1412f 100644 --- a/usr.bin/make/job.c +++ b/usr.bin/make/job.c @@ -1,4 +1,4 @@ -/* $NetBSD: job.c,v 1.146 2009/06/26 01:26:32 sjg Exp $ */ +/* $NetBSD: job.c,v 1.147 2010/04/07 00:11:27 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -70,14 +70,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: job.c,v 1.146 2009/06/26 01:26:32 sjg Exp $"; +static char rcsid[] = "$NetBSD: job.c,v 1.147 2010/04/07 00:11:27 sjg Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: job.c,v 1.146 2009/06/26 01:26:32 sjg Exp $"); +__RCSID("$NetBSD: job.c,v 1.147 2010/04/07 00:11:27 sjg Exp $"); #endif #endif /* not lint */ #endif @@ -1225,8 +1225,8 @@ Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...)) 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); } } diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c index f6fb0808850d..af68e0a94207 100644 --- a/usr.bin/make/main.c +++ b/usr.bin/make/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.175 2010/01/04 17:05:25 sjg Exp $ */ +/* $NetBSD: main.c,v 1.176 2010/04/07 00:11:27 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -69,7 +69,7 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: main.c,v 1.175 2010/01/04 17:05:25 sjg Exp $"; +static char rcsid[] = "$NetBSD: main.c,v 1.176 2010/04/07 00:11:27 sjg Exp $"; #else #include #ifndef lint @@ -81,7 +81,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\ #if 0 static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: main.c,v 1.175 2010/01/04 17:05:25 sjg Exp $"); +__RCSID("$NetBSD: main.c,v 1.176 2010/04/07 00:11:27 sjg Exp $"); #endif #endif /* not lint */ #endif @@ -184,6 +184,7 @@ static Boolean ignorePWD; /* if we use -C, PWD is meaningless */ 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 void *q) 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,27 @@ siginfo(int signo) } #endif +/* + * Allow makefiles some control over the mode we run in. + */ +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 +851,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 +1098,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 +1277,11 @@ ReadMakefile(const void *p, const void *q __unused) 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 +1328,7 @@ ReadMakefile(const void *p, const void *q __unused) * 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 +1721,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 +1753,7 @@ Punt(const char *fmt, ...) (void)fprintf(stderr, "\n"); (void)fflush(stderr); - PrintOnError(NULL); + PrintOnError(NULL, NULL); DieHorribly(); } @@ -1819,15 +1874,32 @@ 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); + } + /* + * See if there is a .ERROR target, and run it if so. + */ + 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); diff --git a/usr.bin/make/make.1 b/usr.bin/make/make.1 index c72f2dfe402e..a5a290b24497 100644 --- a/usr.bin/make/make.1 +++ b/usr.bin/make/make.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: make.1,v 1.167 2010/02/22 19:20:33 joerg Exp $ +.\" $NetBSD: make.1,v 1.168 2010/04/07 00:11:27 sjg Exp $ .\" .\" Copyright (c) 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" from: @(#)make.1 8.4 (Berkeley) 3/19/94 .\" -.Dd November 15, 2009 +.Dd April 6, 2010 .Dt MAKE 1 .Os .Sh NAME @@ -652,14 +652,34 @@ The preferred variable to use is the environment variable 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 , which is useful for tracking dependencies. Each makefile is recorded only once, regardless of the number of times read. +.It Va .MAKE.MODE +Processed after reading all makefiles. +Can affect the mode that +.Nm +runs in. +Currently just +.Ql Pa compat +mode. .It Va .MAKE.LEVEL The recursion depth of .Nm . @@ -1274,6 +1294,11 @@ Conditional expressions are also preceded by a single dot as the first 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 @@ -1286,6 +1311,8 @@ flag, so should be used with caution. Appending a variable name to .Va .MAKE.EXPORTED is equivalent to exporting a variable. +.It Ic .info Ar message +The message is printed along with the name of the makefile and line number. .It Ic .unexport Ar variable ... The opposite of .Ql .export . @@ -1325,6 +1352,10 @@ will also be pushed into the new environment. .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 prefixed by +.Ql Pa warning: +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 +1658,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 diff --git a/usr.bin/make/make.c b/usr.bin/make/make.c index aa8f8bcd7397..11e2ca8cba3a 100644 --- a/usr.bin/make/make.c +++ b/usr.bin/make/make.c @@ -1,4 +1,4 @@ -/* $NetBSD: make.c,v 1.78 2009/01/23 21:26:30 dsl Exp $ */ +/* $NetBSD: make.c,v 1.79 2010/04/07 00:11:27 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -69,14 +69,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: make.c,v 1.78 2009/01/23 21:26:30 dsl Exp $"; +static char rcsid[] = "$NetBSD: make.c,v 1.79 2010/04/07 00:11:27 sjg Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)make.c 8.1 (Berkeley) 6/6/93"; #else -__RCSID("$NetBSD: make.c,v 1.78 2009/01/23 21:26:30 dsl Exp $"); +__RCSID("$NetBSD: make.c,v 1.79 2010/04/07 00:11:27 sjg Exp $"); #endif #endif /* not lint */ #endif @@ -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; } /*- diff --git a/usr.bin/make/make.h b/usr.bin/make/make.h index 582dae4c335f..b86d9df9f4d3 100644 --- a/usr.bin/make/make.h +++ b/usr.bin/make/make.h @@ -1,4 +1,4 @@ -/* $NetBSD: make.h,v 1.79 2009/09/08 17:29:20 sjg Exp $ */ +/* $NetBSD: make.h,v 1.80 2010/04/07 00:11:27 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -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 include path. */ 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 name */ #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 *); diff --git a/usr.bin/make/nonints.h b/usr.bin/make/nonints.h index c22307cb5364..da6100ee1fc6 100644 --- a/usr.bin/make/nonints.h +++ b/usr.bin/make/nonints.h @@ -1,4 +1,4 @@ -/* $NetBSD: nonints.h,v 1.57 2009/11/19 00:30:24 sjg Exp $ */ +/* $NetBSD: nonints.h,v 1.58 2010/04/07 00:11:27 sjg Exp $ */ /*- * Copyright (c) 1988, 1989, 1990, 1993 @@ -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))); diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c index 49bc79cd9e39..5c74110d67bd 100644 --- a/usr.bin/make/parse.c +++ b/usr.bin/make/parse.c @@ -1,4 +1,4 @@ -/* $NetBSD: parse.c,v 1.160 2009/11/19 00:30:25 sjg Exp $ */ +/* $NetBSD: parse.c,v 1.161 2010/04/07 00:11:27 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -69,14 +69,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: parse.c,v 1.160 2009/11/19 00:30:25 sjg Exp $"; +static char rcsid[] = "$NetBSD: parse.c,v 1.161 2010/04/07 00:11:27 sjg Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: parse.c,v 1.160 2009/11/19 00:30:25 sjg Exp $"); +__RCSID("$NetBSD: parse.c,v 1.161 2010/04/07 00:11:27 sjg Exp $"); #endif #endif /* not lint */ #endif @@ -497,6 +497,50 @@ Parse_Error(int type, const char *fmt, ...) } } + +/* + * ParseMessage + * Parse a .info .warning or .error directive + * + * The input is the line minus the ".". 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 mtype; + + switch(*line) { + case 'i': + mtype = 0; + break; + case 'w': + mtype = PARSE_WARNING; + break; + case 'e': + mtype = PARSE_FATAL; + break; + default: + Parse_Error(PARSE_WARNING, "invalid syntax: \".%s\"", line); + return; + } + + while (!isspace((u_char)*line)) + line++; + while (isspace((u_char)*line)) + line++; + + line = Var_Subst(NULL, line, VAR_CMD, 0); + Parse_Error(mtype, "%s", line); + free(line); + + if (mtype == PARSE_FATAL) { + /* Terminate immediately. */ + exit(1); + } +} + /*- *--------------------------------------------------------------------- * ParseLinkSrc -- @@ -2513,7 +2557,12 @@ Parse_File(const char *name, int fd) } else if (strncmp(cp, "unexport", 8) == 0) { Var_UnExport(cp); continue; - } + } else if (strncmp(cp, "info", 4) == 0 || + strncmp(cp, "error", 5) == 0 || + strncmp(cp, "warning", 7) == 0) { + ParseMessage(cp); + continue; + } } if (*line == '\t') { @@ -2661,7 +2710,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); } }