Annotation of src/usr.bin/make/main.c, Revision 1.8
1.8 ! briggs 1: /* $OpenBSD: main.c,v 1.7 1996/04/21 23:43:21 deraadt Exp $ */
! 2: /* $NetBSD: main.c,v 1.30 1996/08/13 16:42:08 christos Exp $ */
1.1 deraadt 3:
4: /*
5: * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
6: * Copyright (c) 1988, 1989 by Adam de Boor
7: * Copyright (c) 1989 by Berkeley Softworks
8: * All rights reserved.
9: *
10: * This code is derived from software contributed to Berkeley by
11: * Adam de Boor.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. All advertising materials mentioning features or use of this software
22: * must display the following acknowledgement:
23: * This product includes software developed by the University of
24: * California, Berkeley and its contributors.
25: * 4. Neither the name of the University nor the names of its contributors
26: * may be used to endorse or promote products derived from this software
27: * without specific prior written permission.
28: *
29: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39: * SUCH DAMAGE.
40: */
41:
42: #ifndef lint
43: char copyright[] =
44: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
45: All rights reserved.\n";
46: #endif /* not lint */
47:
48: #ifndef lint
49: #if 0
50: static char sccsid[] = "@(#)main.c 5.25 (Berkeley) 4/1/91";
1.6 niklas 51: static char rcsid[] = "$NetBSD: main.c,v 1.26 1996/03/11 13:45:33 christos Exp $";
1.1 deraadt 52: #else
1.8 ! briggs 53: static char rcsid[] = "$OpenBSD: main.c,v 1.7 1996/04/21 23:43:21 deraadt Exp $";
1.1 deraadt 54: #endif
55: #endif /* not lint */
56:
57: /*-
58: * main.c --
59: * The main file for this entire program. Exit routines etc
60: * reside here.
61: *
62: * Utility functions defined in this file:
63: * Main_ParseArgLine Takes a line of arguments, breaks them and
64: * treats them as if they were given when first
65: * invoked. Used by the parse module to implement
66: * the .MFLAGS target.
67: *
68: * Error Print a tagged error message. The global
69: * MAKE variable must have been defined. This
70: * takes a format string and two optional
71: * arguments for it.
72: *
73: * Fatal Print an error message and exit. Also takes
74: * a format string and two arguments.
75: *
76: * Punt Aborts all jobs and exits with a message. Also
77: * takes a format string and two arguments.
78: *
79: * Finish Finish things up by printing the number of
80: * errors which occured, as passed to it, and
81: * exiting.
82: */
83:
84: #include <sys/types.h>
85: #include <sys/time.h>
86: #include <sys/param.h>
87: #include <sys/resource.h>
1.2 deraadt 88: #include <sys/signal.h>
1.1 deraadt 89: #include <sys/stat.h>
90: #include <sys/utsname.h>
1.8 ! briggs 91: #include <sys/wait.h>
1.1 deraadt 92: #include <errno.h>
93: #include <fcntl.h>
94: #include <stdio.h>
95: #if __STDC__
96: #include <stdarg.h>
97: #else
98: #include <varargs.h>
99: #endif
100: #include "make.h"
101: #include "hash.h"
102: #include "dir.h"
103: #include "job.h"
104: #include "pathnames.h"
105:
106: #ifndef DEFMAXLOCAL
107: #define DEFMAXLOCAL DEFMAXJOBS
1.4 niklas 108: #endif /* DEFMAXLOCAL */
1.1 deraadt 109:
110: #define MAKEFLAGS ".MAKEFLAGS"
111:
112: Lst create; /* Targets to be made */
113: time_t now; /* Time at start of make */
114: GNode *DEFAULT; /* .DEFAULT node */
115: Boolean allPrecious; /* .PRECIOUS given on line by itself */
116:
117: static Boolean noBuiltins; /* -r flag */
118: static Lst makefiles; /* ordered list of makefiles to read */
1.2 deraadt 119: int maxJobs; /* -j argument */
1.1 deraadt 120: static int maxLocal; /* -L argument */
121: Boolean compatMake; /* -B argument */
122: Boolean debug; /* -d flag */
123: Boolean noExecute; /* -n flag */
124: Boolean keepgoing; /* -k flag */
125: Boolean queryFlag; /* -q flag */
126: Boolean touchFlag; /* -t flag */
127: Boolean usePipes; /* !-P flag */
128: Boolean ignoreErrors; /* -i flag */
129: Boolean beSilent; /* -s flag */
130: Boolean oldVars; /* variable substitution style */
131: Boolean checkEnvFirst; /* -e flag */
132: static Boolean jobsRunning; /* TRUE if the jobs might be running */
133:
134: static Boolean ReadMakefile();
135: static void usage();
136:
137: static char *curdir; /* startup directory */
138: static char *objdir; /* where we chdir'ed to */
139:
140: /*-
141: * MainParseArgs --
142: * Parse a given argument vector. Called from main() and from
143: * Main_ParseArgLine() when the .MAKEFLAGS target is used.
144: *
145: * XXX: Deal with command line overriding .MAKEFLAGS in makefile
146: *
147: * Results:
148: * None
149: *
150: * Side Effects:
151: * Various global and local flags will be set depending on the flags
152: * given
153: */
154: static void
155: MainParseArgs(argc, argv)
156: int argc;
157: char **argv;
158: {
159: extern int optind;
160: extern char *optarg;
161: int c;
1.2 deraadt 162: int forceJobs = 0;
1.1 deraadt 163:
164: optind = 1; /* since we're called more than once */
1.2 deraadt 165: #ifdef REMOTE
1.5 niklas 166: # define OPTFLAGS "BD:I:L:PSd:ef:ij:km:nqrst"
1.1 deraadt 167: #else
1.5 niklas 168: # define OPTFLAGS "BD:I:PSd:ef:ij:km:nqrst"
1.1 deraadt 169: #endif
170: rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
171: switch(c) {
172: case 'D':
173: Var_Set(optarg, "1", VAR_GLOBAL);
174: Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
175: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
176: break;
177: case 'I':
178: Parse_AddIncludeDir(optarg);
179: Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
180: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
181: break;
182: case 'B':
183: compatMake = TRUE;
184: break;
1.2 deraadt 185: #ifdef REMOTE
1.1 deraadt 186: case 'L':
187: maxLocal = atoi(optarg);
188: Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
189: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
190: break;
1.2 deraadt 191: #endif
1.1 deraadt 192: case 'P':
193: usePipes = FALSE;
194: Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
195: break;
196: case 'S':
197: keepgoing = FALSE;
198: Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
199: break;
200: case 'd': {
201: char *modules = optarg;
202:
203: for (; *modules; ++modules)
204: switch (*modules) {
205: case 'A':
206: debug = ~0;
207: break;
208: case 'a':
209: debug |= DEBUG_ARCH;
210: break;
211: case 'c':
212: debug |= DEBUG_COND;
213: break;
214: case 'd':
215: debug |= DEBUG_DIR;
216: break;
217: case 'f':
218: debug |= DEBUG_FOR;
219: break;
220: case 'g':
221: if (modules[1] == '1') {
222: debug |= DEBUG_GRAPH1;
223: ++modules;
224: }
225: else if (modules[1] == '2') {
226: debug |= DEBUG_GRAPH2;
227: ++modules;
228: }
229: break;
230: case 'j':
231: debug |= DEBUG_JOB;
232: break;
233: case 'm':
234: debug |= DEBUG_MAKE;
235: break;
236: case 's':
237: debug |= DEBUG_SUFF;
238: break;
239: case 't':
240: debug |= DEBUG_TARG;
241: break;
242: case 'v':
243: debug |= DEBUG_VAR;
244: break;
245: default:
246: (void)fprintf(stderr,
247: "make: illegal argument to d option -- %c\n",
248: *modules);
249: usage();
250: }
251: Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
252: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
253: break;
254: }
255: case 'e':
256: checkEnvFirst = TRUE;
257: Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
258: break;
259: case 'f':
260: (void)Lst_AtEnd(makefiles, (ClientData)optarg);
261: break;
262: case 'i':
263: ignoreErrors = TRUE;
264: Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
265: break;
266: case 'j':
1.2 deraadt 267: forceJobs = TRUE;
1.1 deraadt 268: maxJobs = atoi(optarg);
1.2 deraadt 269: #ifndef REMOTE
270: maxLocal = maxJobs;
271: #endif
1.1 deraadt 272: Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
273: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
274: break;
275: case 'k':
276: keepgoing = TRUE;
277: Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
278: break;
1.5 niklas 279: case 'm':
280: Dir_AddDir(sysIncPath, optarg);
281: Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
282: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
283: break;
1.1 deraadt 284: case 'n':
285: noExecute = TRUE;
286: Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
287: break;
288: case 'q':
289: queryFlag = TRUE;
290: /* Kind of nonsensical, wot? */
291: Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
292: break;
293: case 'r':
294: noBuiltins = TRUE;
295: Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
296: break;
297: case 's':
298: beSilent = TRUE;
299: Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
300: break;
301: case 't':
302: touchFlag = TRUE;
303: Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
304: break;
305: default:
306: case '?':
307: usage();
308: }
309: }
310:
1.2 deraadt 311: /*
312: * Be compatible if user did not specify -j and did not explicitly
313: * turned compatibility on
314: */
315: if (!compatMake && !forceJobs)
316: compatMake = TRUE;
317:
1.1 deraadt 318: oldVars = TRUE;
319:
320: /*
321: * See if the rest of the arguments are variable assignments and
322: * perform them if so. Else take them to be targets and stuff them
323: * on the end of the "create" list.
324: */
325: for (argv += optind, argc -= optind; *argv; ++argv, --argc)
1.3 deraadt 326: if (Parse_IsVar(*argv)) {
327: char *var = strdup(*argv);
328:
329: Parse_DoVar(var, VAR_CMD);
330: free(var);
331: } else {
1.1 deraadt 332: if (!**argv)
333: Punt("illegal (null) argument.");
334: if (**argv == '-') {
335: if ((*argv)[1])
336: optind = 0; /* -flag... */
337: else
338: optind = 1; /* - */
339: goto rearg;
340: }
1.8 ! briggs 341: (void)Lst_AtEnd(create, (ClientData)estrdup(*argv));
1.1 deraadt 342: }
343: }
344:
345: /*-
346: * Main_ParseArgLine --
347: * Used by the parse module when a .MFLAGS or .MAKEFLAGS target
348: * is encountered and by main() when reading the .MAKEFLAGS envariable.
349: * Takes a line of arguments and breaks it into its
350: * component words and passes those words and the number of them to the
351: * MainParseArgs function.
352: * The line should have all its leading whitespace removed.
353: *
354: * Results:
355: * None
356: *
357: * Side Effects:
358: * Only those that come from the various arguments.
359: */
360: void
361: Main_ParseArgLine(line)
362: char *line; /* Line to fracture */
363: {
364: char **argv; /* Manufactured argument vector */
365: int argc; /* Number of arguments in argv */
366:
367: if (line == NULL)
368: return;
369: for (; *line == ' '; ++line)
370: continue;
371: if (!*line)
372: return;
373:
374: argv = brk_string(line, &argc, TRUE);
375: MainParseArgs(argc, argv);
376: }
377:
378: /*-
379: * main --
380: * The main function, for obvious reasons. Initializes variables
381: * and a few modules, then parses the arguments give it in the
382: * environment and on the command line. Reads the system makefile
383: * followed by either Makefile, makefile or the file given by the
384: * -f argument. Sets the .MAKEFLAGS PMake variable based on all the
385: * flags it has received by then uses either the Make or the Compat
386: * module to create the initial list of targets.
387: *
388: * Results:
389: * If -q was given, exits -1 if anything was out-of-date. Else it exits
390: * 0.
391: *
392: * Side Effects:
393: * The program exits when done. Targets are created. etc. etc. etc.
394: */
395: int
396: main(argc, argv)
397: int argc;
398: char **argv;
399: {
400: Lst targs; /* target nodes to create -- passed to Make_Init */
401: Boolean outOfDate = TRUE; /* FALSE if all targets up to date */
402: struct stat sb, sa;
403: char *p, *p1, *path, *pwd, *getenv(), *getwd();
404: char mdpath[MAXPATHLEN + 1];
405: char obpath[MAXPATHLEN + 1];
406: char cdpath[MAXPATHLEN + 1];
407: struct utsname utsname;
408: char *machine = getenv("MACHINE");
1.5 niklas 409: Lst sysMkPath; /* Path of sys.mk */
410: char *cp = NULL, *start;
411: /* avoid faults on read-only strings */
412: static char syspath[] = _PATH_DEFSYSPATH;
1.1 deraadt 413:
1.2 deraadt 414: #ifdef RLIMIT_NOFILE
415: /*
416: * get rid of resource limit on file descriptors
417: */
418: {
419: struct rlimit rl;
420: if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
421: rl.rlim_cur != rl.rlim_max) {
422: rl.rlim_cur = rl.rlim_max;
423: (void) setrlimit(RLIMIT_NOFILE, &rl);
424: }
425: }
426: #endif
1.1 deraadt 427: /*
428: * Find where we are and take care of PWD for the automounter...
429: * All this code is so that we know where we are when we start up
430: * on a different machine with pmake.
431: */
432: curdir = cdpath;
433: if (getcwd(curdir, MAXPATHLEN) == NULL) {
434: (void)fprintf(stderr, "make: %s.\n", strerror(errno));
435: exit(2);
436: }
437:
438: if (stat(curdir, &sa) == -1) {
439: (void)fprintf(stderr, "make: %s: %s.\n",
440: curdir, strerror(errno));
441: exit(2);
442: }
443:
444: if ((pwd = getenv("PWD")) != NULL) {
445: if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
446: sa.st_dev == sb.st_dev)
447: (void) strcpy(curdir, pwd);
448: }
449:
450: /*
451: * Get the name of this type of MACHINE from utsname
452: * so we can share an executable for similar machines.
453: * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
454: *
455: * Note that while MACHINE is decided at run-time,
456: * MACHINE_ARCH is always known at compile time.
457: */
458: if (!machine) {
1.6 niklas 459: #ifndef MACHINE
1.2 deraadt 460: if (uname(&utsname) == -1) {
1.1 deraadt 461: perror("make: uname");
462: exit(2);
463: }
464: machine = utsname.machine;
1.6 niklas 465: #else
466: machine = MACHINE;
467: #endif
1.1 deraadt 468: }
469:
470: /*
471: * if the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory
472: * exists, change into it and build there. Once things are
473: * initted, have to add the original directory to the search path,
474: * and modify the paths for the Makefiles apropriately. The
475: * current directory is also placed as a variable for make scripts.
476: */
477: if (!(path = getenv("MAKEOBJDIR"))) {
478: path = _PATH_OBJDIR;
479: (void) sprintf(mdpath, "%s.%s", path, machine);
480: }
481: else
482: (void) strncpy(mdpath, path, MAXPATHLEN + 1);
483:
484: if (stat(mdpath, &sb) == 0 && S_ISDIR(sb.st_mode)) {
485:
486: if (chdir(mdpath)) {
487: (void)fprintf(stderr, "make warning: %s: %s.\n",
488: mdpath, strerror(errno));
489: objdir = curdir;
490: }
491: else {
492: if (mdpath[0] != '/') {
493: (void) sprintf(obpath, "%s/%s", curdir, mdpath);
494: objdir = obpath;
495: }
496: else
497: objdir = mdpath;
498: }
499: }
500: else {
501: if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
502:
503: if (chdir(path)) {
504: (void)fprintf(stderr, "make warning: %s: %s.\n",
505: path, strerror(errno));
506: objdir = curdir;
507: }
508: else {
509: if (path[0] != '/') {
510: (void) sprintf(obpath, "%s/%s", curdir,
511: path);
512: objdir = obpath;
513: }
514: else
515: objdir = obpath;
516: }
517: }
518: else
519: objdir = curdir;
520: }
521:
522: setenv("PWD", objdir, 1);
523:
524: create = Lst_Init(FALSE);
525: makefiles = Lst_Init(FALSE);
526: beSilent = FALSE; /* Print commands as executed */
527: ignoreErrors = FALSE; /* Pay attention to non-zero returns */
528: noExecute = FALSE; /* Execute all commands */
529: keepgoing = FALSE; /* Stop on error */
530: allPrecious = FALSE; /* Remove targets when interrupted */
531: queryFlag = FALSE; /* This is not just a check-run */
532: noBuiltins = FALSE; /* Read the built-in rules */
533: touchFlag = FALSE; /* Actually update targets */
534: usePipes = TRUE; /* Catch child output in pipes */
535: debug = 0; /* No debug verbosity, please. */
536: jobsRunning = FALSE;
537:
1.2 deraadt 538: maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */
539: #ifdef REMOTE
1.1 deraadt 540: maxJobs = DEFMAXJOBS; /* Set default max concurrency */
541: #else
1.2 deraadt 542: maxJobs = maxLocal;
1.1 deraadt 543: #endif
1.2 deraadt 544: compatMake = FALSE; /* No compat mode */
1.1 deraadt 545:
546:
547: /*
548: * Initialize the parsing, directory and variable modules to prepare
549: * for the reading of inclusion paths and variable settings on the
550: * command line
551: */
552: Dir_Init(); /* Initialize directory structures so -I flags
553: * can be processed correctly */
554: Parse_Init(); /* Need to initialize the paths of #include
555: * directories */
556: Var_Init(); /* As well as the lists of variables for
557: * parsing arguments */
558: str_init();
559: if (objdir != curdir)
560: Dir_AddDir(dirSearchPath, curdir);
561: Var_Set(".CURDIR", curdir, VAR_GLOBAL);
562: Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
563:
564: /*
565: * Initialize various variables.
566: * MAKE also gets this name, for compatibility
567: * .MAKEFLAGS gets set to the empty string just in case.
568: * MFLAGS also gets initialized empty, for compatibility.
569: */
570: Var_Set("MAKE", argv[0], VAR_GLOBAL);
571: Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
572: Var_Set("MFLAGS", "", VAR_GLOBAL);
573: Var_Set("MACHINE", machine, VAR_GLOBAL);
574: #ifdef MACHINE_ARCH
575: Var_Set("MACHINE_ARCH", MACHINE_ARCH, VAR_GLOBAL);
576: #endif
577:
578: /*
579: * First snag any flags out of the MAKE environment variable.
580: * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
581: * in a different format).
582: */
583: #ifdef POSIX
584: Main_ParseArgLine(getenv("MAKEFLAGS"));
585: #else
586: Main_ParseArgLine(getenv("MAKE"));
587: #endif
588:
589: MainParseArgs(argc, argv);
590:
591: /*
592: * Initialize archive, target and suffix modules in preparation for
593: * parsing the makefile(s)
594: */
595: Arch_Init();
596: Targ_Init();
597: Suff_Init();
598:
599: DEFAULT = NILGNODE;
600: (void)time(&now);
601:
602: /*
603: * Set up the .TARGETS variable to contain the list of targets to be
604: * created. If none specified, make the variable empty -- the parser
605: * will fill the thing in with the default or .MAIN target.
606: */
607: if (!Lst_IsEmpty(create)) {
608: LstNode ln;
609:
610: for (ln = Lst_First(create); ln != NILLNODE;
611: ln = Lst_Succ(ln)) {
612: char *name = (char *)Lst_Datum(ln);
613:
614: Var_Append(".TARGETS", name, VAR_GLOBAL);
615: }
616: } else
617: Var_Set(".TARGETS", "", VAR_GLOBAL);
618:
1.5 niklas 619:
620: /*
621: * If no user-supplied system path was given (through the -m option)
622: * add the directories from the DEFSYSPATH (more than one may be given
623: * as dir1:...:dirn) to the system include path.
624: */
625: if (Lst_IsEmpty(sysIncPath)) {
626: for (start = syspath; *start != '\0'; start = cp) {
627: for (cp = start; *cp != '\0' && *cp != ':'; cp++)
628: continue;
629: if (*cp == '\0') {
630: Dir_AddDir(sysIncPath, start);
631: } else {
632: *cp++ = '\0';
633: Dir_AddDir(sysIncPath, start);
634: }
635: }
636: }
637:
1.1 deraadt 638: /*
1.5 niklas 639: * Read in the built-in rules first, followed by the specified
640: * makefile, if it was (makefile != (char *) NULL), or the default
641: * Makefile and makefile, in that order, if it wasn't.
1.1 deraadt 642: */
1.5 niklas 643: if (!noBuiltins) {
644: LstNode ln;
645:
646: sysMkPath = Lst_Init (FALSE);
647: Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath);
648: if (Lst_IsEmpty(sysMkPath))
649: Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
650: ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
651: if (ln != NILLNODE)
652: Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
653: }
1.1 deraadt 654:
655: if (!Lst_IsEmpty(makefiles)) {
656: LstNode ln;
657:
658: ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile);
659: if (ln != NILLNODE)
660: Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
661: } else if (!ReadMakefile("makefile"))
662: (void)ReadMakefile("Makefile");
663:
664: (void)ReadMakefile(".depend");
665:
666: Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
667: if (p1)
668: free(p1);
669:
670: /* Install all the flags into the MAKE envariable. */
671: if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p)
672: #ifdef POSIX
673: setenv("MAKEFLAGS", p, 1);
674: #else
675: setenv("MAKE", p, 1);
676: #endif
677: if (p1)
678: free(p1);
679:
680: /*
681: * For compatibility, look at the directories in the VPATH variable
682: * and add them to the search path, if the variable is defined. The
683: * variable's value is in the same format as the PATH envariable, i.e.
684: * <directory>:<directory>:<directory>...
685: */
686: if (Var_Exists("VPATH", VAR_CMD)) {
687: char *vpath, *path, *cp, savec;
688: /*
689: * GCC stores string constants in read-only memory, but
690: * Var_Subst will want to write this thing, so store it
691: * in an array
692: */
693: static char VPATH[] = "${VPATH}";
694:
695: vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
696: path = vpath;
697: do {
698: /* skip to end of directory */
699: for (cp = path; *cp != ':' && *cp != '\0'; cp++)
700: continue;
701: /* Save terminator character so know when to stop */
702: savec = *cp;
703: *cp = '\0';
704: /* Add directory to search path */
705: Dir_AddDir(dirSearchPath, path);
706: *cp = savec;
707: path = cp + 1;
708: } while (savec == ':');
709: (void)free((Address)vpath);
710: }
711:
712: /*
713: * Now that all search paths have been read for suffixes et al, it's
714: * time to add the default search path to their lists...
715: */
716: Suff_DoPaths();
717:
718: /* print the initial graph, if the user requested it */
719: if (DEBUG(GRAPH1))
720: Targ_PrintGraph(1);
721:
722: /*
723: * Have now read the entire graph and need to make a list of targets
724: * to create. If none was given on the command line, we consult the
725: * parsing module to find the main target(s) to create.
726: */
727: if (Lst_IsEmpty(create))
728: targs = Parse_MainName();
729: else
730: targs = Targ_FindList(create, TARG_CREATE);
731:
732: if (!compatMake) {
733: /*
734: * Initialize job module before traversing the graph, now that
735: * any .BEGIN and .END targets have been read. This is done
736: * only if the -q flag wasn't given (to prevent the .BEGIN from
737: * being executed should it exist).
738: */
739: if (!queryFlag) {
740: if (maxLocal == -1)
741: maxLocal = maxJobs;
742: Job_Init(maxJobs, maxLocal);
743: jobsRunning = TRUE;
744: }
745:
746: /* Traverse the graph, checking on all the targets */
747: outOfDate = Make_Run(targs);
748: } else
749: /*
750: * Compat_Init will take care of creating all the targets as
751: * well as initializing the module.
752: */
753: Compat_Run(targs);
754:
755: Lst_Destroy(targs, NOFREE);
756: Lst_Destroy(makefiles, NOFREE);
757: Lst_Destroy(create, (void (*) __P((ClientData))) free);
758:
759: /* print the graph now it's been processed if the user requested it */
760: if (DEBUG(GRAPH2))
761: Targ_PrintGraph(2);
762:
763: Suff_End();
764: Targ_End();
765: Arch_End();
766: str_end();
767: Var_End();
768: Parse_End();
769: Dir_End();
770:
771: if (queryFlag && outOfDate)
772: return(1);
773: else
774: return(0);
775: }
776:
777: /*-
778: * ReadMakefile --
779: * Open and parse the given makefile.
780: *
781: * Results:
782: * TRUE if ok. FALSE if couldn't open file.
783: *
784: * Side Effects:
785: * lots
786: */
787: static Boolean
788: ReadMakefile(fname)
789: char *fname; /* makefile to read */
790: {
1.5 niklas 791: extern Lst parseIncPath;
1.1 deraadt 792: FILE *stream;
793: char *name, path[MAXPATHLEN + 1];
794:
795: if (!strcmp(fname, "-")) {
796: Parse_File("(stdin)", stdin);
797: Var_Set("MAKEFILE", "", VAR_GLOBAL);
798: } else {
799: if ((stream = fopen(fname, "r")) != NULL)
800: goto found;
801: /* if we've chdir'd, rebuild the path name */
802: if (curdir != objdir && *fname != '/') {
803: (void)sprintf(path, "%s/%s", curdir, fname);
804: if ((stream = fopen(path, "r")) != NULL) {
805: fname = path;
806: goto found;
807: }
808: }
809: /* look in -I and system include directories. */
810: name = Dir_FindFile(fname, parseIncPath);
811: if (!name)
812: name = Dir_FindFile(fname, sysIncPath);
813: if (!name || !(stream = fopen(name, "r")))
814: return(FALSE);
815: fname = name;
816: /*
817: * set the MAKEFILE variable desired by System V fans -- the
818: * placement of the setting here means it gets set to the last
819: * makefile specified, as it is set by SysV make.
820: */
821: found: Var_Set("MAKEFILE", fname, VAR_GLOBAL);
822: Parse_File(fname, stream);
823: (void)fclose(stream);
824: }
825: return(TRUE);
826: }
827:
828: /*-
1.8 ! briggs 829: * Cmd_Exec --
! 830: * Execute the command in cmd, and return the output of that command
! 831: * in a string.
! 832: *
! 833: * Results:
! 834: * A string containing the output of the command, or the empty string
! 835: * If err is not NULL, it contains the reason for the command failure
! 836: *
! 837: * Side Effects:
! 838: * The string must be freed by the caller.
! 839: */
! 840: char *
! 841: Cmd_Exec(cmd, err)
! 842: char *cmd;
! 843: char **err;
! 844: {
! 845: char *args[4]; /* Args for invoking the shell */
! 846: int fds[2]; /* Pipe streams */
! 847: int cpid; /* Child PID */
! 848: int pid; /* PID from wait() */
! 849: char *res; /* result */
! 850: int status; /* command exit status */
! 851: Buffer buf; /* buffer to store the result */
! 852: char *cp;
! 853: int cc;
! 854:
! 855:
! 856: *err = NULL;
! 857:
! 858: /*
! 859: * Set up arguments for shell
! 860: */
! 861: args[0] = "sh";
! 862: args[1] = "-c";
! 863: args[2] = cmd;
! 864: args[3] = NULL;
! 865:
! 866: /*
! 867: * Open a pipe for fetching its output
! 868: */
! 869: if (pipe(fds) == -1) {
! 870: *err = "Couldn't create pipe for \"%s\"";
! 871: goto bad;
! 872: }
! 873:
! 874: /*
! 875: * Fork
! 876: */
! 877: switch (cpid = vfork()) {
! 878: case 0:
! 879: /*
! 880: * Close input side of pipe
! 881: */
! 882: (void) close(fds[0]);
! 883:
! 884: /*
! 885: * Duplicate the output stream to the shell's output, then
! 886: * shut the extra thing down. Note we don't fetch the error
! 887: * stream...why not? Why?
! 888: */
! 889: (void) dup2(fds[1], 1);
! 890: (void) close(fds[1]);
! 891:
! 892: (void) execv("/bin/sh", args);
! 893: _exit(1);
! 894: /*NOTREACHED*/
! 895:
! 896: case -1:
! 897: *err = "Couldn't exec \"%s\"";
! 898: goto bad;
! 899:
! 900: default:
! 901: /*
! 902: * No need for the writing half
! 903: */
! 904: (void) close(fds[1]);
! 905:
! 906: buf = Buf_Init (MAKE_BSIZE);
! 907:
! 908: do {
! 909: char result[BUFSIZ];
! 910: cc = read(fds[0], result, sizeof(result));
! 911: if (cc > 0)
! 912: Buf_AddBytes(buf, cc, (Byte *) result);
! 913: }
! 914: while (cc > 0 || (cc == -1 && errno == EINTR));
! 915:
! 916: /*
! 917: * Close the input side of the pipe.
! 918: */
! 919: (void) close(fds[0]);
! 920:
! 921: /*
! 922: * Wait for the process to exit.
! 923: */
! 924: while(((pid = wait(&status)) != cpid) && (pid >= 0))
! 925: continue;
! 926:
! 927: res = (char *)Buf_GetAll (buf, &cc);
! 928: Buf_Destroy (buf, FALSE);
! 929:
! 930: if (cc == 0)
! 931: *err = "Couldn't read shell's output for \"%s\"";
! 932:
! 933: if (status)
! 934: *err = "\"%s\" returned non-zero status";
! 935:
! 936: /*
! 937: * Null-terminate the result, convert newlines to spaces and
! 938: * install it in the variable.
! 939: */
! 940: res[cc] = '\0';
! 941: cp = &res[cc] - 1;
! 942:
! 943: if (*cp == '\n') {
! 944: /*
! 945: * A final newline is just stripped
! 946: */
! 947: *cp-- = '\0';
! 948: }
! 949: while (cp >= res) {
! 950: if (*cp == '\n') {
! 951: *cp = ' ';
! 952: }
! 953: cp--;
! 954: }
! 955: break;
! 956: }
! 957: return res;
! 958: bad:
! 959: res = emalloc(1);
! 960: *res = '\0';
! 961: return res;
! 962: }
! 963:
! 964: /*-
1.1 deraadt 965: * Error --
966: * Print an error message given its format.
967: *
968: * Results:
969: * None.
970: *
971: * Side Effects:
972: * The message is printed.
973: */
974: /* VARARGS */
975: void
976: #if __STDC__
977: Error(char *fmt, ...)
978: #else
979: Error(va_alist)
980: va_dcl
981: #endif
982: {
983: va_list ap;
984: #if __STDC__
985: va_start(ap, fmt);
986: #else
987: char *fmt;
988:
989: va_start(ap);
990: fmt = va_arg(ap, char *);
991: #endif
992: (void)vfprintf(stderr, fmt, ap);
993: va_end(ap);
994: (void)fprintf(stderr, "\n");
995: (void)fflush(stderr);
996: }
997:
998: /*-
999: * Fatal --
1000: * Produce a Fatal error message. If jobs are running, waits for them
1001: * to finish.
1002: *
1003: * Results:
1004: * None
1005: *
1006: * Side Effects:
1007: * The program exits
1008: */
1009: /* VARARGS */
1010: void
1011: #if __STDC__
1012: Fatal(char *fmt, ...)
1013: #else
1014: Fatal(va_alist)
1015: va_dcl
1016: #endif
1017: {
1018: va_list ap;
1019: #if __STDC__
1020: va_start(ap, fmt);
1021: #else
1022: char *fmt;
1023:
1024: va_start(ap);
1025: fmt = va_arg(ap, char *);
1026: #endif
1027: if (jobsRunning)
1028: Job_Wait();
1029:
1030: (void)vfprintf(stderr, fmt, ap);
1031: va_end(ap);
1032: (void)fprintf(stderr, "\n");
1033: (void)fflush(stderr);
1034:
1035: if (DEBUG(GRAPH2))
1036: Targ_PrintGraph(2);
1037: exit(2); /* Not 1 so -q can distinguish error */
1038: }
1039:
1040: /*
1041: * Punt --
1042: * Major exception once jobs are being created. Kills all jobs, prints
1043: * a message and exits.
1044: *
1045: * Results:
1046: * None
1047: *
1048: * Side Effects:
1049: * All children are killed indiscriminately and the program Lib_Exits
1050: */
1051: /* VARARGS */
1052: void
1053: #if __STDC__
1054: Punt(char *fmt, ...)
1055: #else
1056: Punt(va_alist)
1057: va_dcl
1058: #endif
1059: {
1060: va_list ap;
1061: #if __STDC__
1062: va_start(ap, fmt);
1063: #else
1064: char *fmt;
1065:
1066: va_start(ap);
1067: fmt = va_arg(ap, char *);
1068: #endif
1069:
1070: (void)fprintf(stderr, "make: ");
1071: (void)vfprintf(stderr, fmt, ap);
1072: va_end(ap);
1073: (void)fprintf(stderr, "\n");
1074: (void)fflush(stderr);
1075:
1076: DieHorribly();
1077: }
1078:
1079: /*-
1080: * DieHorribly --
1081: * Exit without giving a message.
1082: *
1083: * Results:
1084: * None
1085: *
1086: * Side Effects:
1087: * A big one...
1088: */
1089: void
1090: DieHorribly()
1091: {
1092: if (jobsRunning)
1093: Job_AbortAll();
1094: if (DEBUG(GRAPH2))
1095: Targ_PrintGraph(2);
1096: exit(2); /* Not 1, so -q can distinguish error */
1097: }
1098:
1099: /*
1100: * Finish --
1101: * Called when aborting due to errors in child shell to signal
1102: * abnormal exit.
1103: *
1104: * Results:
1105: * None
1106: *
1107: * Side Effects:
1108: * The program exits
1109: */
1110: void
1111: Finish(errors)
1112: int errors; /* number of errors encountered in Make_Make */
1113: {
1114: Fatal("%d error%s", errors, errors == 1 ? "" : "s");
1115: }
1116:
1117: /*
1118: * emalloc --
1119: * malloc, but die on error.
1120: */
1.7 deraadt 1121: void *
1.1 deraadt 1122: emalloc(len)
1123: size_t len;
1124: {
1.7 deraadt 1125: void *p;
1.1 deraadt 1126:
1.7 deraadt 1127: if ((p = malloc(len)) == NULL)
1.8 ! briggs 1128: enomem();
! 1129: return(p);
! 1130: }
! 1131:
! 1132: /*
! 1133: * emalloc --
! 1134: * strdup, but die on error.
! 1135: */
! 1136: char *
! 1137: estrdup(str)
! 1138: const char *str;
! 1139: {
! 1140: char *p;
! 1141:
! 1142: if ((p = strdup(str)) == NULL)
1.1 deraadt 1143: enomem();
1144: return(p);
1.7 deraadt 1145: }
1146:
1147: /*
1148: * erealloc --
1149: * realloc, but die on error.
1150: */
1151: void *
1152: erealloc(ptr, size)
1153: void *ptr;
1154: size_t size;
1155: {
1156: if ((ptr = realloc(ptr, size)) == NULL)
1157: enomem();
1158: return(ptr);
1.1 deraadt 1159: }
1160:
1161: /*
1162: * enomem --
1163: * die when out of memory.
1164: */
1165: void
1166: enomem()
1167: {
1168: (void)fprintf(stderr, "make: %s.\n", strerror(errno));
1169: exit(2);
1.2 deraadt 1170: }
1171:
1172: /*
1173: * enunlink --
1174: * Remove a file carefully, avoiding directories.
1175: */
1176: int
1177: eunlink(file)
1178: const char *file;
1179: {
1180: struct stat st;
1181:
1182: if (lstat(file, &st) == -1)
1183: return -1;
1184:
1185: if (S_ISDIR(st.st_mode)) {
1186: errno = EISDIR;
1187: return -1;
1188: }
1189: return unlink(file);
1.1 deraadt 1190: }
1191:
1192: /*
1193: * usage --
1194: * exit with usage message
1195: */
1196: static void
1197: usage()
1198: {
1199: (void)fprintf(stderr,
1200: "usage: make [-eiknqrst] [-D variable] [-d flags] [-f makefile ]\n\
1.5 niklas 1201: [-I directory] [-j max_jobs] [-m directory] [variable=value]\n");
1.1 deraadt 1202: exit(2);
1203: }
1204:
1205:
1206: int
1207: PrintAddr(a, b)
1208: ClientData a;
1209: ClientData b;
1210: {
1211: printf("%lx ", (unsigned long) a);
1212: return b ? 0 : 0;
1213: }