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