main.c revision 49938
1192067Snwhitehorn/* 2236098Sraj * Copyright (c) 1988, 1989, 1990, 1993 3192067Snwhitehorn * The Regents of the University of California. All rights reserved. 4192067Snwhitehorn * Copyright (c) 1989 by Berkeley Softworks 5192067Snwhitehorn * All rights reserved. 6192067Snwhitehorn * 7192067Snwhitehorn * This code is derived from software contributed to Berkeley by 8192067Snwhitehorn * Adam de Boor. 9192067Snwhitehorn * 10192067Snwhitehorn * Redistribution and use in source and binary forms, with or without 11192067Snwhitehorn * modification, are permitted provided that the following conditions 12192067Snwhitehorn * are met: 13192067Snwhitehorn * 1. Redistributions of source code must retain the above copyright 14192067Snwhitehorn * notice, this list of conditions and the following disclaimer. 15192067Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 16192067Snwhitehorn * notice, this list of conditions and the following disclaimer in the 17192067Snwhitehorn * documentation and/or other materials provided with the distribution. 18192067Snwhitehorn * 3. All advertising materials mentioning features or use of this software 19192067Snwhitehorn * must display the following acknowledgement: 20192067Snwhitehorn * This product includes software developed by the University of 21192067Snwhitehorn * California, Berkeley and its contributors. 22192067Snwhitehorn * 4. Neither the name of the University nor the names of its contributors 23192067Snwhitehorn * may be used to endorse or promote products derived from this software 24192067Snwhitehorn * without specific prior written permission. 25192067Snwhitehorn * 26192067Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27192067Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28192067Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29192067Snwhitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30192067Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31192067Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32192067Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33192067Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34192067Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35192067Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36192067Snwhitehorn * SUCH DAMAGE. 37192067Snwhitehorn */ 38266003Sian 39266003Sian#ifndef lint 40192067Snwhitehornstatic const char copyright[] = 41192067Snwhitehorn"@(#) Copyright (c) 1988, 1989, 1990, 1993\n\ 42192067Snwhitehorn The Regents of the University of California. All rights reserved.\n"; 43192067Snwhitehorn#endif /* not lint */ 44192067Snwhitehorn 45217523Smarcel#ifndef lint 46217523Smarcel#if 0 47192067Snwhitehornstatic char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94"; 48266020Sian#else 49266020Sianstatic const char rcsid[] = 50192067Snwhitehorn "$Id: main.c,v 1.32 1999/07/31 20:53:01 hoek Exp $"; 51192067Snwhitehorn#endif 52266003Sian#endif /* not lint */ 53212054Snwhitehorn 54192067Snwhitehorn/*- 55236325Sraj * main.c -- 56192067Snwhitehorn * The main file for this entire program. Exit routines etc 57192067Snwhitehorn * reside here. 58192067Snwhitehorn * 59266003Sian * Utility functions defined in this file: 60192067Snwhitehorn * Main_ParseArgLine Takes a line of arguments, breaks them and 61246732Srpaulo * treats them as if they were given when first 62192067Snwhitehorn * invoked. Used by the parse module to implement 63192067Snwhitehorn * the .MFLAGS target. 64192067Snwhitehorn * 65266003Sian * Error Print a tagged error message. The global 66192067Snwhitehorn * MAKE variable must have been defined. This 67192067Snwhitehorn * takes a format string and two optional 68192067Snwhitehorn * arguments for it. 69192067Snwhitehorn * 70192067Snwhitehorn * Fatal Print an error message and exit. Also takes 71192067Snwhitehorn * a format string and two arguments. 72192067Snwhitehorn * 73192067Snwhitehorn * Punt Aborts all jobs and exits with a message. Also 74192067Snwhitehorn * takes a format string and two arguments. 75192067Snwhitehorn * 76266003Sian * Finish Finish things up by printing the number of 77266003Sian * errors which occured, as passed to it, and 78193492Sraj * exiting. 79192067Snwhitehorn */ 80192067Snwhitehorn 81192067Snwhitehorn#include <sys/types.h> 82192067Snwhitehorn#include <sys/time.h> 83266020Sian#include <sys/param.h> 84266020Sian#include <sys/resource.h> 85192067Snwhitehorn#include <sys/signal.h> 86192067Snwhitehorn#include <sys/stat.h> 87266003Sian#if defined(__i386__) 88192067Snwhitehorn#include <sys/sysctl.h> 89192067Snwhitehorn#endif 90192067Snwhitehorn#ifndef MACHINE 91192067Snwhitehorn#include <sys/utsname.h> 92192067Snwhitehorn#endif 93217523Smarcel#include <sys/wait.h> 94209908Sraj#include <err.h> 95209908Sraj#include <stdlib.h> 96192067Snwhitehorn#include <errno.h> 97224618Smarcel#include <fcntl.h> 98224611Smarcel#include <stdio.h> 99224611Smarcel#include <sysexits.h> 100224611Smarcel#ifdef __STDC__ 101224611Smarcel#include <stdarg.h> 102224618Smarcel#else 103224611Smarcel#include <varargs.h> 104224618Smarcel#endif 105222327Smarcel#include "make.h" 106222327Smarcel#include "hash.h" 107217523Smarcel#include "dir.h" 108228201Sjchandra#include "job.h" 109209908Sraj#include "pathnames.h" 110209908Sraj 111209908Sraj#ifndef DEFMAXLOCAL 112209908Sraj#define DEFMAXLOCAL DEFMAXJOBS 113209908Sraj#endif /* DEFMAXLOCAL */ 114265968Sian 115265968Sian#define MAKEFLAGS ".MAKEFLAGS" 116265968Sian 117265968SianLst create; /* Targets to be made */ 118265968Siantime_t now; /* Time at start of make */ 119265968SianGNode *DEFAULT; /* .DEFAULT node */ 120265968SianBoolean allPrecious; /* .PRECIOUS given on line by itself */ 121265968Sian 122265968Sianstatic Boolean noBuiltins; /* -r flag */ 123265968Sianstatic Lst makefiles; /* ordered list of makefiles to read */ 124265968Sianstatic Boolean printVars; /* print value of one or more vars */ 125265968Sianstatic Lst variables; /* list of variables to print */ 126265968Sianint maxJobs; /* -j argument */ 127265968Sianstatic Boolean forceJobs; /* -j argument given */ 128265968Sianstatic int maxLocal; /* -L argument */ 129265968SianBoolean compatMake; /* -B argument */ 130265968SianBoolean debug; /* -d flag */ 131265968SianBoolean noExecute; /* -n flag */ 132265968SianBoolean keepgoing; /* -k flag */ 133217523SmarcelBoolean queryFlag; /* -q flag */ 134209908SrajBoolean touchFlag; /* -t flag */ 135209908SrajBoolean usePipes; /* !-P flag */ 136209908SrajBoolean ignoreErrors; /* -i flag */ 137217523SmarcelBoolean beSilent; /* -s flag */ 138192067SnwhitehornBoolean beVerbose; /* -v flag */ 139192067SnwhitehornBoolean oldVars; /* variable substitution style */ 140192067SnwhitehornBoolean checkEnvFirst; /* -e flag */ 141192067SnwhitehornLst envFirstVars; /* (-E) vars to override from env */ 142217523Smarcelstatic Boolean jobsRunning; /* TRUE if the jobs might be running */ 143217523Smarcel 144217523Smarcelstatic void MainParseArgs __P((int, char **)); 145209908Srajchar * chdir_verify_path __P((char *, char *)); 146192067Snwhitehornstatic int ReadMakefile __P((ClientData, ClientData)); 147192067Snwhitehornstatic void usage __P((void)); 148192067Snwhitehorn 149192067Snwhitehornstatic char *curdir; /* startup directory */ 150192067Snwhitehornstatic char *objdir; /* where we chdir'ed to */ 151192067Snwhitehorn 152212054Snwhitehorn/*- 153266003Sian * MainParseArgs -- 154212054Snwhitehorn * Parse a given argument vector. Called from main() and from 155212054Snwhitehorn * Main_ParseArgLine() when the .MAKEFLAGS target is used. 156212054Snwhitehorn * 157236097Sraj * XXX: Deal with command line overriding .MAKEFLAGS in makefile 158236097Sraj * 159212054Snwhitehorn * Results: 160212054Snwhitehorn * None 161 * 162 * Side Effects: 163 * Various global and local flags will be set depending on the flags 164 * given 165 */ 166static void 167MainParseArgs(argc, argv) 168 int argc; 169 char **argv; 170{ 171 extern int optind; 172 extern char *optarg; 173 char *p; 174 int c; 175 176 optind = 1; /* since we're called more than once */ 177#ifdef REMOTE 178# define OPTFLAGS "BD:E:I:L:PSV:d:ef:ij:km:nqrstv" 179#else 180# define OPTFLAGS "BD:E:I:PSV:d:ef:ij:km:nqrstv" 181#endif 182rearg: 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 p = malloc(strlen(optarg) + 1 + 3); 197 if (!p) 198 Punt("make: cannot allocate memory."); 199 /* This sprintf is safe, because of the malloc above */ 200 (void)sprintf(p, "${%s}", optarg); 201 (void)Lst_AtEnd(variables, (ClientData)p); 202 Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL); 203 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 204 break; 205 case 'B': 206 compatMake = TRUE; 207 Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL); 208 break; 209#ifdef REMOTE 210 case 'L': { 211 char *endptr; 212 213 maxLocal = strtol(optarg, &endptr, 10); 214 if (maxLocal < 0 || *endptr != '\0') { 215 warnx("illegal number, -L argument -- %s", 216 optarg); 217 usage(); 218 } 219 Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL); 220 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 221 break; 222 } 223#endif 224 case 'P': 225 usePipes = FALSE; 226 Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL); 227 break; 228 case 'S': 229 keepgoing = FALSE; 230 Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL); 231 break; 232 case 'd': { 233 char *modules = optarg; 234 235 for (; *modules; ++modules) 236 switch (*modules) { 237 case 'A': 238 debug = ~0; 239 break; 240 case 'a': 241 debug |= DEBUG_ARCH; 242 break; 243 case 'c': 244 debug |= DEBUG_COND; 245 break; 246 case 'd': 247 debug |= DEBUG_DIR; 248 break; 249 case 'f': 250 debug |= DEBUG_FOR; 251 break; 252 case 'g': 253 if (modules[1] == '1') { 254 debug |= DEBUG_GRAPH1; 255 ++modules; 256 } 257 else if (modules[1] == '2') { 258 debug |= DEBUG_GRAPH2; 259 ++modules; 260 } 261 break; 262 case 'j': 263 debug |= DEBUG_JOB; 264 break; 265 case 'm': 266 debug |= DEBUG_MAKE; 267 break; 268 case 's': 269 debug |= DEBUG_SUFF; 270 break; 271 case 't': 272 debug |= DEBUG_TARG; 273 break; 274 case 'v': 275 debug |= DEBUG_VAR; 276 break; 277 default: 278 warnx("illegal argument to d option -- %c", *modules); 279 usage(); 280 } 281 Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL); 282 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 283 break; 284 } 285 case 'E': 286 p = malloc(strlen(optarg) + 1); 287 if (!p) 288 Punt("make: cannot allocate memory."); 289 (void)strcpy(p, optarg); 290 (void)Lst_AtEnd(envFirstVars, (ClientData)p); 291 Var_Append(MAKEFLAGS, "-E", VAR_GLOBAL); 292 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 293 break; 294 case 'e': 295 checkEnvFirst = TRUE; 296 Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL); 297 break; 298 case 'f': 299 (void)Lst_AtEnd(makefiles, (ClientData)optarg); 300 break; 301 case 'i': 302 ignoreErrors = TRUE; 303 Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL); 304 break; 305 case 'j': { 306 char *endptr; 307 308 forceJobs = TRUE; 309 maxJobs = strtol(optarg, &endptr, 10); 310 if (maxJobs <= 0 || *endptr != '\0') { 311 warnx("illegal number, -j argument -- %s", 312 optarg); 313 usage(); 314 } 315#ifndef REMOTE 316 maxLocal = maxJobs; 317#endif 318 Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); 319 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 320 break; 321 } 322 case 'k': 323 keepgoing = TRUE; 324 Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); 325 break; 326 case 'm': 327 Dir_AddDir(sysIncPath, optarg); 328 Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL); 329 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 330 break; 331 case 'n': 332 noExecute = TRUE; 333 Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL); 334 break; 335 case 'q': 336 queryFlag = TRUE; 337 /* Kind of nonsensical, wot? */ 338 Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL); 339 break; 340 case 'r': 341 noBuiltins = TRUE; 342 Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL); 343 break; 344 case 's': 345 beSilent = TRUE; 346 Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL); 347 break; 348 case 't': 349 touchFlag = TRUE; 350 Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL); 351 break; 352 case 'v': 353 beVerbose = TRUE; 354 Var_Append(MAKEFLAGS, "-v", VAR_GLOBAL); 355 break; 356 default: 357 case '?': 358 usage(); 359 } 360 } 361 362 oldVars = TRUE; 363 364 /* 365 * See if the rest of the arguments are variable assignments and 366 * perform them if so. Else take them to be targets and stuff them 367 * on the end of the "create" list. 368 */ 369 for (argv += optind, argc -= optind; *argv; ++argv, --argc) 370 if (Parse_IsVar(*argv)) 371 Parse_DoVar(*argv, VAR_CMD); 372 else { 373 if (!**argv) 374 Punt("illegal (null) argument."); 375 if (**argv == '-') { 376 if ((*argv)[1]) 377 optind = 0; /* -flag... */ 378 else 379 optind = 1; /* - */ 380 goto rearg; 381 } 382 (void)Lst_AtEnd(create, (ClientData)estrdup(*argv)); 383 } 384} 385 386/*- 387 * Main_ParseArgLine -- 388 * Used by the parse module when a .MFLAGS or .MAKEFLAGS target 389 * is encountered and by main() when reading the .MAKEFLAGS envariable. 390 * Takes a line of arguments and breaks it into its 391 * component words and passes those words and the number of them to the 392 * MainParseArgs function. 393 * The line should have all its leading whitespace removed. 394 * 395 * Results: 396 * None 397 * 398 * Side Effects: 399 * Only those that come from the various arguments. 400 */ 401void 402Main_ParseArgLine(line) 403 char *line; /* Line to fracture */ 404{ 405 char **argv; /* Manufactured argument vector */ 406 int argc; /* Number of arguments in argv */ 407 408 if (line == NULL) 409 return; 410 for (; *line == ' '; ++line) 411 continue; 412 if (!*line) 413 return; 414 415 argv = brk_string(line, &argc, TRUE); 416 MainParseArgs(argc, argv); 417} 418 419char * 420chdir_verify_path(path, obpath) 421 char *path; 422 char *obpath; 423{ 424 struct stat sb; 425 426 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { 427 if (chdir(path)) { 428 warn("warning: %s", path); 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 */ 463int 464main(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 sa; 471 char *p, *p1, *path, *pathp; 472#ifdef WANT_ENV_PWD 473 struct stat sb; 474 char *pwd; 475#endif 476 char mdpath[MAXPATHLEN + 1]; 477 char obpath[MAXPATHLEN + 1]; 478 char cdpath[MAXPATHLEN + 1]; 479 char *machine = getenv("MACHINE"); 480 char *machine_arch = getenv("MACHINE_ARCH"); 481 Lst sysMkPath; /* Path of sys.mk */ 482 char *cp = NULL, *start; 483 /* avoid faults on read-only strings */ 484 static char syspath[] = _PATH_DEFSYSPATH; 485 486#ifdef RLIMIT_NOFILE 487 /* 488 * get rid of resource limit on file descriptors 489 */ 490 { 491 struct rlimit rl; 492 if (getrlimit(RLIMIT_NOFILE, &rl) != -1 && 493 rl.rlim_cur != rl.rlim_max) { 494 rl.rlim_cur = rl.rlim_max; 495 (void) setrlimit(RLIMIT_NOFILE, &rl); 496 } 497 } 498#endif 499 /* 500 * Find where we are and take care of PWD for the automounter... 501 * All this code is so that we know where we are when we start up 502 * on a different machine with pmake. 503 */ 504 curdir = cdpath; 505 if (getcwd(curdir, MAXPATHLEN) == NULL) 506 err(2, NULL); 507 508 if (stat(curdir, &sa) == -1) 509 err(2, "%s", curdir); 510 511#ifdef WANT_ENV_PWD 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#endif 518 519#if defined(__i386__) 520 /* 521 * PC-98 kernel sets the `i386' string to the utsname.machine and 522 * it cannot be distinguished from IBM-PC by uname(3). Therefore, 523 * we check machine.ispc98 and adjust the machine variable before 524 * using usname(3) below. 525 */ 526 if (!machine) { 527 int ispc98; 528 size_t len; 529 530 len = sizeof(ispc98); 531 if (!sysctlbyname("machdep.ispc98", &ispc98, &len, NULL, 0)) { 532 if (ispc98) 533 machine = "pc98"; 534 } 535 } 536#endif 537 538 /* 539 * Get the name of this type of MACHINE from utsname 540 * so we can share an executable for similar machines. 541 * (i.e. m68k: amiga hp300, mac68k, sun3, ...) 542 * 543 * Note that while MACHINE is decided at run-time, 544 * MACHINE_ARCH is always known at compile time. 545 */ 546 if (!machine) { 547#ifndef MACHINE 548 struct utsname utsname; 549 550 if (uname(&utsname) == -1) { 551 perror("make: uname"); 552 exit(2); 553 } 554 machine = utsname.machine; 555#else 556 machine = MACHINE; 557#endif 558 } 559 560 if (!machine_arch) { 561#ifndef MACHINE_ARCH 562 machine_arch = "unknown"; 563#else 564 machine_arch = MACHINE_ARCH; 565#endif 566 } 567 568 /* 569 * The object directory location is determined using the 570 * following order of preference: 571 * 572 * 1. MAKEOBJDIRPREFIX`cwd` 573 * 2. MAKEOBJDIR 574 * 3. _PATH_OBJDIR.${MACHINE} 575 * 4. _PATH_OBJDIR 576 * 5. _PATH_OBJDIRPREFIX`cwd` 577 * 578 * If one of the first two fails, use the current directory. 579 * If the remaining three all fail, use the current directory. 580 * 581 * Once things are initted, 582 * have to add the original directory to the search path, 583 * and modify the paths for the Makefiles apropriately. The 584 * current directory is also placed as a variable for make scripts. 585 */ 586 if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) { 587 if (!(path = getenv("MAKEOBJDIR"))) { 588 path = _PATH_OBJDIR; 589 pathp = _PATH_OBJDIRPREFIX; 590 (void) snprintf(mdpath, MAXPATHLEN, "%s.%s", 591 path, machine); 592 if (!(objdir = chdir_verify_path(mdpath, obpath))) 593 if (!(objdir=chdir_verify_path(path, obpath))) { 594 (void) snprintf(mdpath, MAXPATHLEN, 595 "%s%s", pathp, curdir); 596 if (!(objdir=chdir_verify_path(mdpath, 597 obpath))) 598 objdir = curdir; 599 } 600 } 601 else if (!(objdir = chdir_verify_path(path, obpath))) 602 objdir = curdir; 603 } 604 else { 605 (void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir); 606 if (!(objdir = chdir_verify_path(mdpath, obpath))) 607 objdir = curdir; 608 } 609 610#ifdef WANT_ENV_PWD 611 setenv("PWD", objdir, 1); 612#endif 613 614 create = Lst_Init(FALSE); 615 makefiles = Lst_Init(FALSE); 616 envFirstVars = Lst_Init(FALSE); 617 printVars = FALSE; 618 variables = Lst_Init(FALSE); 619 beSilent = FALSE; /* Print commands as executed */ 620 ignoreErrors = FALSE; /* Pay attention to non-zero returns */ 621 noExecute = FALSE; /* Execute all commands */ 622 keepgoing = FALSE; /* Stop on error */ 623 allPrecious = FALSE; /* Remove targets when interrupted */ 624 queryFlag = FALSE; /* This is not just a check-run */ 625 noBuiltins = FALSE; /* Read the built-in rules */ 626 touchFlag = FALSE; /* Actually update targets */ 627 usePipes = TRUE; /* Catch child output in pipes */ 628 debug = 0; /* No debug verbosity, please. */ 629 jobsRunning = FALSE; 630 631 maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */ 632#ifdef REMOTE 633 maxJobs = DEFMAXJOBS; /* Set default max concurrency */ 634#else 635 maxJobs = maxLocal; 636#endif 637 forceJobs = FALSE; /* No -j flag */ 638 compatMake = FALSE; /* No compat mode */ 639 640 641 /* 642 * Initialize the parsing, directory and variable modules to prepare 643 * for the reading of inclusion paths and variable settings on the 644 * command line 645 */ 646 Dir_Init(); /* Initialize directory structures so -I flags 647 * can be processed correctly */ 648 Parse_Init(); /* Need to initialize the paths of #include 649 * directories */ 650 Var_Init(); /* As well as the lists of variables for 651 * parsing arguments */ 652 str_init(); 653 if (objdir != curdir) 654 Dir_AddDir(dirSearchPath, curdir); 655 Var_Set(".CURDIR", curdir, VAR_GLOBAL); 656 Var_Set(".OBJDIR", objdir, VAR_GLOBAL); 657 658 /* 659 * Initialize various variables. 660 * MAKE also gets this name, for compatibility 661 * .MAKEFLAGS gets set to the empty string just in case. 662 * MFLAGS also gets initialized empty, for compatibility. 663 */ 664 Var_Set("MAKE", argv[0], VAR_GLOBAL); 665 Var_Set(MAKEFLAGS, "", VAR_GLOBAL); 666 Var_Set("MFLAGS", "", VAR_GLOBAL); 667 Var_Set("MACHINE", machine, VAR_GLOBAL); 668 Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL); 669 670 /* 671 * First snag any flags out of the MAKE environment variable. 672 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's 673 * in a different format). 674 */ 675#ifdef POSIX 676 Main_ParseArgLine(getenv("MAKEFLAGS")); 677#else 678 Main_ParseArgLine(getenv("MAKE")); 679#endif 680 681 MainParseArgs(argc, argv); 682 683 /* 684 * Be compatible if user did not specify -j and did not explicitly 685 * turned compatibility on 686 */ 687 if (!compatMake && !forceJobs) 688 compatMake = TRUE; 689 690 /* 691 * Initialize archive, target and suffix modules in preparation for 692 * parsing the makefile(s) 693 */ 694 Arch_Init(); 695 Targ_Init(); 696 Suff_Init(); 697 698 DEFAULT = NILGNODE; 699 (void)time(&now); 700 701 /* 702 * Set up the .TARGETS variable to contain the list of targets to be 703 * created. If none specified, make the variable empty -- the parser 704 * will fill the thing in with the default or .MAIN target. 705 */ 706 if (!Lst_IsEmpty(create)) { 707 LstNode ln; 708 709 for (ln = Lst_First(create); ln != NILLNODE; 710 ln = Lst_Succ(ln)) { 711 char *name = (char *)Lst_Datum(ln); 712 713 Var_Append(".TARGETS", name, VAR_GLOBAL); 714 } 715 } else 716 Var_Set(".TARGETS", "", VAR_GLOBAL); 717 718 719 /* 720 * If no user-supplied system path was given (through the -m option) 721 * add the directories from the DEFSYSPATH (more than one may be given 722 * as dir1:...:dirn) to the system include path. 723 */ 724 if (Lst_IsEmpty(sysIncPath)) { 725 for (start = syspath; *start != '\0'; start = cp) { 726 for (cp = start; *cp != '\0' && *cp != ':'; cp++) 727 continue; 728 if (*cp == '\0') { 729 Dir_AddDir(sysIncPath, start); 730 } else { 731 *cp++ = '\0'; 732 Dir_AddDir(sysIncPath, start); 733 } 734 } 735 } 736 737 /* 738 * Read in the built-in rules first, followed by the specified 739 * makefile, if it was (makefile != (char *) NULL), or the default 740 * Makefile and makefile, in that order, if it wasn't. 741 */ 742 if (!noBuiltins) { 743 LstNode ln; 744 745 sysMkPath = Lst_Init (FALSE); 746 Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath); 747 if (Lst_IsEmpty(sysMkPath)) 748 Fatal("make: no system rules (%s).", _PATH_DEFSYSMK); 749 ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile); 750 if (ln != NILLNODE) 751 Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); 752 } 753 754 if (!Lst_IsEmpty(makefiles)) { 755 LstNode ln; 756 757 ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile); 758 if (ln != NILLNODE) 759 Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); 760 } else if (!ReadMakefile("makefile", NULL)) 761 (void)ReadMakefile("Makefile", NULL); 762 763 (void)ReadMakefile(".depend", NULL); 764 765 Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL); 766 efree(p1); 767 768 /* Install all the flags into the MAKE envariable. */ 769 if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p) 770#ifdef POSIX 771 setenv("MAKEFLAGS", p, 1); 772#else 773 setenv("MAKE", p, 1); 774#endif 775 efree(p1); 776 777 /* 778 * For compatibility, look at the directories in the VPATH variable 779 * and add them to the search path, if the variable is defined. The 780 * variable's value is in the same format as the PATH envariable, i.e. 781 * <directory>:<directory>:<directory>... 782 */ 783 if (Var_Exists("VPATH", VAR_CMD)) { 784 char *vpath, *path, *cp, savec; 785 /* 786 * GCC stores string constants in read-only memory, but 787 * Var_Subst will want to write this thing, so store it 788 * in an array 789 */ 790 static char VPATH[] = "${VPATH}"; 791 792 vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE); 793 path = vpath; 794 do { 795 /* skip to end of directory */ 796 for (cp = path; *cp != ':' && *cp != '\0'; cp++) 797 continue; 798 /* Save terminator character so know when to stop */ 799 savec = *cp; 800 *cp = '\0'; 801 /* Add directory to search path */ 802 Dir_AddDir(dirSearchPath, path); 803 *cp = savec; 804 path = cp + 1; 805 } while (savec == ':'); 806 (void)free((Address)vpath); 807 } 808 809 /* 810 * Now that all search paths have been read for suffixes et al, it's 811 * time to add the default search path to their lists... 812 */ 813 Suff_DoPaths(); 814 815 /* print the initial graph, if the user requested it */ 816 if (DEBUG(GRAPH1)) 817 Targ_PrintGraph(1); 818 819 /* print the values of any variables requested by the user */ 820 if (printVars) { 821 LstNode ln; 822 823 for (ln = Lst_First(variables); ln != NILLNODE; 824 ln = Lst_Succ(ln)) { 825 char *value = Var_Subst(NULL, (char *)Lst_Datum(ln), 826 VAR_GLOBAL, FALSE); 827 828 printf("%s\n", value ? value : ""); 829 } 830 } 831 832 /* 833 * Have now read the entire graph and need to make a list of targets 834 * to create. If none was given on the command line, we consult the 835 * parsing module to find the main target(s) to create. 836 */ 837 if (Lst_IsEmpty(create)) 838 targs = Parse_MainName(); 839 else 840 targs = Targ_FindList(create, TARG_CREATE); 841 842 if (!compatMake && !printVars) { 843 /* 844 * Initialize job module before traversing the graph, now that 845 * any .BEGIN and .END targets have been read. This is done 846 * only if the -q flag wasn't given (to prevent the .BEGIN from 847 * being executed should it exist). 848 */ 849 if (!queryFlag) { 850 if (maxLocal == -1) 851 maxLocal = maxJobs; 852 Job_Init(maxJobs, maxLocal); 853 jobsRunning = TRUE; 854 } 855 856 /* Traverse the graph, checking on all the targets */ 857 outOfDate = Make_Run(targs); 858 } else if (!printVars) { 859 /* 860 * Compat_Init will take care of creating all the targets as 861 * well as initializing the module. 862 */ 863 Compat_Run(targs); 864 } 865 866 Lst_Destroy(targs, NOFREE); 867 Lst_Destroy(variables, NOFREE); 868 Lst_Destroy(makefiles, NOFREE); 869 Lst_Destroy(create, (void (*) __P((ClientData))) free); 870 871 /* print the graph now it's been processed if the user requested it */ 872 if (DEBUG(GRAPH2)) 873 Targ_PrintGraph(2); 874 875 Suff_End(); 876 Targ_End(); 877 Arch_End(); 878 str_end(); 879 Var_End(); 880 Parse_End(); 881 Dir_End(); 882 883 if (queryFlag && outOfDate) 884 return(1); 885 else 886 return(0); 887} 888 889/*- 890 * ReadMakefile -- 891 * Open and parse the given makefile. 892 * 893 * Results: 894 * TRUE if ok. FALSE if couldn't open file. 895 * 896 * Side Effects: 897 * lots 898 */ 899static Boolean 900ReadMakefile(p, q) 901 ClientData p, q; 902{ 903 char *fname = p; /* makefile to read */ 904 extern Lst parseIncPath; 905 FILE *stream; 906 char *name, path[MAXPATHLEN + 1]; 907 908 if (!strcmp(fname, "-")) { 909 Parse_File("(stdin)", stdin); 910 Var_Set("MAKEFILE", "", VAR_GLOBAL); 911 } else { 912 /* if we've chdir'd, rebuild the path name */ 913 if (curdir != objdir && *fname != '/') { 914 (void)sprintf(path, "%s/%s", curdir, fname); 915 if ((stream = fopen(path, "r")) != NULL) { 916 fname = path; 917 goto found; 918 } 919 } else if ((stream = fopen(fname, "r")) != NULL) 920 goto found; 921 /* look in -I and system include directories. */ 922 name = Dir_FindFile(fname, parseIncPath); 923 if (!name) 924 name = Dir_FindFile(fname, sysIncPath); 925 if (!name || !(stream = fopen(name, "r"))) 926 return(FALSE); 927 fname = name; 928 /* 929 * set the MAKEFILE variable desired by System V fans -- the 930 * placement of the setting here means it gets set to the last 931 * makefile specified, as it is set by SysV make. 932 */ 933found: Var_Set("MAKEFILE", fname, VAR_GLOBAL); 934 Parse_File(fname, stream); 935 (void)fclose(stream); 936 } 937 return(TRUE); 938} 939 940/*- 941 * Cmd_Exec -- 942 * Execute the command in cmd, and return the output of that command 943 * in a string. 944 * 945 * Results: 946 * A string containing the output of the command, or the empty string 947 * If err is not NULL, it contains the reason for the command failure 948 * 949 * Side Effects: 950 * The string must be freed by the caller. 951 */ 952char * 953Cmd_Exec(cmd, err) 954 char *cmd; 955 char **err; 956{ 957 char *args[4]; /* Args for invoking the shell */ 958 int fds[2]; /* Pipe streams */ 959 int cpid; /* Child PID */ 960 int pid; /* PID from wait() */ 961 char *res; /* result */ 962 int status; /* command exit status */ 963 Buffer buf; /* buffer to store the result */ 964 char *cp; 965 int cc; 966 967 968 *err = NULL; 969 970 /* 971 * Set up arguments for shell 972 */ 973 args[0] = "sh"; 974 args[1] = "-c"; 975 args[2] = cmd; 976 args[3] = NULL; 977 978 /* 979 * Open a pipe for fetching its output 980 */ 981 if (pipe(fds) == -1) { 982 *err = "Couldn't create pipe for \"%s\""; 983 goto bad; 984 } 985 986 /* 987 * Fork 988 */ 989 switch (cpid = vfork()) { 990 case 0: 991 /* 992 * Close input side of pipe 993 */ 994 (void) close(fds[0]); 995 996 /* 997 * Duplicate the output stream to the shell's output, then 998 * shut the extra thing down. Note we don't fetch the error 999 * stream...why not? Why? 1000 */ 1001 (void) dup2(fds[1], 1); 1002 (void) close(fds[1]); 1003 1004 (void) execv("/bin/sh", args); 1005 _exit(1); 1006 /*NOTREACHED*/ 1007 1008 case -1: 1009 *err = "Couldn't exec \"%s\""; 1010 goto bad; 1011 1012 default: 1013 /* 1014 * No need for the writing half 1015 */ 1016 (void) close(fds[1]); 1017 1018 buf = Buf_Init (MAKE_BSIZE); 1019 1020 do { 1021 char result[BUFSIZ]; 1022 cc = read(fds[0], result, sizeof(result)); 1023 if (cc > 0) 1024 Buf_AddBytes(buf, cc, (Byte *) result); 1025 } 1026 while (cc > 0 || (cc == -1 && errno == EINTR)); 1027 1028 /* 1029 * Close the input side of the pipe. 1030 */ 1031 (void) close(fds[0]); 1032 1033 /* 1034 * Wait for the process to exit. 1035 */ 1036 while(((pid = wait(&status)) != cpid) && (pid >= 0)) 1037 continue; 1038 1039 if (cc == -1) 1040 *err = "Error reading shell's output for \"%s\""; 1041 1042 res = (char *)Buf_GetAll (buf, &cc); 1043 Buf_Destroy (buf, FALSE); 1044 1045 if (status) 1046 *err = "\"%s\" returned non-zero status"; 1047 1048 /* 1049 * Null-terminate the result, convert newlines to spaces and 1050 * install it in the variable. 1051 */ 1052 res[cc] = '\0'; 1053 cp = &res[cc] - 1; 1054 1055 if (*cp == '\n') { 1056 /* 1057 * A final newline is just stripped 1058 */ 1059 *cp-- = '\0'; 1060 } 1061 while (cp >= res) { 1062 if (*cp == '\n') { 1063 *cp = ' '; 1064 } 1065 cp--; 1066 } 1067 break; 1068 } 1069 return res; 1070bad: 1071 res = emalloc(1); 1072 *res = '\0'; 1073 return res; 1074} 1075 1076/*- 1077 * Error -- 1078 * Print an error message given its format. 1079 * 1080 * Results: 1081 * None. 1082 * 1083 * Side Effects: 1084 * The message is printed. 1085 */ 1086/* VARARGS */ 1087void 1088#ifdef __STDC__ 1089Error(char *fmt, ...) 1090#else 1091Error(va_alist) 1092 va_dcl 1093#endif 1094{ 1095 va_list ap; 1096#ifdef __STDC__ 1097 va_start(ap, fmt); 1098#else 1099 char *fmt; 1100 1101 va_start(ap); 1102 fmt = va_arg(ap, char *); 1103#endif 1104 (void)vfprintf(stderr, fmt, ap); 1105 va_end(ap); 1106 (void)fprintf(stderr, "\n"); 1107 (void)fflush(stderr); 1108} 1109 1110/*- 1111 * Fatal -- 1112 * Produce a Fatal error message. If jobs are running, waits for them 1113 * to finish. 1114 * 1115 * Results: 1116 * None 1117 * 1118 * Side Effects: 1119 * The program exits 1120 */ 1121/* VARARGS */ 1122void 1123#ifdef __STDC__ 1124Fatal(char *fmt, ...) 1125#else 1126Fatal(va_alist) 1127 va_dcl 1128#endif 1129{ 1130 va_list ap; 1131#ifdef __STDC__ 1132 va_start(ap, fmt); 1133#else 1134 char *fmt; 1135 1136 va_start(ap); 1137 fmt = va_arg(ap, char *); 1138#endif 1139 if (jobsRunning) 1140 Job_Wait(); 1141 1142 (void)vfprintf(stderr, fmt, ap); 1143 va_end(ap); 1144 (void)fprintf(stderr, "\n"); 1145 (void)fflush(stderr); 1146 1147 if (DEBUG(GRAPH2)) 1148 Targ_PrintGraph(2); 1149 exit(2); /* Not 1 so -q can distinguish error */ 1150} 1151 1152/* 1153 * Punt -- 1154 * Major exception once jobs are being created. Kills all jobs, prints 1155 * a message and exits. 1156 * 1157 * Results: 1158 * None 1159 * 1160 * Side Effects: 1161 * All children are killed indiscriminately and the program Lib_Exits 1162 */ 1163/* VARARGS */ 1164void 1165#ifdef __STDC__ 1166Punt(char *fmt, ...) 1167#else 1168Punt(va_alist) 1169 va_dcl 1170#endif 1171{ 1172 va_list ap; 1173#if __STDC__ 1174 va_start(ap, fmt); 1175#else 1176 char *fmt; 1177 1178 va_start(ap); 1179 fmt = va_arg(ap, char *); 1180#endif 1181 1182 (void)fprintf(stderr, "make: "); 1183 (void)vfprintf(stderr, fmt, ap); 1184 va_end(ap); 1185 (void)fprintf(stderr, "\n"); 1186 (void)fflush(stderr); 1187 1188 DieHorribly(); 1189} 1190 1191/*- 1192 * DieHorribly -- 1193 * Exit without giving a message. 1194 * 1195 * Results: 1196 * None 1197 * 1198 * Side Effects: 1199 * A big one... 1200 */ 1201void 1202DieHorribly() 1203{ 1204 if (jobsRunning) 1205 Job_AbortAll(); 1206 if (DEBUG(GRAPH2)) 1207 Targ_PrintGraph(2); 1208 exit(2); /* Not 1, so -q can distinguish error */ 1209} 1210 1211/* 1212 * Finish -- 1213 * Called when aborting due to errors in child shell to signal 1214 * abnormal exit. 1215 * 1216 * Results: 1217 * None 1218 * 1219 * Side Effects: 1220 * The program exits 1221 */ 1222void 1223Finish(errors) 1224 int errors; /* number of errors encountered in Make_Make */ 1225{ 1226 Fatal("%d error%s", errors, errors == 1 ? "" : "s"); 1227} 1228 1229/* 1230 * emalloc -- 1231 * malloc, but die on error. 1232 */ 1233void * 1234emalloc(len) 1235 size_t len; 1236{ 1237 void *p; 1238 1239 if ((p = malloc(len)) == NULL) 1240 enomem(); 1241 return(p); 1242} 1243 1244/* 1245 * estrdup -- 1246 * strdup, but die on error. 1247 */ 1248char * 1249estrdup(str) 1250 const char *str; 1251{ 1252 char *p; 1253 1254 if ((p = strdup(str)) == NULL) 1255 enomem(); 1256 return(p); 1257} 1258 1259/* 1260 * erealloc -- 1261 * realloc, but die on error. 1262 */ 1263void * 1264erealloc(ptr, size) 1265 void *ptr; 1266 size_t size; 1267{ 1268 if ((ptr = realloc(ptr, size)) == NULL) 1269 enomem(); 1270 return(ptr); 1271} 1272 1273/* 1274 * enomem -- 1275 * die when out of memory. 1276 */ 1277void 1278enomem() 1279{ 1280 err(2, NULL); 1281} 1282 1283/* 1284 * enunlink -- 1285 * Remove a file carefully, avoiding directories. 1286 */ 1287int 1288eunlink(file) 1289 const char *file; 1290{ 1291 struct stat st; 1292 1293 if (lstat(file, &st) == -1) 1294 return -1; 1295 1296 if (S_ISDIR(st.st_mode)) { 1297 errno = EISDIR; 1298 return -1; 1299 } 1300 return unlink(file); 1301} 1302 1303/* 1304 * usage -- 1305 * exit with usage message 1306 */ 1307static void 1308usage() 1309{ 1310 (void)fprintf(stderr, "%s\n%s\n%s\n", 1311"usage: make [-Beiknqrstv] [-D variable] [-d flags] [-E variable] [-f makefile]", 1312" [-I directory] [-j max_jobs] [-m directory] [-V variable]", 1313" [variable=value] [target ...]"); 1314 exit(2); 1315} 1316 1317 1318int 1319PrintAddr(a, b) 1320 ClientData a; 1321 ClientData b; 1322{ 1323 printf("%lx ", (unsigned long) a); 1324 return b ? 0 : 0; 1325} 1326