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