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