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