Annotation of src/usr.bin/make/main.c, Revision 1.558
1.558 ! rillig 1: /* $NetBSD: main.c,v 1.557 2021/12/27 23:11:55 rillig Exp $ */
1.19 christos 2:
1.1 cgd 3: /*
1.31 christos 4: * Copyright (c) 1988, 1989, 1990, 1993
5: * The Regents of the University of California. All rights reserved.
1.91 agc 6: *
7: * This code is derived from software contributed to Berkeley by
8: * Adam de Boor.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. Neither the name of the University nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: */
34:
35: /*
1.1 cgd 36: * Copyright (c) 1989 by Berkeley Softworks
37: * All rights reserved.
38: *
39: * This code is derived from software contributed to Berkeley by
40: * Adam de Boor.
41: *
42: * Redistribution and use in source and binary forms, with or without
43: * modification, are permitted provided that the following conditions
44: * are met:
45: * 1. Redistributions of source code must retain the above copyright
46: * notice, this list of conditions and the following disclaimer.
47: * 2. Redistributions in binary form must reproduce the above copyright
48: * notice, this list of conditions and the following disclaimer in the
49: * documentation and/or other materials provided with the distribution.
50: * 3. All advertising materials mentioning features or use of this software
51: * must display the following acknowledgement:
52: * This product includes software developed by the University of
53: * California, Berkeley and its contributors.
54: * 4. Neither the name of the University nor the names of its contributors
55: * may be used to endorse or promote products derived from this software
56: * without specific prior written permission.
57: *
58: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68: * SUCH DAMAGE.
69: */
70:
1.507 rillig 71: /*
72: * The main file for this entire program. Exit routines etc. reside here.
1.1 cgd 73: *
74: * Utility functions defined in this file:
75: *
1.521 rillig 76: * Main_ParseArgLine
77: * Parse and process command line arguments from a
78: * single string. Used to implement the special targets
79: * .MFLAGS and .MAKEFLAGS.
1.438 rillig 80: *
1.521 rillig 81: * Error Print a tagged error message.
1.438 rillig 82: *
1.521 rillig 83: * Fatal Print an error message and exit.
1.1 cgd 84: *
1.521 rillig 85: * Punt Abort all jobs and exit with a message.
1.1 cgd 86: *
1.521 rillig 87: * Finish Finish things up by printing the number of errors
88: * that occurred, and exit.
1.1 cgd 89: */
90:
1.13 cgd 91: #include <sys/types.h>
92: #include <sys/time.h>
1.1 cgd 93: #include <sys/param.h>
1.13 cgd 94: #include <sys/resource.h>
1.1 cgd 95: #include <sys/stat.h>
1.225 matt 96: #ifdef MAKE_NATIVE
97: #include <sys/sysctl.h>
98: #endif
1.17 gwr 99: #include <sys/utsname.h>
1.29 christos 100: #include <sys/wait.h>
1.85 wiz 101:
1.1 cgd 102: #include <errno.h>
1.215 christos 103: #include <signal.h>
1.85 wiz 104: #include <stdarg.h>
1.42 kleink 105: #include <time.h>
1.85 wiz 106:
1.1 cgd 107: #include "make.h"
1.13 cgd 108: #include "dir.h"
109: #include "job.h"
1.1 cgd 110: #include "pathnames.h"
1.58 sommerfe 111: #include "trace.h"
1.1 cgd 112:
1.337 rillig 113: /* "@(#)main.c 8.3 (Berkeley) 3/19/94" */
1.558 ! rillig 114: MAKE_RCSID("$NetBSD: main.c,v 1.557 2021/12/27 23:11:55 rillig Exp $");
1.337 rillig 115: #if defined(MAKE_NATIVE) && !defined(lint)
1.369 rillig 116: __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
117: "The Regents of the University of California. "
118: "All rights reserved.");
1.337 rillig 119: #endif
120:
1.391 rillig 121: CmdOpts opts;
1.453 rillig 122: time_t now; /* Time at start of make */
1.459 rillig 123: GNode *defaultNode; /* .DEFAULT node */
1.534 rillig 124: bool allPrecious; /* .PRECIOUS given on line by itself */
125: bool deleteOnError; /* .DELETE_ON_ERROR: set */
1.1 cgd 126:
1.453 rillig 127: static int maxJobTokens; /* -j argument */
1.534 rillig 128: bool enterFlagObj; /* -w and objdir != srcdir */
1.391 rillig 129:
1.453 rillig 130: static int jp_0 = -1, jp_1 = -1; /* ends of parent job pipe */
1.534 rillig 131: bool doing_depend; /* Set while reading .depend */
132: static bool jobsRunning; /* true if the jobs might be running */
1.453 rillig 133: static const char *tracefile;
1.553 rillig 134: static bool ReadMakefile(const char *);
1.469 rillig 135: static void purge_relative_cached_realpaths(void);
1.453 rillig 136:
1.547 rillig 137: static bool ignorePWD; /* if we use -C, PWD is meaningless */
1.453 rillig 138: static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */
139: char curdir[MAXPATHLEN + 1]; /* Startup directory */
1.497 rillig 140: const char *progname;
1.176 sjg 141: char *makeDependfile;
1.183 sjg 142: pid_t myPid;
1.220 christos 143: int makelevel;
1.1 cgd 144:
1.534 rillig 145: bool forceJobs = false;
1.481 rillig 146: static int main_errors = 0;
1.469 rillig 147: static HashTable cached_realpaths;
1.58 sommerfe 148:
1.220 christos 149: /*
150: * For compatibility with the POSIX version of MAKEFLAGS that includes
1.439 rillig 151: * all the options without '-', convert 'flags' to '-f -l -a -g -s'.
1.220 christos 152: */
153: static char *
154: explode(const char *flags)
155: {
1.551 rillig 156: char *exploded, *ep;
157: const char *p;
1.453 rillig 158:
159: if (flags == NULL)
160: return NULL;
161:
1.551 rillig 162: for (p = flags; *p != '\0'; p++)
163: if (!ch_isalpha(*p))
164: return bmake_strdup(flags);
165:
166: exploded = bmake_malloc((size_t)(p - flags) * 3 + 1);
167: for (p = flags, ep = exploded; *p != '\0'; p++) {
168: *ep++ = '-';
169: *ep++ = *p;
170: *ep++ = ' ';
1.453 rillig 171: }
1.551 rillig 172: *ep = '\0';
173: return exploded;
1.220 christos 174: }
1.279 rillig 175:
1.450 rillig 176: MAKE_ATTR_DEAD static void
177: usage(void)
178: {
1.466 rillig 179: size_t prognameLen = strcspn(progname, "[");
1.450 rillig 180:
181: (void)fprintf(stderr,
1.468 rillig 182: "usage: %.*s [-BeikNnqrSstWwX]\n"
1.450 rillig 183: " [-C directory] [-D variable] [-d flags] [-f makefile]\n"
184: " [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n"
185: " [-V variable] [-v variable] [variable=value] [target ...]\n",
1.466 rillig 186: (int)prognameLen, progname);
1.450 rillig 187: exit(2);
188: }
189:
1.133 dsl 190: static void
1.522 rillig 191: MainParseArgDebugFile(const char *arg)
1.344 rillig 192: {
1.453 rillig 193: const char *mode;
194: size_t len;
195: char *fname;
196:
197: if (opts.debug_file != stdout && opts.debug_file != stderr)
198: fclose(opts.debug_file);
199:
1.522 rillig 200: if (*arg == '+') {
201: arg++;
1.453 rillig 202: mode = "a";
203: } else
204: mode = "w";
1.344 rillig 205:
1.522 rillig 206: if (strcmp(arg, "stdout") == 0) {
1.453 rillig 207: opts.debug_file = stdout;
208: return;
209: }
1.522 rillig 210: if (strcmp(arg, "stderr") == 0) {
1.453 rillig 211: opts.debug_file = stderr;
212: return;
213: }
1.344 rillig 214:
1.522 rillig 215: len = strlen(arg);
1.453 rillig 216: fname = bmake_malloc(len + 20);
1.522 rillig 217: memcpy(fname, arg, len + 1);
1.453 rillig 218:
1.555 rillig 219: /* Replace the trailing '%d' after '.%d' with the pid. */
220: if (len >= 3 && memcmp(fname + len - 3, ".%d", 3) == 0)
1.453 rillig 221: snprintf(fname + len - 2, 20, "%d", getpid());
222:
223: opts.debug_file = fopen(fname, mode);
224: if (opts.debug_file == NULL) {
1.554 rillig 225: fprintf(stderr, "Cannot open debug file \"%s\"\n",
1.453 rillig 226: fname);
1.554 rillig 227: exit(2);
1.453 rillig 228: }
229: free(fname);
1.344 rillig 230: }
231:
232: static void
1.522 rillig 233: MainParseArgDebug(const char *argvalue)
1.133 dsl 234: {
235: const char *modules;
1.470 rillig 236: DebugFlags debug = opts.debug;
1.133 dsl 237:
1.523 rillig 238: for (modules = argvalue; *modules != '\0'; modules++) {
1.133 dsl 239: switch (*modules) {
1.369 rillig 240: case '0': /* undocumented, only intended for tests */
1.543 rillig 241: memset(&debug, 0, sizeof(debug));
1.369 rillig 242: break;
1.133 dsl 243: case 'A':
1.543 rillig 244: memset(&debug, ~0, sizeof(debug));
1.133 dsl 245: break;
246: case 'a':
1.543 rillig 247: debug.DEBUG_ARCH = true;
1.133 dsl 248: break;
1.155 christos 249: case 'C':
1.543 rillig 250: debug.DEBUG_CWD = true;
1.155 christos 251: break;
1.133 dsl 252: case 'c':
1.543 rillig 253: debug.DEBUG_COND = true;
1.133 dsl 254: break;
255: case 'd':
1.543 rillig 256: debug.DEBUG_DIR = true;
1.133 dsl 257: break;
258: case 'e':
1.543 rillig 259: debug.DEBUG_ERROR = true;
1.133 dsl 260: break;
261: case 'f':
1.543 rillig 262: debug.DEBUG_FOR = true;
1.133 dsl 263: break;
264: case 'g':
265: if (modules[1] == '1') {
1.543 rillig 266: debug.DEBUG_GRAPH1 = true;
1.475 rillig 267: modules++;
1.444 rillig 268: } else if (modules[1] == '2') {
1.543 rillig 269: debug.DEBUG_GRAPH2 = true;
1.475 rillig 270: modules++;
1.444 rillig 271: } else if (modules[1] == '3') {
1.543 rillig 272: debug.DEBUG_GRAPH3 = true;
1.475 rillig 273: modules++;
1.133 dsl 274: }
275: break;
1.280 sjg 276: case 'h':
1.543 rillig 277: debug.DEBUG_HASH = true;
1.280 sjg 278: break;
1.133 dsl 279: case 'j':
1.543 rillig 280: debug.DEBUG_JOB = true;
1.133 dsl 281: break;
1.285 sjg 282: case 'L':
1.534 rillig 283: opts.strict = true;
1.285 sjg 284: break;
1.146 sjg 285: case 'l':
1.543 rillig 286: debug.DEBUG_LOUD = true;
1.146 sjg 287: break;
1.190 sjg 288: case 'M':
1.543 rillig 289: debug.DEBUG_META = true;
1.190 sjg 290: break;
1.133 dsl 291: case 'm':
1.543 rillig 292: debug.DEBUG_MAKE = true;
1.133 dsl 293: break;
294: case 'n':
1.543 rillig 295: debug.DEBUG_SCRIPT = true;
1.133 dsl 296: break;
297: case 'p':
1.543 rillig 298: debug.DEBUG_PARSE = true;
1.133 dsl 299: break;
300: case 's':
1.543 rillig 301: debug.DEBUG_SUFF = true;
1.133 dsl 302: break;
303: case 't':
1.543 rillig 304: debug.DEBUG_TARG = true;
1.133 dsl 305: break;
1.201 sjg 306: case 'V':
1.534 rillig 307: opts.debugVflag = true;
1.201 sjg 308: break;
1.133 dsl 309: case 'v':
1.543 rillig 310: debug.DEBUG_VAR = true;
1.133 dsl 311: break;
312: case 'x':
1.543 rillig 313: debug.DEBUG_SHELL = true;
1.133 dsl 314: break;
315: case 'F':
1.522 rillig 316: MainParseArgDebugFile(modules + 1);
1.153 apb 317: goto debug_setbuf;
1.133 dsl 318: default:
319: (void)fprintf(stderr,
320: "%s: illegal argument to d option -- %c\n",
321: progname, *modules);
322: usage();
323: }
324: }
1.471 rillig 325:
326: debug_setbuf:
1.470 rillig 327: opts.debug = debug;
1.453 rillig 328:
1.153 apb 329: /*
330: * Make the debug_file unbuffered, and make
331: * stdout line buffered (unless debugfile == stdout).
332: */
1.391 rillig 333: setvbuf(opts.debug_file, NULL, _IONBF, 0);
334: if (opts.debug_file != stdout) {
1.153 apb 335: setvbuf(stdout, NULL, _IOLBF, 0);
336: }
1.133 dsl 337: }
338:
1.521 rillig 339: /* Is path relative, or does it contain any relative component "." or ".."? */
1.534 rillig 340: static bool
1.522 rillig 341: IsRelativePath(const char *path)
1.264 sjg 342: {
1.540 rillig 343: const char *p;
1.264 sjg 344:
345: if (path[0] != '/')
1.534 rillig 346: return true;
1.540 rillig 347: p = path;
348: while ((p = strstr(p, "/.")) != NULL) {
349: p += 2;
350: if (*p == '.')
351: p++;
352: if (*p == '/' || *p == '\0')
1.534 rillig 353: return true;
1.286 rillig 354: }
1.534 rillig 355: return false;
1.264 sjg 356: }
357:
1.355 rillig 358: static void
359: MainParseArgChdir(const char *argvalue)
360: {
361: struct stat sa, sb;
362:
363: if (chdir(argvalue) == -1) {
364: (void)fprintf(stderr, "%s: chdir %s: %s\n",
365: progname, argvalue, strerror(errno));
1.505 rillig 366: exit(2); /* Not 1 so -q can distinguish error */
1.355 rillig 367: }
368: if (getcwd(curdir, MAXPATHLEN) == NULL) {
369: (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
370: exit(2);
371: }
1.522 rillig 372: if (!IsRelativePath(argvalue) &&
1.355 rillig 373: stat(argvalue, &sa) != -1 &&
374: stat(curdir, &sb) != -1 &&
375: sa.st_ino == sb.st_ino &&
376: sa.st_dev == sb.st_dev)
377: strncpy(curdir, argvalue, MAXPATHLEN);
1.534 rillig 378: ignorePWD = true;
1.355 rillig 379: }
380:
1.356 rillig 381: static void
382: MainParseArgJobsInternal(const char *argvalue)
383: {
1.440 rillig 384: char end;
385: if (sscanf(argvalue, "%d,%d%c", &jp_0, &jp_1, &end) != 2) {
1.356 rillig 386: (void)fprintf(stderr,
1.453 rillig 387: "%s: internal error -- J option malformed (%s)\n",
388: progname, argvalue);
1.356 rillig 389: usage();
390: }
391: if ((fcntl(jp_0, F_GETFD, 0) < 0) ||
392: (fcntl(jp_1, F_GETFD, 0) < 0)) {
393: #if 0
394: (void)fprintf(stderr,
395: "%s: ###### warning -- J descriptors were closed!\n",
396: progname);
397: exit(2);
398: #endif
399: jp_0 = -1;
400: jp_1 = -1;
1.534 rillig 401: opts.compatMake = true;
1.356 rillig 402: } else {
1.529 rillig 403: Global_Append(MAKEFLAGS, "-J");
404: Global_Append(MAKEFLAGS, argvalue);
1.356 rillig 405: }
406: }
407:
408: static void
409: MainParseArgJobs(const char *argvalue)
410: {
411: char *p;
412:
1.534 rillig 413: forceJobs = true;
1.391 rillig 414: opts.maxJobs = (int)strtol(argvalue, &p, 0);
415: if (*p != '\0' || opts.maxJobs < 1) {
1.356 rillig 416: (void)fprintf(stderr,
417: "%s: illegal argument to -j -- must be positive integer!\n",
418: progname);
1.505 rillig 419: exit(2); /* Not 1 so -q can distinguish error */
1.356 rillig 420: }
1.529 rillig 421: Global_Append(MAKEFLAGS, "-j");
422: Global_Append(MAKEFLAGS, argvalue);
1.528 rillig 423: Global_Set(".MAKE.JOBS", argvalue);
1.391 rillig 424: maxJobTokens = opts.maxJobs;
1.356 rillig 425: }
426:
1.357 rillig 427: static void
428: MainParseArgSysInc(const char *argvalue)
429: {
430: /* look for magic parent directory search string */
431: if (strncmp(".../", argvalue, 4) == 0) {
1.371 rillig 432: char *found_path = Dir_FindHereOrAbove(curdir, argvalue + 4);
433: if (found_path == NULL)
1.357 rillig 434: return;
1.516 rillig 435: (void)SearchPath_Add(sysIncPath, found_path);
1.371 rillig 436: free(found_path);
1.357 rillig 437: } else {
1.516 rillig 438: (void)SearchPath_Add(sysIncPath, argvalue);
1.357 rillig 439: }
1.529 rillig 440: Global_Append(MAKEFLAGS, "-m");
441: Global_Append(MAKEFLAGS, argvalue);
1.357 rillig 442: }
443:
1.534 rillig 444: static bool
1.360 rillig 445: MainParseArg(char c, const char *argvalue)
1.354 rillig 446: {
447: switch (c) {
448: case '\0':
449: break;
450: case 'B':
1.534 rillig 451: opts.compatMake = true;
1.529 rillig 452: Global_Append(MAKEFLAGS, "-B");
1.528 rillig 453: Global_Set(MAKE_MODE, "compat");
1.354 rillig 454: break;
455: case 'C':
1.355 rillig 456: MainParseArgChdir(argvalue);
1.354 rillig 457: break;
458: case 'D':
1.546 rillig 459: if (argvalue[0] == '\0')
460: return false;
1.527 rillig 461: Global_SetExpand(argvalue, "1");
1.529 rillig 462: Global_Append(MAKEFLAGS, "-D");
463: Global_Append(MAKEFLAGS, argvalue);
1.354 rillig 464: break;
465: case 'I':
466: Parse_AddIncludeDir(argvalue);
1.529 rillig 467: Global_Append(MAKEFLAGS, "-I");
468: Global_Append(MAKEFLAGS, argvalue);
1.354 rillig 469: break;
470: case 'J':
1.356 rillig 471: MainParseArgJobsInternal(argvalue);
1.354 rillig 472: break;
473: case 'N':
1.534 rillig 474: opts.noExecute = true;
475: opts.noRecursiveExecute = true;
1.529 rillig 476: Global_Append(MAKEFLAGS, "-N");
1.354 rillig 477: break;
478: case 'S':
1.534 rillig 479: opts.keepgoing = false;
1.529 rillig 480: Global_Append(MAKEFLAGS, "-S");
1.354 rillig 481: break;
482: case 'T':
483: tracefile = bmake_strdup(argvalue);
1.529 rillig 484: Global_Append(MAKEFLAGS, "-T");
485: Global_Append(MAKEFLAGS, argvalue);
1.354 rillig 486: break;
487: case 'V':
488: case 'v':
1.437 rillig 489: opts.printVars = c == 'v' ? PVM_EXPANDED : PVM_UNEXPANDED;
1.485 rillig 490: Lst_Append(&opts.variables, bmake_strdup(argvalue));
1.391 rillig 491: /* XXX: Why always -V? */
1.529 rillig 492: Global_Append(MAKEFLAGS, "-V");
493: Global_Append(MAKEFLAGS, argvalue);
1.354 rillig 494: break;
495: case 'W':
1.534 rillig 496: opts.parseWarnFatal = true;
1.550 rillig 497: /* XXX: why no Global_Append? */
1.354 rillig 498: break;
499: case 'X':
1.534 rillig 500: opts.varNoExportEnv = true;
1.529 rillig 501: Global_Append(MAKEFLAGS, "-X");
1.354 rillig 502: break;
503: case 'd':
504: /* If '-d-opts' don't pass to children */
505: if (argvalue[0] == '-')
506: argvalue++;
507: else {
1.529 rillig 508: Global_Append(MAKEFLAGS, "-d");
509: Global_Append(MAKEFLAGS, argvalue);
1.354 rillig 510: }
1.522 rillig 511: MainParseArgDebug(argvalue);
1.354 rillig 512: break;
513: case 'e':
1.534 rillig 514: opts.checkEnvFirst = true;
1.529 rillig 515: Global_Append(MAKEFLAGS, "-e");
1.354 rillig 516: break;
517: case 'f':
1.484 rillig 518: Lst_Append(&opts.makefiles, bmake_strdup(argvalue));
1.354 rillig 519: break;
520: case 'i':
1.534 rillig 521: opts.ignoreErrors = true;
1.529 rillig 522: Global_Append(MAKEFLAGS, "-i");
1.354 rillig 523: break;
524: case 'j':
1.356 rillig 525: MainParseArgJobs(argvalue);
1.354 rillig 526: break;
527: case 'k':
1.534 rillig 528: opts.keepgoing = true;
1.529 rillig 529: Global_Append(MAKEFLAGS, "-k");
1.354 rillig 530: break;
531: case 'm':
1.357 rillig 532: MainParseArgSysInc(argvalue);
1.441 rillig 533: /* XXX: why no Var_Append? */
1.354 rillig 534: break;
535: case 'n':
1.534 rillig 536: opts.noExecute = true;
1.529 rillig 537: Global_Append(MAKEFLAGS, "-n");
1.354 rillig 538: break;
539: case 'q':
1.549 rillig 540: opts.query = true;
1.354 rillig 541: /* Kind of nonsensical, wot? */
1.529 rillig 542: Global_Append(MAKEFLAGS, "-q");
1.354 rillig 543: break;
544: case 'r':
1.534 rillig 545: opts.noBuiltins = true;
1.529 rillig 546: Global_Append(MAKEFLAGS, "-r");
1.354 rillig 547: break;
548: case 's':
1.549 rillig 549: opts.silent = true;
1.529 rillig 550: Global_Append(MAKEFLAGS, "-s");
1.354 rillig 551: break;
552: case 't':
1.549 rillig 553: opts.touch = true;
1.529 rillig 554: Global_Append(MAKEFLAGS, "-t");
1.354 rillig 555: break;
556: case 'w':
1.534 rillig 557: opts.enterFlag = true;
1.529 rillig 558: Global_Append(MAKEFLAGS, "-w");
1.354 rillig 559: break;
560: default:
561: case '?':
562: usage();
563: }
1.534 rillig 564: return true;
1.354 rillig 565: }
566:
1.507 rillig 567: /*
568: * Parse the given arguments. Called from main() and from
1.345 rillig 569: * Main_ParseArgLine() when the .MAKEFLAGS target is used.
1.1 cgd 570: *
1.345 rillig 571: * The arguments must be treated as read-only and will be freed after the
572: * call.
1.1 cgd 573: *
1.507 rillig 574: * XXX: Deal with command line overriding .MAKEFLAGS in makefile
575: */
1.1 cgd 576: static void
1.149 christos 577: MainParseArgs(int argc, char **argv)
1.1 cgd 578: {
1.360 rillig 579: char c;
1.98 ross 580: int arginc;
1.133 dsl 581: char *argvalue;
1.98 ross 582: char *optscan;
1.534 rillig 583: bool inOption, dashDash = false;
1.1 cgd 584:
1.359 rillig 585: const char *optspecs = "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrstv:w";
1.98 ross 586: /* Can't actually use getopt(3) because rescanning is not portable */
587:
1.279 rillig 588: rearg:
1.534 rillig 589: inOption = false;
1.108 lukem 590: optscan = NULL;
1.358 rillig 591: while (argc > 1) {
1.359 rillig 592: const char *optspec;
1.358 rillig 593: if (!inOption)
1.98 ross 594: optscan = argv[1];
595: c = *optscan++;
596: arginc = 0;
1.358 rillig 597: if (inOption) {
598: if (c == '\0') {
1.475 rillig 599: argv++;
600: argc--;
1.534 rillig 601: inOption = false;
1.98 ross 602: continue;
603: }
604: } else {
1.101 ross 605: if (c != '-' || dashDash)
1.98 ross 606: break;
1.534 rillig 607: inOption = true;
1.98 ross 608: c = *optscan++;
609: }
610: /* '-' found at some earlier point */
1.359 rillig 611: optspec = strchr(optspecs, c);
612: if (c != '\0' && optspec != NULL && optspec[1] == ':') {
1.547 rillig 613: /*
614: * -<something> found, and <something> should have an
615: * argument
616: */
1.534 rillig 617: inOption = false;
1.98 ross 618: arginc = 1;
619: argvalue = optscan;
1.358 rillig 620: if (*argvalue == '\0') {
1.122 christos 621: if (argc < 3)
622: goto noarg;
1.98 ross 623: argvalue = argv[2];
624: arginc = 2;
625: }
1.108 lukem 626: } else {
1.279 rillig 627: argvalue = NULL;
1.98 ross 628: }
1.354 rillig 629: switch (c) {
1.98 ross 630: case '\0':
1.358 rillig 631: arginc = 1;
1.534 rillig 632: inOption = false;
1.358 rillig 633: break;
1.101 ross 634: case '-':
1.534 rillig 635: dashDash = true;
1.358 rillig 636: break;
1.1 cgd 637: default:
1.358 rillig 638: if (!MainParseArg(c, argvalue))
639: goto noarg;
1.1 cgd 640: }
1.98 ross 641: argv += arginc;
642: argc -= arginc;
1.1 cgd 643: }
644:
645: /*
646: * See if the rest of the arguments are variable assignments and
647: * perform them if so. Else take them to be targets and stuff them
648: * on the end of the "create" list.
649: */
1.523 rillig 650: for (; argc > 1; argv++, argc--) {
1.369 rillig 651: VarAssign var;
652: if (Parse_IsVar(argv[1], &var)) {
1.536 rillig 653: Parse_Var(&var, SCOPE_CMDLINE);
1.67 sjg 654: } else {
1.460 rillig 655: if (argv[1][0] == '\0')
1.1 cgd 656: Punt("illegal (null) argument.");
1.460 rillig 657: if (argv[1][0] == '-' && !dashDash)
1.1 cgd 658: goto rearg;
1.486 rillig 659: Lst_Append(&opts.create, bmake_strdup(argv[1]));
1.1 cgd 660: }
1.369 rillig 661: }
1.122 christos 662:
663: return;
664: noarg:
665: (void)fprintf(stderr, "%s: option requires an argument -- %c\n",
666: progname, c);
667: usage();
1.1 cgd 668: }
669:
1.507 rillig 670: /*
671: * Break a line of arguments into words and parse them.
1.85 wiz 672: *
1.361 rillig 673: * Used when a .MFLAGS or .MAKEFLAGS target is encountered during parsing and
1.507 rillig 674: * by main() when reading the MAKEFLAGS environment variable.
675: */
1.1 cgd 676: void
1.161 dsl 677: Main_ParseArgLine(const char *line)
1.1 cgd 678: {
1.331 rillig 679: Words words;
1.296 rillig 680: char *buf;
1.1 cgd 681:
682: if (line == NULL)
683: return;
1.496 rillig 684: /* XXX: don't use line as an iterator variable */
1.523 rillig 685: for (; *line == ' '; line++)
1.13 cgd 686: continue;
1.442 rillig 687: if (line[0] == '\0')
1.1 cgd 688: return;
689:
1.442 rillig 690: {
1.532 rillig 691: FStr argv0 = Var_Value(SCOPE_GLOBAL, ".MAKE");
1.499 rillig 692: buf = str_concat3(argv0.str, " ", line);
693: FStr_Done(&argv0);
1.442 rillig 694: }
1.40 christos 695:
1.534 rillig 696: words = Str_Words(buf, true);
1.331 rillig 697: if (words.words == NULL) {
1.159 christos 698: Error("Unterminated quoted string [%s]", buf);
699: free(buf);
700: return;
701: }
1.45 itohy 702: free(buf);
1.331 rillig 703: MainParseArgs((int)words.len, words.words);
1.40 christos 704:
1.331 rillig 705: Words_Free(words);
1.1 cgd 706: }
707:
1.534 rillig 708: bool
709: Main_SetObjdir(bool writable, const char *fmt, ...)
1.31 christos 710: {
711: struct stat sb;
1.260 christos 712: char *path;
713: char buf[MAXPATHLEN + 1];
1.265 sjg 714: char buf2[MAXPATHLEN + 1];
1.534 rillig 715: bool rc = false;
1.252 christos 716: va_list ap;
717:
718: va_start(ap, fmt);
1.260 christos 719: vsnprintf(path = buf, MAXPATHLEN, fmt, ap);
1.252 christos 720: va_end(ap);
1.31 christos 721:
1.74 tv 722: if (path[0] != '/') {
1.263 sjg 723: snprintf(buf2, MAXPATHLEN, "%s/%s", curdir, path);
724: path = buf2;
1.74 tv 725: }
726:
727: /* look for the directory and try to chdir there */
1.31 christos 728: if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
1.456 sjg 729: if ((writable && access(path, W_OK) != 0) ||
1.433 rillig 730: (chdir(path) != 0)) {
1.463 rillig 731: (void)fprintf(stderr, "%s warning: %s: %s.\n",
732: progname, path, strerror(errno));
1.74 tv 733: } else {
1.295 rillig 734: snprintf(objdir, sizeof objdir, "%s", path);
1.528 rillig 735: Global_Set(".OBJDIR", objdir);
1.74 tv 736: setenv("PWD", objdir, 1);
1.79 tv 737: Dir_InitDot();
1.469 rillig 738: purge_relative_cached_realpaths();
1.534 rillig 739: rc = true;
1.391 rillig 740: if (opts.enterFlag && strcmp(objdir, curdir) != 0)
1.534 rillig 741: enterFlagObj = true;
1.31 christos 742: }
743: }
744:
1.74 tv 745: return rc;
1.31 christos 746: }
747:
1.534 rillig 748: static bool
749: SetVarObjdir(bool writable, const char *var, const char *suffix)
1.252 christos 750: {
1.532 rillig 751: FStr path = Var_Value(SCOPE_CMDLINE, var);
1.296 rillig 752:
1.499 rillig 753: if (path.str == NULL || path.str[0] == '\0') {
754: FStr_Done(&path);
1.534 rillig 755: return false;
1.288 rillig 756: }
1.252 christos 757:
1.260 christos 758: /* expand variable substitutions */
1.499 rillig 759: if (strchr(path.str, '$') != 0) {
760: char *expanded;
1.530 rillig 761: (void)Var_Subst(path.str, SCOPE_GLOBAL, VARE_WANTRES, &expanded);
1.341 rillig 762: /* TODO: handle errors */
1.556 rillig 763: FStr_Done(&path);
764: path = FStr_InitOwn(expanded);
1.341 rillig 765: }
1.260 christos 766:
1.556 rillig 767: (void)Main_SetObjdir(writable, "%s%s", path.str, suffix);
1.260 christos 768:
1.499 rillig 769: FStr_Done(&path);
1.534 rillig 770: return true;
1.252 christos 771: }
772:
1.507 rillig 773: /*
774: * Splits str into words, adding them to the list.
775: * The string must be kept alive as long as the list.
776: */
1.197 sjg 777: int
1.462 rillig 778: str2Lst_Append(StringList *lp, char *str)
1.176 sjg 779: {
1.453 rillig 780: char *cp;
781: int n;
1.176 sjg 782:
1.462 rillig 783: const char *sep = " \t";
1.176 sjg 784:
1.512 rillig 785: for (n = 0, cp = strtok(str, sep); cp != NULL; cp = strtok(NULL, sep)) {
1.453 rillig 786: Lst_Append(lp, cp);
787: n++;
788: }
789: return n;
1.176 sjg 790: }
791:
1.167 christos 792: #ifdef SIGINFO
793: /*ARGSUSED*/
794: static void
1.200 joerg 795: siginfo(int signo MAKE_ATTR_UNUSED)
1.167 christos 796: {
797: char dir[MAXPATHLEN];
798: char str[2 * MAXPATHLEN];
799: int len;
1.426 rillig 800: if (getcwd(dir, sizeof dir) == NULL)
1.167 christos 801: return;
1.426 rillig 802: len = snprintf(str, sizeof str, "%s: Working in: %s\n", progname, dir);
1.167 christos 803: if (len > 0)
804: (void)write(STDERR_FILENO, str, (size_t)len);
805: }
806: #endif
807:
1.500 rillig 808: /* Allow makefiles some control over the mode we run in. */
809: static void
810: MakeMode(void)
1.176 sjg 811: {
1.524 rillig 812: char *mode;
1.176 sjg 813:
1.530 rillig 814: (void)Var_Subst("${" MAKE_MODE ":tl}", SCOPE_GLOBAL, VARE_WANTRES, &mode);
1.524 rillig 815: /* TODO: handle errors */
1.176 sjg 816:
1.524 rillig 817: if (mode[0] != '\0') {
818: if (strstr(mode, "compat") != NULL) {
1.534 rillig 819: opts.compatMake = true;
820: forceJobs = false;
1.453 rillig 821: }
1.190 sjg 822: #if USE_META
1.524 rillig 823: if (strstr(mode, "meta") != NULL)
824: meta_mode_init(mode);
1.190 sjg 825: #endif
1.453 rillig 826: }
1.238 christos 827:
1.524 rillig 828: free(mode);
1.176 sjg 829: }
830:
1.266 christos 831: static void
1.534 rillig 832: PrintVar(const char *varname, bool expandVars)
1.383 rillig 833: {
1.508 rillig 834: if (strchr(varname, '$') != NULL) {
1.384 rillig 835: char *evalue;
1.530 rillig 836: (void)Var_Subst(varname, SCOPE_GLOBAL, VARE_WANTRES, &evalue);
1.383 rillig 837: /* TODO: handle errors */
1.384 rillig 838: printf("%s\n", evalue);
1.545 rillig 839: free(evalue);
1.384 rillig 840:
1.383 rillig 841: } else if (expandVars) {
842: char *expr = str_concat3("${", varname, "}");
1.384 rillig 843: char *evalue;
1.530 rillig 844: (void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &evalue);
1.383 rillig 845: /* TODO: handle errors */
846: free(expr);
1.384 rillig 847: printf("%s\n", evalue);
1.545 rillig 848: free(evalue);
1.384 rillig 849:
1.383 rillig 850: } else {
1.532 rillig 851: FStr value = Var_Value(SCOPE_GLOBAL, varname);
1.499 rillig 852: printf("%s\n", value.str != NULL ? value.str : "");
853: FStr_Done(&value);
1.383 rillig 854: }
855: }
856:
1.432 rillig 857: /*
1.534 rillig 858: * Return a bool based on a variable.
1.432 rillig 859: *
860: * If the knob is not set, return the fallback.
861: * If set, anything that looks or smells like "No", "False", "Off", "0", etc.
1.534 rillig 862: * is false, otherwise true.
1.432 rillig 863: */
1.534 rillig 864: static bool
1.538 rillig 865: GetBooleanExpr(const char *expr, bool fallback)
1.432 rillig 866: {
1.453 rillig 867: char *value;
1.534 rillig 868: bool res;
1.453 rillig 869:
1.530 rillig 870: (void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &value);
1.453 rillig 871: /* TODO: handle errors */
872: res = ParseBoolean(value, fallback);
873: free(value);
874: return res;
1.432 rillig 875: }
876:
1.383 rillig 877: static void
1.266 christos 878: doPrintVars(void)
879: {
1.338 rillig 880: StringListNode *ln;
1.534 rillig 881: bool expandVars;
1.266 christos 882:
1.437 rillig 883: if (opts.printVars == PVM_EXPANDED)
1.534 rillig 884: expandVars = true;
1.394 rillig 885: else if (opts.debugVflag)
1.534 rillig 886: expandVars = false;
1.266 christos 887: else
1.538 rillig 888: expandVars = GetBooleanExpr("${.MAKE.EXPAND_VARIABLES}",
889: false);
1.266 christos 890:
1.485 rillig 891: for (ln = opts.variables.first; ln != NULL; ln = ln->next) {
1.383 rillig 892: const char *varname = ln->datum;
893: PrintVar(varname, expandVars);
1.266 christos 894: }
895: }
896:
1.534 rillig 897: static bool
1.266 christos 898: runTargets(void)
899: {
1.488 rillig 900: GNodeList targs = LST_INIT; /* target nodes to create */
1.547 rillig 901: bool outOfDate; /* false if all targets up to date */
1.266 christos 902:
903: /*
904: * Have now read the entire graph and need to make a list of
905: * targets to create. If none was given on the command line,
906: * we consult the parsing module to find the main target(s)
907: * to create.
908: */
1.486 rillig 909: if (Lst_IsEmpty(&opts.create))
1.488 rillig 910: Parse_MainName(&targs);
1.266 christos 911: else
1.488 rillig 912: Targ_FindList(&targs, &opts.create);
1.266 christos 913:
1.391 rillig 914: if (!opts.compatMake) {
1.266 christos 915: /*
916: * Initialize job module before traversing the graph
917: * now that any .BEGIN and .END targets have been read.
918: * This is done only if the -q flag wasn't given
919: * (to prevent the .BEGIN from being executed should
920: * it exist).
921: */
1.549 rillig 922: if (!opts.query) {
1.266 christos 923: Job_Init();
1.534 rillig 924: jobsRunning = true;
1.266 christos 925: }
926:
927: /* Traverse the graph, checking on all the targets */
1.488 rillig 928: outOfDate = Make_Run(&targs);
1.266 christos 929: } else {
930: /*
931: * Compat_Init will take care of creating all the
932: * targets as well as initializing the module.
933: */
1.488 rillig 934: Compat_Run(&targs);
1.534 rillig 935: outOfDate = false;
1.266 christos 936: }
1.525 rillig 937: Lst_Done(&targs); /* Don't free the targets themselves. */
1.266 christos 938: return outOfDate;
939: }
940:
1.343 rillig 941: /*
942: * Set up the .TARGETS variable to contain the list of targets to be
943: * created. If none specified, make the variable empty -- the parser
944: * will fill the thing in with the default or .MAIN target.
945: */
946: static void
947: InitVarTargets(void)
948: {
949: StringListNode *ln;
950:
1.486 rillig 951: if (Lst_IsEmpty(&opts.create)) {
1.528 rillig 952: Global_Set(".TARGETS", "");
1.343 rillig 953: return;
954: }
955:
1.486 rillig 956: for (ln = opts.create.first; ln != NULL; ln = ln->next) {
1.525 rillig 957: const char *name = ln->datum;
1.529 rillig 958: Global_Append(".TARGETS", name);
1.343 rillig 959: }
960: }
961:
1.404 rillig 962: static void
963: InitRandom(void)
964: {
965: struct timeval tv;
966:
967: gettimeofday(&tv, NULL);
968: srandom((unsigned int)(tv.tv_sec + tv.tv_usec));
969: }
970:
1.369 rillig 971: static const char *
1.525 rillig 972: InitVarMachine(const struct utsname *utsname MAKE_ATTR_UNUSED)
1.369 rillig 973: {
974: const char *machine = getenv("MACHINE");
975: if (machine != NULL)
976: return machine;
977:
1.458 rillig 978: #if defined(MAKE_NATIVE)
1.369 rillig 979: return utsname->machine;
1.458 rillig 980: #elif defined(MAKE_MACHINE)
1.369 rillig 981: return MAKE_MACHINE;
982: #else
983: return "unknown";
984: #endif
985: }
986:
987: static const char *
1.451 rillig 988: InitVarMachineArch(void)
1.369 rillig 989: {
990: const char *env = getenv("MACHINE_ARCH");
991: if (env != NULL)
992: return env;
993:
994: #ifdef MAKE_NATIVE
995: {
996: struct utsname utsname;
1.426 rillig 997: static char machine_arch_buf[sizeof utsname.machine];
1.369 rillig 998: const int mib[2] = { CTL_HW, HW_MACHINE_ARCH };
1.426 rillig 999: size_t len = sizeof machine_arch_buf;
1.369 rillig 1000:
1.510 rillig 1001: if (sysctl(mib, (unsigned int)__arraycount(mib),
1002: machine_arch_buf, &len, NULL, 0) < 0) {
1003: (void)fprintf(stderr, "%s: sysctl failed (%s).\n",
1004: progname, strerror(errno));
1005: exit(2);
1.369 rillig 1006: }
1007:
1008: return machine_arch_buf;
1009: }
1.457 rillig 1010: #elif defined(MACHINE_ARCH)
1011: return MACHINE_ARCH;
1012: #elif defined(MAKE_MACHINE_ARCH)
1.369 rillig 1013: return MAKE_MACHINE_ARCH;
1014: #else
1015: return "unknown";
1016: #endif
1017: }
1018:
1.381 rillig 1019: #ifndef NO_PWD_OVERRIDE
1020: /*
1021: * All this code is so that we know where we are when we start up
1022: * on a different machine with pmake.
1.382 rillig 1023: *
1.525 rillig 1024: * XXX: Make no longer has "local" and "remote" mode. Is this code still
1025: * necessary?
1026: *
1.381 rillig 1027: * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX
1028: * since the value of curdir can vary depending on how we got
1029: * here. Ie sitting at a shell prompt (shell that provides $PWD)
1030: * or via subdir.mk in which case its likely a shell which does
1031: * not provide it.
1.382 rillig 1032: *
1.381 rillig 1033: * So, to stop it breaking this case only, we ignore PWD if
1.382 rillig 1034: * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a variable expression.
1.381 rillig 1035: */
1036: static void
1.382 rillig 1037: HandlePWD(const struct stat *curdir_st)
1.381 rillig 1038: {
1.382 rillig 1039: char *pwd;
1.499 rillig 1040: FStr prefix, makeobjdir;
1.382 rillig 1041: struct stat pwd_st;
1.381 rillig 1042:
1043: if (ignorePWD || (pwd = getenv("PWD")) == NULL)
1044: return;
1045:
1.532 rillig 1046: prefix = Var_Value(SCOPE_CMDLINE, "MAKEOBJDIRPREFIX");
1.499 rillig 1047: if (prefix.str != NULL) {
1048: FStr_Done(&prefix);
1.382 rillig 1049: return;
1.381 rillig 1050: }
1.382 rillig 1051:
1.532 rillig 1052: makeobjdir = Var_Value(SCOPE_CMDLINE, "MAKEOBJDIR");
1.499 rillig 1053: if (makeobjdir.str != NULL && strchr(makeobjdir.str, '$') != NULL)
1.382 rillig 1054: goto ignore_pwd;
1055:
1056: if (stat(pwd, &pwd_st) == 0 &&
1057: curdir_st->st_ino == pwd_st.st_ino &&
1058: curdir_st->st_dev == pwd_st.st_dev)
1059: (void)strncpy(curdir, pwd, MAXPATHLEN);
1060:
1061: ignore_pwd:
1.499 rillig 1062: FStr_Done(&makeobjdir);
1.381 rillig 1063: }
1064: #endif
1065:
1.407 rillig 1066: /*
1.550 rillig 1067: * Find the .OBJDIR. If MAKEOBJDIRPREFIX, or failing that, MAKEOBJDIR is set
1068: * in the environment, try only that value and fall back to .CURDIR if it
1069: * does not exist.
1.407 rillig 1070: *
1071: * Otherwise, try _PATH_OBJDIR.MACHINE-MACHINE_ARCH, _PATH_OBJDIR.MACHINE,
1.550 rillig 1072: * and finally _PATH_OBJDIRPREFIX`pwd`, in that order. If none of these
1073: * paths exist, just use .CURDIR.
1.407 rillig 1074: */
1075: static void
1076: InitObjdir(const char *machine, const char *machine_arch)
1077: {
1.534 rillig 1078: bool writable;
1.456 sjg 1079:
1.491 rillig 1080: Dir_InitCur(curdir);
1.538 rillig 1081: writable = GetBooleanExpr("${MAKE_OBJDIR_CHECK_WRITABLE}", true);
1.534 rillig 1082: (void)Main_SetObjdir(false, "%s", curdir);
1.407 rillig 1083:
1.461 rillig 1084: if (!SetVarObjdir(writable, "MAKEOBJDIRPREFIX", curdir) &&
1085: !SetVarObjdir(writable, "MAKEOBJDIR", "") &&
1.456 sjg 1086: !Main_SetObjdir(writable, "%s.%s-%s", _PATH_OBJDIR, machine, machine_arch) &&
1087: !Main_SetObjdir(writable, "%s.%s", _PATH_OBJDIR, machine) &&
1088: !Main_SetObjdir(writable, "%s", _PATH_OBJDIR))
1089: (void)Main_SetObjdir(writable, "%s%s", _PATH_OBJDIRPREFIX, curdir);
1.407 rillig 1090: }
1091:
1.393 rillig 1092: /* get rid of resource limit on file descriptors */
1093: static void
1094: UnlimitFiles(void)
1095: {
1096: #if defined(MAKE_NATIVE) || (defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE))
1097: struct rlimit rl;
1098: if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
1099: rl.rlim_cur != rl.rlim_max) {
1100: rl.rlim_cur = rl.rlim_max;
1101: (void)setrlimit(RLIMIT_NOFILE, &rl);
1102: }
1103: #endif
1104: }
1105:
1.395 rillig 1106: static void
1107: CmdOpts_Init(void)
1108: {
1.534 rillig 1109: opts.compatMake = false;
1.543 rillig 1110: memset(&opts.debug, 0, sizeof(opts.debug));
1.525 rillig 1111: /* opts.debug_file has already been initialized earlier */
1.534 rillig 1112: opts.strict = false;
1113: opts.debugVflag = false;
1114: opts.checkEnvFirst = false;
1.484 rillig 1115: Lst_Init(&opts.makefiles);
1.534 rillig 1116: opts.ignoreErrors = false; /* Pay attention to non-zero returns */
1.493 rillig 1117: opts.maxJobs = 1;
1.534 rillig 1118: opts.keepgoing = false; /* Stop on error */
1119: opts.noRecursiveExecute = false; /* Execute all .MAKE targets */
1120: opts.noExecute = false; /* Execute all commands */
1.549 rillig 1121: opts.query = false;
1.534 rillig 1122: opts.noBuiltins = false; /* Read the built-in rules */
1.549 rillig 1123: opts.silent = false; /* Print commands as executed */
1124: opts.touch = false;
1.437 rillig 1125: opts.printVars = PVM_NONE;
1.485 rillig 1126: Lst_Init(&opts.variables);
1.534 rillig 1127: opts.parseWarnFatal = false;
1128: opts.enterFlag = false;
1129: opts.varNoExportEnv = false;
1.486 rillig 1130: Lst_Init(&opts.create);
1.395 rillig 1131: }
1132:
1.507 rillig 1133: /*
1134: * Initialize MAKE and .MAKE to the path of the executable, so that it can be
1.406 rillig 1135: * found by execvp(3) and the shells, even after a chdir.
1136: *
1137: * If it's a relative path and contains a '/', resolve it to an absolute path.
1.507 rillig 1138: * Otherwise keep it as is, assuming it will be found in the PATH.
1139: */
1.397 rillig 1140: static void
1.406 rillig 1141: InitVarMake(const char *argv0)
1.405 rillig 1142: {
1.406 rillig 1143: const char *make = argv0;
1.405 rillig 1144:
1.406 rillig 1145: if (argv0[0] != '/' && strchr(argv0, '/') != NULL) {
1146: char pathbuf[MAXPATHLEN];
1.502 rillig 1147: const char *abspath = cached_realpath(argv0, pathbuf);
1.406 rillig 1148: struct stat st;
1.502 rillig 1149: if (abspath != NULL && abspath[0] == '/' &&
1150: stat(make, &st) == 0)
1151: make = abspath;
1.405 rillig 1152: }
1.406 rillig 1153:
1.528 rillig 1154: Global_Set("MAKE", make);
1155: Global_Set(".MAKE", make);
1.405 rillig 1156: }
1157:
1.507 rillig 1158: /*
1159: * Add the directories from the colon-separated syspath to defSysIncPath.
1160: * After returning, the contents of syspath is unspecified.
1161: */
1.405 rillig 1162: static void
1.409 rillig 1163: InitDefSysIncPath(char *syspath)
1.397 rillig 1164: {
1165: static char defsyspath[] = _PATH_DEFSYSPATH;
1166: char *start, *cp;
1167:
1168: /*
1169: * If no user-supplied system path was given (through the -m option)
1170: * add the directories from the DEFSYSPATH (more than one may be given
1171: * as dir1:...:dirn) to the system include path.
1172: */
1173: if (syspath == NULL || syspath[0] == '\0')
1174: syspath = defsyspath;
1175: else
1176: syspath = bmake_strdup(syspath);
1177:
1178: for (start = syspath; *start != '\0'; start = cp) {
1179: for (cp = start; *cp != '\0' && *cp != ':'; cp++)
1180: continue;
1.433 rillig 1181: if (*cp == ':')
1.397 rillig 1182: *cp++ = '\0';
1.433 rillig 1183:
1.397 rillig 1184: /* look for magic parent directory search string */
1.464 rillig 1185: if (strncmp(start, ".../", 4) == 0) {
1.397 rillig 1186: char *dir = Dir_FindHereOrAbove(curdir, start + 4);
1187: if (dir != NULL) {
1.516 rillig 1188: (void)SearchPath_Add(defSysIncPath, dir);
1.397 rillig 1189: free(dir);
1190: }
1.464 rillig 1191: } else {
1.516 rillig 1192: (void)SearchPath_Add(defSysIncPath, start);
1.397 rillig 1193: }
1194: }
1195:
1196: if (syspath != defsyspath)
1197: free(syspath);
1198: }
1199:
1.398 rillig 1200: static void
1201: ReadBuiltinRules(void)
1202: {
1.445 rillig 1203: StringListNode *ln;
1.525 rillig 1204: StringList sysMkFiles = LST_INIT;
1.445 rillig 1205:
1.515 rillig 1206: SearchPath_Expand(
1.517 rillig 1207: Lst_IsEmpty(&sysIncPath->dirs) ? defSysIncPath : sysIncPath,
1.515 rillig 1208: _PATH_DEFSYSMK,
1.525 rillig 1209: &sysMkFiles);
1210: if (Lst_IsEmpty(&sysMkFiles))
1.398 rillig 1211: Fatal("%s: no system rules (%s).", progname, _PATH_DEFSYSMK);
1.445 rillig 1212:
1.525 rillig 1213: for (ln = sysMkFiles.first; ln != NULL; ln = ln->next)
1.553 rillig 1214: if (ReadMakefile(ln->datum))
1.445 rillig 1215: break;
1216:
1217: if (ln == NULL)
1218: Fatal("%s: cannot open %s.",
1.525 rillig 1219: progname, (const char *)sysMkFiles.first->datum);
1.445 rillig 1220:
1.557 rillig 1221: Lst_DoneCall(&sysMkFiles, free);
1.398 rillig 1222: }
1223:
1.408 rillig 1224: static void
1225: InitMaxJobs(void)
1226: {
1227: char *value;
1228: int n;
1229:
1230: if (forceJobs || opts.compatMake ||
1.532 rillig 1231: !Var_Exists(SCOPE_GLOBAL, ".MAKE.JOBS"))
1.408 rillig 1232: return;
1233:
1.530 rillig 1234: (void)Var_Subst("${.MAKE.JOBS}", SCOPE_GLOBAL, VARE_WANTRES, &value);
1.408 rillig 1235: /* TODO: handle errors */
1236: n = (int)strtol(value, NULL, 0);
1237: if (n < 1) {
1238: (void)fprintf(stderr,
1.453 rillig 1239: "%s: illegal value for .MAKE.JOBS "
1240: "-- must be positive integer!\n",
1241: progname);
1.505 rillig 1242: exit(2); /* Not 1 so -q can distinguish error */
1.408 rillig 1243: }
1244:
1245: if (n != opts.maxJobs) {
1.529 rillig 1246: Global_Append(MAKEFLAGS, "-j");
1247: Global_Append(MAKEFLAGS, value);
1.408 rillig 1248: }
1249:
1250: opts.maxJobs = n;
1251: maxJobTokens = opts.maxJobs;
1.534 rillig 1252: forceJobs = true;
1.408 rillig 1253: free(value);
1254: }
1255:
1.400 rillig 1256: /*
1257: * For compatibility, look at the directories in the VPATH variable
1258: * and add them to the search path, if the variable is defined. The
1259: * variable's value is in the same format as the PATH environment
1260: * variable, i.e. <directory>:<directory>:<directory>...
1261: */
1262: static void
1263: InitVpath(void)
1264: {
1265: char *vpath, savec, *path;
1.532 rillig 1266: if (!Var_Exists(SCOPE_CMDLINE, "VPATH"))
1.400 rillig 1267: return;
1268:
1.530 rillig 1269: (void)Var_Subst("${VPATH}", SCOPE_CMDLINE, VARE_WANTRES, &vpath);
1.400 rillig 1270: /* TODO: handle errors */
1271: path = vpath;
1272: do {
1273: char *cp;
1274: /* skip to end of directory */
1275: for (cp = path; *cp != ':' && *cp != '\0'; cp++)
1276: continue;
1277: /* Save terminator character so know when to stop */
1278: savec = *cp;
1279: *cp = '\0';
1280: /* Add directory to search path */
1.516 rillig 1281: (void)SearchPath_Add(&dirSearchPath, path);
1.400 rillig 1282: *cp = savec;
1283: path = cp + 1;
1284: } while (savec == ':');
1285: free(vpath);
1286: }
1287:
1.402 rillig 1288: static void
1.553 rillig 1289: ReadAllMakefiles(const StringList *makefiles)
1.403 rillig 1290: {
1.443 rillig 1291: StringListNode *ln;
1.403 rillig 1292:
1.443 rillig 1293: for (ln = makefiles->first; ln != NULL; ln = ln->next) {
1294: const char *fname = ln->datum;
1.553 rillig 1295: if (!ReadMakefile(fname))
1.443 rillig 1296: Fatal("%s: cannot open %s.", progname, fname);
1.403 rillig 1297: }
1298: }
1299:
1300: static void
1.443 rillig 1301: ReadFirstDefaultMakefile(void)
1302: {
1.446 rillig 1303: StringListNode *ln;
1.443 rillig 1304: char *prefs;
1.446 rillig 1305:
1.443 rillig 1306: (void)Var_Subst("${" MAKE_MAKEFILE_PREFERENCE "}",
1.530 rillig 1307: SCOPE_CMDLINE, VARE_WANTRES, &prefs);
1.443 rillig 1308: /* TODO: handle errors */
1309:
1.547 rillig 1310: /*
1311: * XXX: This should use a local list instead of opts.makefiles since
1312: * these makefiles do not come from the command line. They also have
1313: * different semantics in that only the first file that is found is
1314: * processed. See ReadAllMakefiles.
1315: */
1.484 rillig 1316: (void)str2Lst_Append(&opts.makefiles, prefs);
1.446 rillig 1317:
1.484 rillig 1318: for (ln = opts.makefiles.first; ln != NULL; ln = ln->next)
1.553 rillig 1319: if (ReadMakefile(ln->datum))
1.446 rillig 1320: break;
1321:
1.443 rillig 1322: free(prefs);
1323: }
1324:
1.507 rillig 1325: /*
1326: * Initialize variables such as MAKE, MACHINE, .MAKEFLAGS.
1.449 rillig 1327: * Initialize a few modules.
1.507 rillig 1328: * Parse the arguments from MAKEFLAGS and the command line.
1329: */
1.443 rillig 1330: static void
1.448 rillig 1331: main_Init(int argc, char **argv)
1.402 rillig 1332: {
1.381 rillig 1333: struct stat sa;
1.369 rillig 1334: const char *machine;
1335: const char *machine_arch;
1.55 sjg 1336: char *syspath = getenv("MAKESYSPATH");
1.119 tsutsui 1337: struct utsname utsname;
1.107 sjg 1338:
1.154 apb 1339: /* default to writing debug to stderr */
1.391 rillig 1340: opts.debug_file = stderr;
1.133 dsl 1341:
1.542 rillig 1342: Str_Intern_Init();
1.469 rillig 1343: HashTable_Init(&cached_realpaths);
1344:
1.167 christos 1345: #ifdef SIGINFO
1.188 sjg 1346: (void)bmake_signal(SIGINFO, siginfo);
1.167 christos 1347: #endif
1.404 rillig 1348:
1349: InitRandom();
1.277 rillig 1350:
1.498 rillig 1351: progname = str_basename(argv[0]);
1.393 rillig 1352:
1353: UnlimitFiles();
1.13 cgd 1354:
1.206 christos 1355: if (uname(&utsname) == -1) {
1.447 rillig 1356: (void)fprintf(stderr, "%s: uname failed (%s).\n", progname,
1.453 rillig 1357: strerror(errno));
1.447 rillig 1358: exit(2);
1.206 christos 1359: }
1360:
1.17 gwr 1361: /*
1362: * Get the name of this type of MACHINE from utsname
1363: * so we can share an executable for similar machines.
1364: * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
1365: *
1.33 christos 1366: * Note that both MACHINE and MACHINE_ARCH are decided at
1367: * run-time.
1.17 gwr 1368: */
1.451 rillig 1369: machine = InitVarMachine(&utsname);
1370: machine_arch = InitVarMachineArch();
1.33 christos 1371:
1.447 rillig 1372: myPid = getpid(); /* remember this for vFork() */
1.183 sjg 1373:
1.1 cgd 1374: /*
1.51 sjg 1375: * Just in case MAKEOBJDIR wants us to do something tricky.
1376: */
1.476 rillig 1377: Targ_Init();
1378: Var_Init();
1.528 rillig 1379: Global_Set(".MAKE.OS", utsname.sysname);
1380: Global_Set("MACHINE", machine);
1381: Global_Set("MACHINE_ARCH", machine_arch);
1.170 perry 1382: #ifdef MAKE_VERSION
1.528 rillig 1383: Global_Set("MAKE_VERSION", MAKE_VERSION);
1.170 perry 1384: #endif
1.547 rillig 1385: Global_Set(".newline", "\n"); /* handy for :@ loops */
1.176 sjg 1386: #ifndef MAKEFILE_PREFERENCE_LIST
1.550 rillig 1387: /* This is the traditional preference for makefiles. */
1.176 sjg 1388: # define MAKEFILE_PREFERENCE_LIST "makefile Makefile"
1389: #endif
1.528 rillig 1390: Global_Set(MAKE_MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST);
1391: Global_Set(MAKE_DEPENDFILE, ".depend");
1.51 sjg 1392:
1.395 rillig 1393: CmdOpts_Init();
1.534 rillig 1394: allPrecious = false; /* Remove targets when interrupted */
1395: deleteOnError = false; /* Historical default behavior */
1396: jobsRunning = false;
1.1 cgd 1397:
1.391 rillig 1398: maxJobTokens = opts.maxJobs;
1.534 rillig 1399: ignorePWD = false;
1.13 cgd 1400:
1.1 cgd 1401: /*
1402: * Initialize the parsing, directory and variable modules to prepare
1403: * for the reading of inclusion paths and variable settings on the
1404: * command line
1405: */
1.36 gwr 1406:
1407: /*
1.1 cgd 1408: * Initialize various variables.
1409: * MAKE also gets this name, for compatibility
1410: * .MAKEFLAGS gets set to the empty string just in case.
1411: * MFLAGS also gets initialized empty, for compatibility.
1412: */
1.79 tv 1413: Parse_Init();
1.406 rillig 1414: InitVarMake(argv[0]);
1.528 rillig 1415: Global_Set(MAKEFLAGS, "");
1416: Global_Set(MAKEOVERRIDES, "");
1417: Global_Set("MFLAGS", "");
1418: Global_Set(".ALLTARGETS", "");
1.532 rillig 1419: Var_Set(SCOPE_CMDLINE, MAKE_LEVEL ".ENV", MAKE_LEVEL_ENV);
1.1 cgd 1420:
1.447 rillig 1421: /* Set some other useful variables. */
1.142 sjg 1422: {
1.552 rillig 1423: char buf[64], *ep = getenv(MAKE_LEVEL_ENV);
1.142 sjg 1424:
1.447 rillig 1425: makelevel = ep != NULL && ep[0] != '\0' ? atoi(ep) : 0;
1426: if (makelevel < 0)
1427: makelevel = 0;
1.552 rillig 1428: snprintf(buf, sizeof buf, "%d", makelevel);
1429: Global_Set(MAKE_LEVEL, buf);
1430: snprintf(buf, sizeof buf, "%u", myPid);
1431: Global_Set(".MAKE.PID", buf);
1432: snprintf(buf, sizeof buf, "%u", getppid());
1433: Global_Set(".MAKE.PPID", buf);
1434: snprintf(buf, sizeof buf, "%u", getuid());
1435: Global_Set(".MAKE.UID", buf);
1436: snprintf(buf, sizeof buf, "%u", getgid());
1437: Global_Set(".MAKE.GID", buf);
1.142 sjg 1438: }
1.220 christos 1439: if (makelevel > 0) {
1440: char pn[1024];
1.426 rillig 1441: snprintf(pn, sizeof pn, "%s[%d]", progname, makelevel);
1.221 christos 1442: progname = bmake_strdup(pn);
1.220 christos 1443: }
1.142 sjg 1444:
1.210 sjg 1445: #ifdef USE_META
1446: meta_init();
1447: #endif
1.306 rillig 1448: Dir_Init();
1.255 sjg 1449:
1.1 cgd 1450: #ifdef POSIX
1.412 rillig 1451: {
1.447 rillig 1452: char *p1 = explode(getenv("MAKEFLAGS"));
1453: Main_ParseArgLine(p1);
1454: free(p1);
1.412 rillig 1455: }
1.1 cgd 1456: #else
1.550 rillig 1457: /*
1458: * First snag any flags out of the MAKE environment variable.
1459: * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
1460: * in a different format).
1461: */
1.1 cgd 1462: Main_ParseArgLine(getenv("MAKE"));
1463: #endif
1.31 christos 1464:
1.174 sjg 1465: if (getcwd(curdir, MAXPATHLEN) == NULL) {
1.194 dholland 1466: (void)fprintf(stderr, "%s: getcwd: %s.\n",
1.453 rillig 1467: progname, strerror(errno));
1.174 sjg 1468: exit(2);
1469: }
1470:
1.175 sjg 1471: MainParseArgs(argc, argv);
1472:
1.391 rillig 1473: if (opts.enterFlag)
1.220 christos 1474: printf("%s: Entering directory `%s'\n", progname, curdir);
1475:
1.174 sjg 1476: if (stat(curdir, &sa) == -1) {
1.447 rillig 1477: (void)fprintf(stderr, "%s: %s: %s.\n",
1.453 rillig 1478: progname, curdir, strerror(errno));
1.447 rillig 1479: exit(2);
1.174 sjg 1480: }
1481:
1.222 sjg 1482: #ifndef NO_PWD_OVERRIDE
1.381 rillig 1483: HandlePWD(&sa);
1.222 sjg 1484: #endif
1.528 rillig 1485: Global_Set(".CURDIR", curdir);
1.174 sjg 1486:
1.407 rillig 1487: InitObjdir(machine, machine_arch);
1.174 sjg 1488:
1.1 cgd 1489: Arch_Init();
1490: Suff_Init();
1.58 sommerfe 1491: Trace_Init(tracefile);
1.1 cgd 1492:
1.459 rillig 1493: defaultNode = NULL;
1.1 cgd 1494: (void)time(&now);
1495:
1.58 sommerfe 1496: Trace_Log(MAKESTART, NULL);
1.279 rillig 1497:
1.343 rillig 1498: InitVarTargets();
1.25 christos 1499:
1.409 rillig 1500: InitDefSysIncPath(syspath);
1.448 rillig 1501: }
1.25 christos 1502:
1.507 rillig 1503: /*
1504: * Read the system makefile followed by either makefile, Makefile or the
1505: * files given by the -f option. Exit on parse errors.
1506: */
1.448 rillig 1507: static void
1508: main_ReadFiles(void)
1509: {
1.452 rillig 1510:
1.398 rillig 1511: if (!opts.noBuiltins)
1512: ReadBuiltinRules();
1.452 rillig 1513:
1.484 rillig 1514: if (!Lst_IsEmpty(&opts.makefiles))
1515: ReadAllMakefiles(&opts.makefiles);
1.443 rillig 1516: else
1517: ReadFirstDefaultMakefile();
1.448 rillig 1518: }
1.436 rillig 1519:
1.449 rillig 1520: /* Compute the dependency graph. */
1.448 rillig 1521: static void
1522: main_PrepareMaking(void)
1523: {
1.138 dsl 1524: /* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
1.437 rillig 1525: if (!opts.noBuiltins || opts.printVars == PVM_NONE) {
1.503 sjg 1526: (void)Var_Subst("${.MAKE.DEPENDFILE}",
1.530 rillig 1527: SCOPE_CMDLINE, VARE_WANTRES, &makeDependfile);
1.447 rillig 1528: if (makeDependfile[0] != '\0') {
1529: /* TODO: handle errors */
1.534 rillig 1530: doing_depend = true;
1.447 rillig 1531: (void)ReadMakefile(makeDependfile);
1.534 rillig 1532: doing_depend = false;
1.447 rillig 1533: }
1.145 dsl 1534: }
1.1 cgd 1535:
1.233 sjg 1536: if (enterFlagObj)
1537: printf("%s: Entering directory `%s'\n", progname, objdir);
1.279 rillig 1538:
1.500 rillig 1539: MakeMode();
1.176 sjg 1540:
1.412 rillig 1541: {
1.532 rillig 1542: FStr makeflags = Var_Value(SCOPE_GLOBAL, MAKEFLAGS);
1.529 rillig 1543: Global_Append("MFLAGS", makeflags.str);
1.499 rillig 1544: FStr_Done(&makeflags);
1.412 rillig 1545: }
1.1 cgd 1546:
1.408 rillig 1547: InitMaxJobs();
1.243 matthias 1548:
1.447 rillig 1549: if (!opts.compatMake && !forceJobs)
1.534 rillig 1550: opts.compatMake = true;
1.243 matthias 1551:
1.391 rillig 1552: if (!opts.compatMake)
1.447 rillig 1553: Job_ServerStart(maxJobTokens, jp_0, jp_1);
1.352 rillig 1554: DEBUG5(JOB, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n",
1.453 rillig 1555: jp_0, jp_1, opts.maxJobs, maxJobTokens, opts.compatMake ? 1 : 0);
1.58 sommerfe 1556:
1.437 rillig 1557: if (opts.printVars == PVM_NONE)
1.534 rillig 1558: Main_ExportMAKEFLAGS(true); /* initial export */
1.279 rillig 1559:
1.400 rillig 1560: InitVpath();
1.1 cgd 1561:
1562: /*
1563: * Now that all search paths have been read for suffixes et al, it's
1564: * time to add the default search path to their lists...
1565: */
1.535 rillig 1566: Suff_ExtendPaths();
1.50 mycroft 1567:
1568: /*
1569: * Propagate attributes through :: dependency lists.
1570: */
1571: Targ_Propagate();
1.1 cgd 1572:
1573: /* print the initial graph, if the user requested it */
1574: if (DEBUG(GRAPH1))
1575: Targ_PrintGraph(1);
1.448 rillig 1576: }
1.1 cgd 1577:
1.507 rillig 1578: /*
1579: * Make the targets.
1.449 rillig 1580: * If the -v or -V options are given, print variables instead.
1.507 rillig 1581: * Return whether any of the targets is out-of-date.
1582: */
1.534 rillig 1583: static bool
1.448 rillig 1584: main_Run(void)
1585: {
1.437 rillig 1586: if (opts.printVars != PVM_NONE) {
1.465 rillig 1587: /* print the values of any variables requested by the user */
1.266 christos 1588: doPrintVars();
1.534 rillig 1589: return false;
1.138 dsl 1590: } else {
1.448 rillig 1591: return runTargets();
1.31 christos 1592: }
1.448 rillig 1593: }
1594:
1.449 rillig 1595: /* Clean up after making the targets. */
1.448 rillig 1596: static void
1597: main_CleanUp(void)
1598: {
1599: #ifdef CLEANUP
1.485 rillig 1600: Lst_DoneCall(&opts.variables, free);
1.557 rillig 1601: Lst_DoneCall(&opts.makefiles, free);
1.489 rillig 1602: Lst_DoneCall(&opts.create, free);
1.448 rillig 1603: #endif
1604:
1605: if (DEBUG(GRAPH2))
1606: Targ_PrintGraph(2);
1.31 christos 1607:
1.448 rillig 1608: Trace_Log(MAKEEND, NULL);
1609:
1610: if (enterFlagObj)
1611: printf("%s: Leaving directory `%s'\n", progname, objdir);
1612: if (opts.enterFlag)
1613: printf("%s: Leaving directory `%s'\n", progname, curdir);
1.14 jtc 1614:
1.448 rillig 1615: #ifdef USE_META
1616: meta_finish();
1617: #endif
1618: Suff_End();
1619: Targ_End();
1620: Arch_End();
1621: Var_End();
1622: Parse_End();
1623: Dir_End();
1624: Job_End();
1625: Trace_End();
1.544 rillig 1626: Str_Intern_End();
1.448 rillig 1627: }
1628:
1.449 rillig 1629: /* Determine the exit code. */
1.448 rillig 1630: static int
1.534 rillig 1631: main_Exit(bool outOfDate)
1.448 rillig 1632: {
1.541 rillig 1633: if (opts.strict && (main_errors > 0 || Parse_NumErrors() > 0))
1.447 rillig 1634: return 2; /* Not 1 so -q can distinguish error */
1.137 dsl 1635: return outOfDate ? 1 : 0;
1.1 cgd 1636: }
1637:
1.448 rillig 1638: int
1639: main(int argc, char **argv)
1640: {
1.534 rillig 1641: bool outOfDate;
1.448 rillig 1642:
1643: main_Init(argc, argv);
1644: main_ReadFiles();
1645: main_PrepareMaking();
1646: outOfDate = main_Run();
1647: main_CleanUp();
1648: return main_Exit(outOfDate);
1649: }
1650:
1.507 rillig 1651: /*
1652: * Open and parse the given makefile, with all its side effects.
1.553 rillig 1653: * Return false if the file could not be opened.
1.1 cgd 1654: */
1.553 rillig 1655: static bool
1.325 rillig 1656: ReadMakefile(const char *fname)
1.1 cgd 1657: {
1.140 dsl 1658: int fd;
1.304 rillig 1659: char *name, *path = NULL;
1.1 cgd 1660:
1.454 rillig 1661: if (strcmp(fname, "-") == 0) {
1.193 dholland 1662: Parse_File(NULL /*stdin*/, -1);
1.532 rillig 1663: Var_Set(SCOPE_INTERNAL, "MAKEFILE", "");
1.1 cgd 1664: } else {
1665: /* if we've chdir'd, rebuild the path name */
1.454 rillig 1666: if (strcmp(curdir, objdir) != 0 && *fname != '/') {
1.304 rillig 1667: path = str_concat3(curdir, "/", fname);
1.140 dsl 1668: fd = open(path, O_RDONLY);
1669: if (fd != -1) {
1.1 cgd 1670: fname = path;
1671: goto found;
1672: }
1.309 rillig 1673: free(path);
1.279 rillig 1674:
1.95 jmc 1675: /* If curdir failed, try objdir (ala .depend) */
1.304 rillig 1676: path = str_concat3(objdir, "/", fname);
1.140 dsl 1677: fd = open(path, O_RDONLY);
1678: if (fd != -1) {
1.95 jmc 1679: fname = path;
1680: goto found;
1681: }
1.140 dsl 1682: } else {
1683: fd = open(fname, O_RDONLY);
1684: if (fd != -1)
1685: goto found;
1686: }
1.1 cgd 1687: /* look in -I and system include directories. */
1688: name = Dir_FindFile(fname, parseIncPath);
1.454 rillig 1689: if (name == NULL) {
1.517 rillig 1690: SearchPath *sysInc = Lst_IsEmpty(&sysIncPath->dirs)
1.546 rillig 1691: ? defSysIncPath : sysIncPath;
1.409 rillig 1692: name = Dir_FindFile(fname, sysInc);
1693: }
1.454 rillig 1694: if (name == NULL || (fd = open(name, O_RDONLY)) == -1) {
1.238 christos 1695: free(name);
1.48 christos 1696: free(path);
1.553 rillig 1697: return false;
1.48 christos 1698: }
1.1 cgd 1699: fname = name;
1700: /*
1701: * set the MAKEFILE variable desired by System V fans -- the
1702: * placement of the setting here means it gets set to the last
1703: * makefile specified, as it is set by SysV make.
1704: */
1.67 sjg 1705: found:
1.176 sjg 1706: if (!doing_depend)
1.532 rillig 1707: Var_Set(SCOPE_INTERNAL, "MAKEFILE", fname);
1.140 dsl 1708: Parse_File(fname, fd);
1.1 cgd 1709: }
1.48 christos 1710: free(path);
1.553 rillig 1711: return true;
1.54 sjg 1712: }
1713:
1.514 rillig 1714: /*
1.550 rillig 1715: * Execute the command in cmd, and return its output (only stdout, not
1716: * stderr). In the output, replace newlines with spaces.
1.29 christos 1717: *
1718: * Results:
1.550 rillig 1719: * The output of the command, can be empty.
1.293 rillig 1720: * *errfmt returns a format string describing the command failure,
1721: * if any, using a single %s conversion specification.
1.550 rillig 1722: * TODO: replace errfmt with an actual error message.
1.29 christos 1723: */
1724: char *
1.293 rillig 1725: Cmd_Exec(const char *cmd, const char **errfmt)
1.29 christos 1726: {
1.550 rillig 1727: const char *args[4]; /* Arguments for invoking the shell */
1.482 rillig 1728: int pipefds[2];
1.453 rillig 1729: int cpid; /* Child PID */
1730: int pid; /* PID from wait() */
1731: int status; /* command exit status */
1732: Buffer buf; /* buffer to store the result */
1733: ssize_t bytes_read;
1734: char *res; /* result */
1735: size_t res_len;
1736: char *cp;
1737: int savederr; /* saved errno */
1738:
1739: *errfmt = NULL;
1740:
1.511 rillig 1741: if (shellName == NULL)
1.453 rillig 1742: Shell_Init();
1.550 rillig 1743:
1.453 rillig 1744: args[0] = shellName;
1745: args[1] = "-c";
1746: args[2] = cmd;
1747: args[3] = NULL;
1.31 christos 1748:
1.482 rillig 1749: if (pipe(pipefds) == -1) {
1.453 rillig 1750: *errfmt = "Couldn't create pipe for \"%s\"";
1.558 ! rillig 1751: return bmake_strdup("");
1.453 rillig 1752: }
1753:
1.504 rillig 1754: Var_ReexportVars();
1755:
1.526 rillig 1756: switch (cpid = vfork()) {
1.453 rillig 1757: case 0:
1.550 rillig 1758: (void)close(pipefds[0]);
1.482 rillig 1759: (void)dup2(pipefds[1], 1);
1760: (void)close(pipefds[1]);
1.143 sjg 1761:
1.453 rillig 1762: (void)execv(shellPath, UNCONST(args));
1763: _exit(1);
1.547 rillig 1764: /* NOTREACHED */
1.453 rillig 1765:
1766: case -1:
1767: *errfmt = "Couldn't exec \"%s\"";
1.558 ! rillig 1768: return bmake_strdup("");
! 1769: }
1.29 christos 1770:
1.558 ! rillig 1771: (void)close(pipefds[1]); /* No need for the writing half */
1.31 christos 1772:
1.558 ! rillig 1773: savederr = 0;
! 1774: Buf_Init(&buf);
! 1775:
! 1776: do {
! 1777: char result[BUFSIZ];
! 1778: bytes_read = read(pipefds[0], result, sizeof result);
! 1779: if (bytes_read > 0)
! 1780: Buf_AddBytes(&buf, result, (size_t)bytes_read);
! 1781: } while (bytes_read > 0 || (bytes_read == -1 && errno == EINTR));
! 1782: if (bytes_read == -1)
! 1783: savederr = errno;
! 1784:
! 1785: (void)close(pipefds[0]); /* Close the input side of the pipe. */
! 1786:
! 1787: while ((pid = waitpid(cpid, &status, 0)) != cpid && pid >= 0)
! 1788: JobReapChild(pid, status, false);
! 1789:
! 1790: res_len = buf.len;
! 1791: res = Buf_DoneData(&buf);
! 1792:
! 1793: if (savederr != 0)
! 1794: *errfmt = "Couldn't read shell's output for \"%s\"";
! 1795:
! 1796: if (WIFSIGNALED(status))
! 1797: *errfmt = "\"%s\" exited on a signal";
! 1798: else if (WEXITSTATUS(status) != 0)
! 1799: *errfmt = "\"%s\" returned non-zero status";
! 1800:
! 1801: /* Convert newlines to spaces, strip the final newline. */
! 1802: if (res_len > 0 && res[res_len - 1] == '\n')
! 1803: res[res_len - 1] = '\0';
! 1804: for (cp = res; *cp != '\0'; cp++)
! 1805: if (*cp == '\n')
! 1806: *cp = ' ';
1.29 christos 1807:
1.453 rillig 1808: return res;
1.1 cgd 1809: }
1810:
1.507 rillig 1811: /*
1812: * Print a printf-style error message.
1.1 cgd 1813: *
1.550 rillig 1814: * In default mode, this error message has no consequences, for compatibility
1815: * reasons, in particular it does not affect the exit status. Only in lint
1816: * mode (-dL) it does.
1.507 rillig 1817: */
1.1 cgd 1818: void
1.89 christos 1819: Error(const char *fmt, ...)
1.1 cgd 1820: {
1821: va_list ap;
1.162 dsl 1822: FILE *err_file;
1.85 wiz 1823:
1.391 rillig 1824: err_file = opts.debug_file;
1.162 dsl 1825: if (err_file == stdout)
1826: err_file = stderr;
1.184 sjg 1827: (void)fflush(stdout);
1.162 dsl 1828: for (;;) {
1829: va_start(ap, fmt);
1830: fprintf(err_file, "%s: ", progname);
1831: (void)vfprintf(err_file, fmt, ap);
1832: va_end(ap);
1833: (void)fprintf(err_file, "\n");
1834: (void)fflush(err_file);
1835: if (err_file == stderr)
1836: break;
1837: err_file = stderr;
1838: }
1.481 rillig 1839: main_errors++;
1.1 cgd 1840: }
1841:
1.507 rillig 1842: /*
1843: * Wait for any running jobs to finish, then produce an error message,
1.465 rillig 1844: * finally exit immediately.
1.1 cgd 1845: *
1.465 rillig 1846: * Exiting immediately differs from Parse_Error, which exits only after the
1.507 rillig 1847: * current top-level makefile has been parsed completely.
1848: */
1.1 cgd 1849: void
1.89 christos 1850: Fatal(const char *fmt, ...)
1.1 cgd 1851: {
1852: va_list ap;
1.85 wiz 1853:
1.1 cgd 1854: if (jobsRunning)
1855: Job_Wait();
1856:
1.184 sjg 1857: (void)fflush(stdout);
1.465 rillig 1858: va_start(ap, fmt);
1.1 cgd 1859: (void)vfprintf(stderr, fmt, ap);
1860: va_end(ap);
1861: (void)fprintf(stderr, "\n");
1862: (void)fflush(stderr);
1863:
1.176 sjg 1864: PrintOnError(NULL, NULL);
1.67 sjg 1865:
1.94 dsl 1866: if (DEBUG(GRAPH2) || DEBUG(GRAPH3))
1.1 cgd 1867: Targ_PrintGraph(2);
1.433 rillig 1868: Trace_Log(MAKEERROR, NULL);
1.1 cgd 1869: exit(2); /* Not 1 so -q can distinguish error */
1870: }
1871:
1.507 rillig 1872: /*
1873: * Major exception once jobs are being created.
1874: * Kills all jobs, prints a message and exits.
1875: */
1.1 cgd 1876: void
1.89 christos 1877: Punt(const char *fmt, ...)
1.1 cgd 1878: {
1879: va_list ap;
1.85 wiz 1880:
1.13 cgd 1881: va_start(ap, fmt);
1.184 sjg 1882: (void)fflush(stdout);
1.63 christos 1883: (void)fprintf(stderr, "%s: ", progname);
1.1 cgd 1884: (void)vfprintf(stderr, fmt, ap);
1885: va_end(ap);
1886: (void)fprintf(stderr, "\n");
1887: (void)fflush(stderr);
1888:
1.176 sjg 1889: PrintOnError(NULL, NULL);
1.67 sjg 1890:
1.1 cgd 1891: DieHorribly();
1892: }
1893:
1.392 rillig 1894: /* Exit without giving a message. */
1.1 cgd 1895: void
1.85 wiz 1896: DieHorribly(void)
1.1 cgd 1897: {
1898: if (jobsRunning)
1899: Job_AbortAll();
1900: if (DEBUG(GRAPH2))
1901: Targ_PrintGraph(2);
1.433 rillig 1902: Trace_Log(MAKEERROR, NULL);
1.505 rillig 1903: exit(2); /* Not 1 so -q can distinguish error */
1.1 cgd 1904: }
1905:
1.507 rillig 1906: /*
1907: * Called when aborting due to errors in child shell to signal abnormal exit.
1.392 rillig 1908: * The program exits.
1.507 rillig 1909: * Errors is the number of errors encountered in Make_Make.
1910: */
1.1 cgd 1911: void
1.421 rillig 1912: Finish(int errs)
1.1 cgd 1913: {
1.429 rillig 1914: if (shouldDieQuietly(NULL, -1))
1.275 sjg 1915: exit(2);
1.421 rillig 1916: Fatal("%d error%s", errs, errs == 1 ? "" : "s");
1.1 cgd 1917: }
1918:
1.548 rillig 1919: bool
1920: unlink_file(const char *file)
1.21 christos 1921: {
1922: struct stat st;
1923:
1924: if (lstat(file, &st) == -1)
1.548 rillig 1925: return false;
1.21 christos 1926:
1927: if (S_ISDIR(st.st_mode)) {
1928: errno = EISDIR;
1.548 rillig 1929: return false;
1.21 christos 1930: }
1.548 rillig 1931: return unlink(file) == 0;
1.1 cgd 1932: }
1933:
1.373 rillig 1934: static void
1935: write_all(int fd, const void *data, size_t n)
1936: {
1937: const char *mem = data;
1938:
1939: while (n > 0) {
1940: ssize_t written = write(fd, mem, n);
1941: if (written == -1 && errno == EAGAIN)
1942: continue;
1943: if (written == -1)
1944: break;
1945: mem += written;
1.375 rillig 1946: n -= (size_t)written;
1.373 rillig 1947: }
1948: }
1949:
1.550 rillig 1950: /* Print why exec failed, avoiding stdio. */
1.372 rillig 1951: void MAKE_ATTR_DEAD
1952: execDie(const char *af, const char *av)
1.66 christos 1953: {
1.373 rillig 1954: Buffer buf;
1955:
1.435 rillig 1956: Buf_Init(&buf);
1.373 rillig 1957: Buf_AddStr(&buf, progname);
1958: Buf_AddStr(&buf, ": ");
1959: Buf_AddStr(&buf, af);
1960: Buf_AddStr(&buf, "(");
1961: Buf_AddStr(&buf, av);
1962: Buf_AddStr(&buf, ") failed (");
1963: Buf_AddStr(&buf, strerror(errno));
1964: Buf_AddStr(&buf, ")\n");
1.66 christos 1965:
1.520 rillig 1966: write_all(STDERR_FILENO, buf.data, buf.len);
1.66 christos 1967:
1.518 rillig 1968: Buf_Done(&buf);
1.372 rillig 1969: _exit(1);
1.66 christos 1970: }
1971:
1.262 riastrad 1972: /* purge any relative paths */
1973: static void
1.469 rillig 1974: purge_relative_cached_realpaths(void)
1.262 riastrad 1975: {
1.453 rillig 1976: HashEntry *he, *nhe;
1977: HashIter hi;
1978:
1.469 rillig 1979: HashIter_Init(&hi, &cached_realpaths);
1.453 rillig 1980: he = HashIter_Next(&hi);
1981: while (he != NULL) {
1982: nhe = HashIter_Next(&hi);
1983: if (he->key[0] != '/') {
1.469 rillig 1984: DEBUG1(DIR, "cached_realpath: purging %s\n", he->key);
1985: HashTable_DeleteEntry(&cached_realpaths, he);
1.547 rillig 1986: /*
1987: * XXX: What about the allocated he->value? Either
1988: * free them or document why they cannot be freed.
1989: */
1.453 rillig 1990: }
1991: he = nhe;
1.262 riastrad 1992: }
1993: }
1994:
1.245 sjg 1995: char *
1996: cached_realpath(const char *pathname, char *resolved)
1997: {
1.453 rillig 1998: const char *rp;
1999:
2000: if (pathname == NULL || pathname[0] == '\0')
2001: return NULL;
2002:
1.469 rillig 2003: rp = HashTable_FindValue(&cached_realpaths, pathname);
2004: if (rp != NULL) {
1.453 rillig 2005: /* a hit */
2006: strncpy(resolved, rp, MAXPATHLEN);
2007: resolved[MAXPATHLEN - 1] = '\0';
1.469 rillig 2008: return resolved;
2009: }
2010:
2011: rp = realpath(pathname, resolved);
2012: if (rp != NULL) {
2013: HashTable_Set(&cached_realpaths, pathname, bmake_strdup(rp));
2014: DEBUG2(DIR, "cached_realpath: %s -> %s\n", pathname, rp);
2015: return resolved;
2016: }
1.248 christos 2017:
1.469 rillig 2018: /* should we negative-cache? */
2019: return NULL;
1.245 sjg 2020: }
2021:
1.275 sjg 2022: /*
2023: * Return true if we should die without noise.
1.429 rillig 2024: * For example our failing child was a sub-make or failure happened elsewhere.
1.275 sjg 2025: */
1.534 rillig 2026: bool
1.429 rillig 2027: shouldDieQuietly(GNode *gn, int bf)
1.275 sjg 2028: {
1.453 rillig 2029: static int quietly = -1;
1.275 sjg 2030:
1.453 rillig 2031: if (quietly < 0) {
1.538 rillig 2032: if (DEBUG(JOB) ||
2033: !GetBooleanExpr("${.MAKE.DIE_QUIETLY}", true))
1.453 rillig 2034: quietly = 0;
2035: else if (bf >= 0)
2036: quietly = bf;
2037: else
1.512 rillig 2038: quietly = (gn != NULL && (gn->type & OP_MAKE)) ? 1 : 0;
1.453 rillig 2039: }
1.513 rillig 2040: return quietly != 0;
1.275 sjg 2041: }
2042:
1.385 rillig 2043: static void
2044: SetErrorVars(GNode *gn)
2045: {
1.453 rillig 2046: StringListNode *ln;
1.385 rillig 2047:
1.453 rillig 2048: /*
2049: * We can print this even if there is no .ERROR target.
2050: */
1.528 rillig 2051: Global_Set(".ERROR_TARGET", gn->name);
1.531 rillig 2052: Global_Delete(".ERROR_CMD");
1.453 rillig 2053:
1.483 rillig 2054: for (ln = gn->commands.first; ln != NULL; ln = ln->next) {
1.453 rillig 2055: const char *cmd = ln->datum;
2056:
2057: if (cmd == NULL)
2058: break;
1.529 rillig 2059: Global_Append(".ERROR_CMD", cmd);
1.453 rillig 2060: }
1.385 rillig 2061: }
2062:
1.507 rillig 2063: /*
2064: * Print some helpful information in case of an error.
2065: * The caller should exit soon after calling this function.
2066: */
1.67 sjg 2067: void
1.472 rillig 2068: PrintOnError(GNode *gn, const char *msg)
1.67 sjg 2069: {
1.472 rillig 2070: static GNode *errorNode = NULL;
1.283 sjg 2071:
1.453 rillig 2072: if (DEBUG(HASH)) {
2073: Targ_Stats();
2074: Var_Stats();
2075: }
2076:
1.509 sjg 2077: if (errorNode != NULL)
2078: return; /* we've been here! */
1.453 rillig 2079:
1.472 rillig 2080: if (msg != NULL)
2081: printf("%s", msg);
1.453 rillig 2082: printf("\n%s: stopped in %s\n", progname, curdir);
1.279 rillig 2083:
1.509 sjg 2084: /* we generally want to keep quiet if a sub-make died */
2085: if (shouldDieQuietly(gn, -1))
2086: return;
1.472 rillig 2087:
2088: if (gn != NULL)
1.453 rillig 2089: SetErrorVars(gn);
1.472 rillig 2090:
2091: {
2092: char *errorVarsValues;
2093: (void)Var_Subst("${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
1.546 rillig 2094: SCOPE_GLOBAL, VARE_WANTRES, &errorVarsValues);
1.472 rillig 2095: /* TODO: handle errors */
2096: printf("%s", errorVarsValues);
2097: free(errorVarsValues);
2098: }
2099:
1.453 rillig 2100: fflush(stdout);
1.176 sjg 2101:
1.453 rillig 2102: /*
2103: * Finally, see if there is a .ERROR target, and run it if so.
2104: */
1.472 rillig 2105: errorNode = Targ_FindNode(".ERROR");
2106: if (errorNode != NULL) {
2107: errorNode->type |= OP_SPECIAL;
2108: Compat_Make(errorNode, errorNode);
1.453 rillig 2109: }
1.68 sjg 2110: }
2111:
2112: void
1.534 rillig 2113: Main_ExportMAKEFLAGS(bool first)
1.68 sjg 2114: {
1.534 rillig 2115: static bool once = true;
1.453 rillig 2116: const char *expr;
2117: char *s;
1.68 sjg 2118:
1.453 rillig 2119: if (once != first)
2120: return;
1.534 rillig 2121: once = false;
1.279 rillig 2122:
1.453 rillig 2123: expr = "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}";
1.530 rillig 2124: (void)Var_Subst(expr, SCOPE_CMDLINE, VARE_WANTRES, &s);
1.453 rillig 2125: /* TODO: handle errors */
2126: if (s[0] != '\0') {
1.68 sjg 2127: #ifdef POSIX
1.453 rillig 2128: setenv("MAKEFLAGS", s, 1);
1.68 sjg 2129: #else
1.453 rillig 2130: setenv("MAKE", s, 1);
1.68 sjg 2131: #endif
1.453 rillig 2132: }
1.1 cgd 2133: }
1.180 sjg 2134:
1.191 sjg 2135: char *
2136: getTmpdir(void)
1.180 sjg 2137: {
1.453 rillig 2138: static char *tmpdir = NULL;
1.473 rillig 2139: struct stat st;
2140:
2141: if (tmpdir != NULL)
2142: return tmpdir;
1.180 sjg 2143:
1.473 rillig 2144: /* Honor $TMPDIR but only if it is valid. Ensure it ends with '/'. */
1.539 rillig 2145: (void)Var_Subst("${TMPDIR:tA:U" _PATH_TMP ":S,/$,,W}/",
1.530 rillig 2146: SCOPE_GLOBAL, VARE_WANTRES, &tmpdir);
1.473 rillig 2147: /* TODO: handle errors */
1.180 sjg 2148:
1.473 rillig 2149: if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
2150: free(tmpdir);
2151: tmpdir = bmake_strdup(_PATH_TMP);
1.180 sjg 2152: }
1.453 rillig 2153: return tmpdir;
1.191 sjg 2154: }
2155:
2156: /*
2157: * Create and open a temp file using "pattern".
1.414 rillig 2158: * If out_fname is provided, set it to a copy of the filename created.
1.191 sjg 2159: * Otherwise unlink the file once open.
2160: */
2161: int
1.533 sjg 2162: mkTempFile(const char *pattern, char *tfile, size_t tfile_sz)
1.191 sjg 2163: {
1.453 rillig 2164: static char *tmpdir = NULL;
1.533 sjg 2165: char tbuf[MAXPATHLEN];
1.453 rillig 2166: int fd;
2167:
2168: if (pattern == NULL)
2169: pattern = TMPPAT;
2170: if (tmpdir == NULL)
2171: tmpdir = getTmpdir();
1.533 sjg 2172: if (tfile == NULL) {
1.546 rillig 2173: tfile = tbuf;
2174: tfile_sz = sizeof tbuf;
1.533 sjg 2175: }
1.453 rillig 2176: if (pattern[0] == '/') {
1.533 sjg 2177: snprintf(tfile, tfile_sz, "%s", pattern);
1.453 rillig 2178: } else {
1.533 sjg 2179: snprintf(tfile, tfile_sz, "%s%s", tmpdir, pattern);
1.453 rillig 2180: }
2181: if ((fd = mkstemp(tfile)) < 0)
2182: Punt("Could not create temporary file %s: %s", tfile,
2183: strerror(errno));
1.533 sjg 2184: if (tfile == tbuf) {
1.479 rillig 2185: unlink(tfile); /* we just want the descriptor */
1.453 rillig 2186: }
2187: return fd;
1.180 sjg 2188: }
1.201 sjg 2189:
1.240 sjg 2190: /*
1.474 rillig 2191: * Convert a string representation of a boolean into a boolean value.
1.534 rillig 2192: * Anything that looks like "No", "False", "Off", "0" etc. is false,
2193: * the empty string is the fallback, everything else is true.
1.240 sjg 2194: */
1.534 rillig 2195: bool
2196: ParseBoolean(const char *s, bool fallback)
1.240 sjg 2197: {
1.474 rillig 2198: char ch = ch_tolower(s[0]);
2199: if (ch == '\0')
2200: return fallback;
2201: if (ch == '0' || ch == 'f' || ch == 'n')
1.534 rillig 2202: return false;
1.474 rillig 2203: if (ch == 'o')
2204: return ch_tolower(s[1]) != 'f';
1.534 rillig 2205: return true;
1.240 sjg 2206: }
CVSweb <webmaster@jp.NetBSD.org>