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