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