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