1/* $OpenBSD: main.c,v 1.133 2024/06/18 02:11:03 millert Exp $ */ 2/* $NetBSD: main.c,v 1.34 1997/03/24 20:56:36 gwr Exp $ */ 3 4/* 5 * Copyright (c) 1988, 1989, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * Copyright (c) 1989 by Berkeley Softworks 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * Adam de Boor. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 38#include <sys/param.h> /* MACHINE MACHINE_ARCH */ 39#include <sys/types.h> 40#include <sys/stat.h> 41#include <sys/utsname.h> 42#include <err.h> 43#include <errno.h> 44#include <stdio.h> 45#include <stdlib.h> 46#include <string.h> 47#include <unistd.h> 48#include "defines.h" 49#include "var.h" 50#include "lowparse.h" 51#include "parse.h" 52#include "parsevar.h" 53#include "dir.h" 54#include "direxpand.h" 55#include "error.h" 56#include "pathnames.h" 57#include "init.h" 58#include "job.h" 59#include "targ.h" 60#include "suff.h" 61#include "str.h" 62#include "main.h" 63#include "lst.h" 64#include "memory.h" 65#include "dump.h" 66#include "enginechoice.h" 67 68#define MAKEFLAGS ".MAKEFLAGS" 69 70static LIST to_create; /* Targets to be made */ 71Lst create = &to_create; 72bool allPrecious; /* .PRECIOUS given on line by itself */ 73 74static bool noBuiltins; /* -r flag */ 75static LIST makefiles; /* ordered list of makefiles to read */ 76static LIST varstoprint; /* list of variables to print */ 77static int optj; /* -j argument */ 78static bool compatMake; /* -B argument */ 79static bool forceJobs = false; 80int debug; /* -d flag */ 81bool noExecute; /* -n flag */ 82bool keepgoing; /* -k flag */ 83bool queryFlag; /* -q flag */ 84bool touchFlag; /* -t flag */ 85bool ignoreErrors; /* -i flag */ 86bool beSilent; /* -s flag */ 87bool dumpData; /* -p flag */ 88 89static LIST unreadable; 90 91struct dirs { 92 char *current; 93 char *object; 94}; 95 96static void MainParseArgs(int, char **); 97static void add_dirpath(Lst, const char *); 98static void usage(void); 99static void posixParseOptLetter(int); 100static void record_option(int, const char *); 101 102static char *figure_out_MACHINE(void); 103static char *figure_out_MACHINE_ARCH(void); 104static char *figure_out_MACHINE_CPU(void); 105 106static char *chdir_verify_path(const char *, struct dirs *); 107static char *figure_out_CURDIR(void); 108static void setup_CURDIR_OBJDIR(struct dirs *); 109 110static void setup_VPATH(void); 111 112static void read_all_make_rules(bool, bool, Lst, struct dirs *); 113static void read_makefile_list(Lst, struct dirs *); 114static bool ReadMakefile(void *, void *); 115 116static void 117record_option(int c, const char *arg) 118{ 119 char opt[3]; 120 121 opt[0] = '-'; 122 opt[1] = c; 123 opt[2] = '\0'; 124 Var_Append(MAKEFLAGS, opt); 125 if (arg != NULL) 126 Var_Append(MAKEFLAGS, arg); 127} 128 129void 130set_notparallel(void) 131{ 132 compatMake = true; 133} 134 135static void 136posixParseOptLetter(int c) 137{ 138 switch(c) { 139 case 'B': 140 compatMake = true; 141 return; /* XXX don't pass to submakes. */ 142 case 'S': 143 keepgoing = false; 144 break; 145 case 'e': 146 Var_setCheckEnvFirst(true); 147 break; 148 case 'i': 149 ignoreErrors = true; 150 break; 151 case 'k': 152 keepgoing = true; 153 break; 154 case 'n': 155 noExecute = true; 156 break; 157 case 'p': 158 dumpData = true; 159 break; 160 case 'q': 161 queryFlag = true; 162 /* Kind of nonsensical, wot? */ 163 break; 164 case 'r': 165 noBuiltins = true; 166 break; 167 case 's': 168 beSilent = true; 169 break; 170 case 't': 171 touchFlag = true; 172 break; 173 default: 174 usage(); 175 } 176 record_option(c, NULL); 177} 178 179/*- 180 * MainParseArgs -- 181 * Parse a given argument vector. Called from main() and from 182 * Main_ParseArgLine() when the .MAKEFLAGS target is used. 183 * 184 * XXX: Deal with command line overriding .MAKEFLAGS in makefile 185 * 186 * Side Effects: 187 * Various global and local flags will be set depending on the flags 188 * given 189 */ 190static void 191MainParseArgs(int argc, char **argv) 192{ 193 int c, optend; 194 195#define OPTFLAGS "BC:D:I:SV:d:ef:ij:km:npqrst" 196#define OPTLETTERS "BSiknpqrst" 197 198 if (pledge("stdio rpath wpath cpath fattr proc exec", NULL) == -1) 199 err(2, "pledge"); 200 201 optind = 1; /* since we're called more than once */ 202 optreset = 1; 203 optend = 0; 204 while (optind < argc) { 205 if (!optend && argv[optind][0] == '-') { 206 if (argv[optind][1] == '\0') 207 optind++; /* ignore "-" */ 208 else if (argv[optind][1] == '-' && 209 argv[optind][2] == '\0') { 210 optind++; /* ignore "--" */ 211 optend++; /* "--" denotes end of flags */ 212 } 213 } 214 c = optend ? -1 : getopt(argc, argv, OPTFLAGS); 215 switch (c) { 216 case 'C': 217 break; 218 case 'D': 219 Var_Set(optarg, "1"); 220 record_option(c, optarg); 221 break; 222 case 'I': 223 Parse_AddIncludeDir(optarg); 224 record_option(c, optarg); 225 break; 226 case 'V': 227 Lst_AtEnd(&varstoprint, optarg); 228 record_option(c, optarg); 229 break; 230 case 'd': { 231 char *modules = optarg; 232 233 for (; *modules; ++modules) 234 switch (*modules) { 235 case 'A': 236 debug = ~0; 237 break; 238 case 'a': 239 debug |= DEBUG_ARCH; 240 break; 241 case 'c': 242 debug |= DEBUG_COND; 243 break; 244 case 'd': 245 debug |= DEBUG_DIR; 246 break; 247 case 'D': 248 debug |= DEBUG_DOUBLE; 249 break; 250 case 'e': 251 debug |= DEBUG_EXPENSIVE; 252 break; 253 case 'f': 254 debug |= DEBUG_FOR; 255 break; 256 case 'g': 257 if (modules[1] == '1') { 258 debug |= DEBUG_GRAPH1; 259 ++modules; 260 } 261 else if (modules[1] == '2') { 262 debug |= DEBUG_GRAPH2; 263 ++modules; 264 } 265 break; 266 case 'h': 267 debug |= DEBUG_HELDJOBS; 268 break; 269 case 'j': 270 debug |= DEBUG_JOB | DEBUG_KILL; 271 break; 272 case 'J': 273 /* ignore */ 274 break; 275 case 'k': 276 debug |= DEBUG_KILL; 277 break; 278 case 'l': 279 debug |= DEBUG_LOUD; 280 break; 281 case 'm': 282 debug |= DEBUG_MAKE; 283 break; 284 case 'n': 285 debug |= DEBUG_NAME_MATCHING; 286 break; 287 case 'p': 288 debug |= DEBUG_PARALLEL; 289 break; 290 case 'q': 291 debug |= DEBUG_QUICKDEATH; 292 break; 293 case 's': 294 debug |= DEBUG_SUFF; 295 break; 296 case 't': 297 debug |= DEBUG_TARG; 298 break; 299 case 'T': 300 debug |= DEBUG_TARGGROUP; 301 break; 302 case 'v': 303 debug |= DEBUG_VAR; 304 break; 305 default: 306 (void)fprintf(stderr, 307 "make: illegal argument to -d option -- %c\n", 308 *modules); 309 usage(); 310 } 311 record_option(c, optarg); 312 break; 313 } 314 case 'f': 315 Lst_AtEnd(&makefiles, optarg); 316 break; 317 case 'j': { 318 const char *errstr; 319 320 forceJobs = true; 321 optj = strtonum(optarg, 1, INT_MAX, &errstr); 322 if (errstr != NULL) { 323 fprintf(stderr, 324 "make: illegal argument to -j option" 325 " -- %s -- %s\n", optarg, errstr); 326 usage(); 327 } 328 record_option(c, optarg); 329 break; 330 } 331 case 'm': 332 Dir_AddDir(systemIncludePath, optarg); 333 record_option(c, optarg); 334 break; 335 case -1: 336 /* Check for variable assignments and targets. */ 337 if (argv[optind] != NULL && 338 !Parse_CmdlineVar(argv[optind])) { 339 if (!*argv[optind]) 340 Punt("illegal (null) argument."); 341 Lst_AtEnd(create, estrdup(argv[optind])); 342 } 343 optind++; /* skip over non-option */ 344 break; 345 default: 346 posixParseOptLetter(c); 347 } 348 } 349} 350 351static void 352MainParseChdir(int argc, char **argv) 353{ 354 int c, optend, oldopterr; 355 356 optind = 1; /* since we're called more than once */ 357 optreset = 1; 358 optend = 0; 359 oldopterr = opterr; 360 opterr = 0; 361 while (optind < argc) { 362 if (!optend && argv[optind][0] == '-') { 363 if (argv[optind][1] == '\0') 364 optind++; /* ignore "-" */ 365 else if (argv[optind][1] == '-' && 366 argv[optind][2] == '\0') { 367 optind++; /* ignore "--" */ 368 optend++; /* "--" denotes end of flags */ 369 } 370 } 371 c = optend ? -1 : getopt(argc, argv, OPTFLAGS); 372 switch (c) { 373 case 'C': 374 if (chdir(optarg) == -1) 375 err(2, "chdir(%s)", optarg); 376 break; 377 case -1: 378 optind++; /* skip over non-option */ 379 break; 380 default: 381 break; 382 } 383 } 384 opterr = oldopterr; 385} 386 387/*- 388 * Main_ParseArgLine -- 389 * Used by the parse module when a .MFLAGS or .MAKEFLAGS target 390 * is encountered and by main() when reading the .MAKEFLAGS envariable. 391 * Takes a line of arguments and breaks it into its 392 * component words and passes those words and the number of them to the 393 * MainParseArgs function. 394 * The line should have all its leading whitespace removed. 395 * 396 * Side Effects: 397 * Only those that come from the various arguments. 398 */ 399void 400Main_ParseArgLine(const char *line) /* Line to fracture */ 401{ 402 char **argv; /* Manufactured argument vector */ 403 int argc; /* Number of arguments in argv */ 404 char *args; /* Space used by the args */ 405 char *buf; 406 char *argv0; 407 const char *s; 408 size_t len; 409 410 411 if (line == NULL) 412 return; 413 for (; *line == ' '; ++line) 414 continue; 415 if (!*line) 416 return; 417 418 /* POSIX rule: MAKEFLAGS can hold a set of option letters without 419 * any blanks or dashes. */ 420 for (s = line;; s++) { 421 if (*s == '\0') { 422 while (line != s) 423 posixParseOptLetter(*line++); 424 return; 425 } 426 if (strchr(OPTLETTERS, *s) == NULL) 427 break; 428 } 429 argv0 = Var_Value(".MAKE"); 430 len = strlen(line) + strlen(argv0) + 2; 431 buf = emalloc(len); 432 (void)snprintf(buf, len, "%s %s", argv0, line); 433 434 argv = brk_string(buf, &argc, &args); 435 free(buf); 436 MainParseArgs(argc, argv); 437 438 free(args); 439 free(argv); 440} 441 442/* Add a :-separated path to a Lst of directories. */ 443static void 444add_dirpath(Lst l, const char *n) 445{ 446 const char *start; 447 const char *cp; 448 449 for (start = n;;) { 450 for (cp = start; *cp != '\0' && *cp != ':';) 451 cp++; 452 Dir_AddDiri(l, start, cp); 453 if (*cp == '\0') 454 break; 455 else 456 start= cp+1; 457 } 458} 459 460/* 461 * Get the name of this type of MACHINE from utsname so we can share an 462 * executable for similar machines. (i.e. m68k: amiga hp300, mac68k, sun3, ...) 463 * 464 * Note that MACHINE, MACHINE_ARCH and MACHINE_CPU are decided at 465 * run-time. 466 */ 467static char * 468figure_out_MACHINE(void) 469{ 470 char *r = getenv("MACHINE"); 471 if (r == NULL) { 472 static struct utsname utsname; 473 474 if (uname(&utsname) == -1) 475 err(2, "uname"); 476 r = utsname.machine; 477 } 478 return r; 479} 480 481static char * 482figure_out_MACHINE_ARCH(void) 483{ 484 char *r = getenv("MACHINE_ARCH"); 485 if (r == NULL) { 486#ifndef MACHINE_ARCH 487 r = "unknown"; /* XXX: no uname -p yet */ 488#else 489 r = MACHINE_ARCH; 490#endif 491 } 492 return r; 493} 494static char * 495figure_out_MACHINE_CPU(void) 496{ 497 char *r = getenv("MACHINE_CPU"); 498 if (r == NULL) { 499#if !defined(MACHINE_CPU) && ! defined(MACHINE_ARCH) 500 r = "unknown"; /* XXX: no uname -p yet */ 501#else 502#if defined(MACHINE_CPU) 503 r = MACHINE_CPU; 504#else 505 r = MACHINE_ARCH; 506#endif 507#endif 508 } 509 return r; 510} 511 512static char * 513figure_out_CURDIR(void) 514{ 515 char *dir, *cwd; 516 struct stat sa, sb; 517 518 /* curdir is cwd... */ 519 cwd = getcwd(NULL, 0); 520 if (cwd == NULL) 521 err(2, "getcwd"); 522 523 if (stat(cwd, &sa) == -1) 524 err(2, "%s", cwd); 525 526 /* ...but we can use the alias $PWD if we can prove it is the same 527 * directory */ 528 if ((dir = getenv("PWD")) != NULL) { 529 if (stat(dir, &sb) == 0 && sa.st_ino == sb.st_ino && 530 sa.st_dev == sb.st_dev) { 531 free(cwd); 532 return estrdup(dir); 533 } 534 } 535 536 return cwd; 537} 538 539static char * 540chdir_verify_path(const char *path, struct dirs *d) 541{ 542 if (chdir(path) == 0) { 543 if (path[0] != '/') 544 return Str_concat(d->current, path, '/'); 545 else 546 return estrdup(path); 547 } 548 return NULL; 549} 550 551static void 552setup_CURDIR_OBJDIR(struct dirs *d) 553{ 554 char *path; 555 556 d->current = figure_out_CURDIR(); 557 /* 558 * If the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory 559 * exists, change into it and build there. 560 * 561 * Once things are initted, 562 * have to add the original directory to the search path, 563 * and modify the paths for the Makefiles appropriately. The 564 * current directory is also placed as a variable for make scripts. 565 */ 566 if ((path = getenv("MAKEOBJDIR")) == NULL) { 567 path = _PATH_OBJDIR; 568 } 569 d->object = chdir_verify_path(path, d); 570 if (d->object == NULL) 571 d->object = d->current; 572} 573 574/* 575 * if the VPATH variable is defined, add its contents to the search path. 576 * Uses the same format as the PATH env variable, i.e., 577 * <directory>:<directory>:<directory>... 578 */ 579static void 580setup_VPATH(void) 581{ 582 if (Var_Value("VPATH") != NULL) { 583 char *vpath; 584 585 vpath = Var_Subst("${VPATH}", NULL, false); 586 add_dirpath(defaultPath, vpath); 587 (void)free(vpath); 588 } 589} 590 591static void 592read_makefile_list(Lst mk, struct dirs *d) 593{ 594 LstNode ln; 595 ln = Lst_Find(mk, ReadMakefile, d); 596 if (ln != NULL) 597 Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); 598} 599 600static void 601read_all_make_rules(bool noBuiltins, bool read_depend, 602 Lst makefiles, struct dirs *d) 603{ 604 /* 605 * Read in the built-in rules first, followed by the specified 606 * makefile(s), or the default Makefile or makefile, in that order. 607 */ 608 if (!noBuiltins) { 609 LIST sysMkPath; /* Path of sys.mk */ 610 611 Lst_Init(&sysMkPath); 612 Dir_Expand(_PATH_DEFSYSMK, systemIncludePath, &sysMkPath); 613 if (Lst_IsEmpty(&sysMkPath)) 614 Fatal("make: no system rules (%s).", _PATH_DEFSYSMK); 615 616 read_makefile_list(&sysMkPath, d); 617 } 618 619 if (!Lst_IsEmpty(makefiles)) { 620 read_makefile_list(makefiles, d); 621 } else if (!ReadMakefile("makefile", d)) 622 (void)ReadMakefile("Makefile", d); 623 624 /* read a .depend file, if it exists, and we're not building depend */ 625 626 if (read_depend) 627 (void)ReadMakefile(".depend", d); 628 Parse_End(); 629} 630 631static void 632run_node(GNode *gn, bool *has_errors, bool *out_of_date) 633{ 634 LIST l; 635 636 Lst_Init(&l); 637 Lst_AtEnd(&l, gn); 638 engine_run_list(&l, has_errors, out_of_date); 639 Lst_Destroy(&l, NOFREE); 640} 641 642int main(int, char **); 643 644int 645main(int argc, char **argv) 646{ 647 static LIST targs; /* target nodes to create */ 648 bool outOfDate = false; /* false if all targets up to date */ 649 bool errored = false; /* true if errors occurred */ 650 char *machine = figure_out_MACHINE(); 651 char *machine_arch = figure_out_MACHINE_ARCH(); 652 char *machine_cpu = figure_out_MACHINE_CPU(); 653 const char *syspath = _PATH_DEFSYSPATH; 654 char *p; 655 static struct dirs d; 656 bool read_depend = true;/* false if we don't want to read .depend */ 657 658 MainParseChdir(argc, argv); 659 setup_CURDIR_OBJDIR(&d); 660 661 esetenv("PWD", d.object); 662 unsetenv("CDPATH"); 663 664 Static_Lst_Init(create); 665 Static_Lst_Init(&makefiles); 666 Static_Lst_Init(&varstoprint); 667 Static_Lst_Init(&targs); 668 Static_Lst_Init(&special); 669 670 beSilent = false; /* Print commands as executed */ 671 ignoreErrors = false; /* Pay attention to non-zero returns */ 672 noExecute = false; /* Execute all commands */ 673 keepgoing = false; /* Stop on error */ 674 allPrecious = false; /* Remove targets when interrupted */ 675 queryFlag = false; /* This is not just a check-run */ 676 noBuiltins = false; /* Read the built-in rules */ 677 touchFlag = false; /* Actually update targets */ 678 debug = 0; /* No debug verbosity, please. */ 679 680 optj = DEFMAXJOBS; 681 compatMake = false; /* No compat mode */ 682 683 684 /* 685 * Initialize all external modules. 686 */ 687 Init(); 688 689 if (d.object != d.current) 690 Dir_AddDir(defaultPath, d.current); 691 Var_Set(".CURDIR", d.current); 692 Var_Set(".OBJDIR", d.object); 693 Parse_setcurdir(d.current); 694 Targ_setdirs(d.current, d.object); 695 696 /* 697 * Initialize various variables. 698 * MAKE also gets this name, for compatibility 699 * .MAKEFLAGS gets set to the empty string just in case. 700 * MFLAGS also gets initialized empty, for compatibility. 701 */ 702 Var_Set("MAKE", argv[0]); 703 Var_Set(".MAKE", argv[0]); 704 Var_Set(MAKEFLAGS, ""); 705 Var_Set("MFLAGS", ""); 706 Var_Set("MACHINE", machine); 707 Var_Set("MACHINE_ARCH", machine_arch); 708 Var_Set("MACHINE_CPU", machine_cpu); 709 710 /* 711 * First snag any flags out of the MAKEFLAGS environment variable. 712 */ 713 Main_ParseArgLine(getenv("MAKEFLAGS")); 714 715 basedirectory = getenv("MAKEBASEDIRECTORY"); 716 if (basedirectory == NULL) 717 setenv("MAKEBASEDIRECTORY", d.current, 0); 718 719 MainParseArgs(argc, argv); 720 721 /* 722 * Be compatible if user did not specify -j 723 */ 724 if (!forceJobs) 725 compatMake = true; 726 727 /* And set up everything for sub-makes */ 728 Var_AddCmdline(MAKEFLAGS); 729 730 731 /* 732 * Set up the .TARGETS variable to contain the list of targets to be 733 * created. If none specified, make the variable empty -- the parser 734 * will fill the thing in with the default or .MAIN target. 735 */ 736 if (!Lst_IsEmpty(create)) { 737 LstNode ln; 738 739 for (ln = Lst_First(create); ln != NULL; ln = Lst_Adv(ln)) { 740 char *name = Lst_Datum(ln); 741 742 if (strcmp(name, "depend") == 0) 743 read_depend = false; 744 745 Var_Append(".TARGETS", name); 746 } 747 } else 748 Var_Set(".TARGETS", ""); 749 750 751 /* 752 * If no user-supplied system path was given (through the -m option) 753 * add the directories from the DEFSYSPATH (more than one may be given 754 * as dir1:...:dirn) to the system include path. 755 */ 756 if (Lst_IsEmpty(systemIncludePath)) 757 add_dirpath(systemIncludePath, syspath); 758 759 read_all_make_rules(noBuiltins, read_depend, &makefiles, &d); 760 761 if (compatMake) 762 optj = 1; 763 764 Var_Append("MFLAGS", Var_Value(MAKEFLAGS)); 765 766 /* Install all the flags into the MAKEFLAGS env variable. */ 767 if (((p = Var_Value(MAKEFLAGS)) != NULL) && *p) 768 esetenv("MAKEFLAGS", p); 769 770 setup_VPATH(); 771 772 process_suffixes_after_makefile_is_read(); 773 774 if (dumpData) { 775 dump_data(); 776 exit(0); 777 } 778 779 /* Print the initial graph, if the user requested it. */ 780 if (DEBUG(GRAPH1)) 781 dump_data(); 782 783 /* Print the values of any variables requested by the user. */ 784 if (!Lst_IsEmpty(&varstoprint)) { 785 LstNode ln; 786 787 for (ln = Lst_First(&varstoprint); ln != NULL; 788 ln = Lst_Adv(ln)) { 789 char *value = Var_Value(Lst_Datum(ln)); 790 791 printf("%s\n", value ? value : ""); 792 } 793 } else { 794 /* Have now read the entire graph and need to make a list 795 * of targets to create. If none was given on the command 796 * line, we consult the parsing module to find the main 797 * target(s) to create. */ 798 if (Lst_IsEmpty(create)) 799 Parse_MainName(&targs); 800 else 801 Targ_FindList(&targs, create); 802 803 choose_engine(compatMake); 804 Job_Init(optj); 805 if (!queryFlag && node_is_real(begin_node)) 806 run_node(begin_node, &errored, &outOfDate); 807 808 if (!errored) 809 engine_run_list(&targs, &errored, &outOfDate); 810 811 if (!queryFlag && !errored && node_is_real(end_node)) 812 run_node(end_node, &errored, &outOfDate); 813 } 814 815 /* print the graph now it's been processed if the user requested it */ 816 if (DEBUG(GRAPH2)) 817 post_mortem(); 818 819 /* Note that we only hit this code if -k is used, otherwise we 820 * exited early in case of errors. */ 821 if (errored) 822 Fatal("Errors while building"); 823 824 if (queryFlag && outOfDate) 825 return 1; 826 else 827 return 0; 828} 829 830struct unreadable { 831 char *fname; 832 int errcode; 833}; 834 835void 836dump_unreadable(void) 837{ 838 struct unreadable *u; 839 840 if (Lst_IsEmpty(&unreadable)) 841 return; 842 843 fprintf(stderr, "Makefile(s) that couldn't be read:\n"); 844 845 while ((u = Lst_Pop(&unreadable))) { 846 fprintf(stderr, "\t%s: %s\n", u->fname, strerror(u->errcode)); 847 free(u->fname); 848 free(u); 849 } 850} 851 852static FILE * 853open_makefile(const char *fname) 854{ 855 FILE *stream; 856 struct unreadable *u; 857 858 stream = fopen(fname, "r"); 859 if (stream != NULL) 860 return stream; 861 862 if (errno != ENOENT) { 863 u = emalloc(sizeof *u); 864 u->fname = estrdup(fname); 865 u->errcode = errno; 866 Lst_AtEnd(&unreadable, u); 867 } 868 869 return NULL; 870} 871 872/*- 873 * ReadMakefile -- 874 * Open and parse the given makefile. 875 * 876 * Results: 877 * true if ok. false if couldn't open file. 878 * 879 * Side Effects: 880 * lots 881 */ 882static bool 883ReadMakefile(void *p, void *q) 884{ 885 const char *fname = p; /* makefile to read */ 886 struct dirs *d = q; 887 FILE *stream; 888 char *name; 889 890 if (!strcmp(fname, "-")) { 891 Var_Set("MAKEFILE", ""); 892 Parse_File(estrdup("(stdin)"), stdin); 893 } else { 894 if ((stream = open_makefile(fname)) != NULL) 895 goto found; 896 /* if we've chdir'd, rebuild the path name */ 897 if (d->current != d->object && *fname != '/') { 898 char *path; 899 900 path = Str_concat(d->current, fname, '/'); 901 if ((stream = open_makefile(path)) == NULL) 902 free(path); 903 else { 904 fname = path; 905 goto found; 906 } 907 } 908 /* look in -I and system include directories. */ 909 name = Dir_FindFile(fname, userIncludePath); 910 if (!name) 911 name = Dir_FindFile(fname, systemIncludePath); 912 if (!name) 913 return false; 914 /* do not try to open a file we already have, so that 915 * dump_unreadable() yields non-confusing results. 916 */ 917 if (strcmp(name, fname) == 0) 918 return false; 919 if ((stream = open_makefile(name)) == NULL) 920 return false; 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 */ 927found: Var_Set("MAKEFILE", fname); 928 Parse_File(fname, stream); 929 } 930 return true; 931} 932 933 934/* 935 * usage -- 936 * exit with usage message 937 */ 938static void 939usage(void) 940{ 941 (void)fprintf(stderr, 942"usage: make [-BeiknpqrSst] [-C directory] [-D variable] [-d flags] [-f mk]\n\ 943 [-I directory] [-j max_jobs] [-m directory] [-V variable]\n\ 944 [NAME=value ...] [target ...]\n"); 945 exit(2); 946} 947 948 949