1 1.662 rillig /* $NetBSD: main.c,v 1.662 2025/08/09 23:13:28 rillig Exp $ */ 2 1.19 christos 3 1.1 cgd /* 4 1.31 christos * Copyright (c) 1988, 1989, 1990, 1993 5 1.31 christos * The Regents of the University of California. All rights reserved. 6 1.91 agc * 7 1.91 agc * This code is derived from software contributed to Berkeley by 8 1.91 agc * Adam de Boor. 9 1.91 agc * 10 1.91 agc * Redistribution and use in source and binary forms, with or without 11 1.91 agc * modification, are permitted provided that the following conditions 12 1.91 agc * are met: 13 1.91 agc * 1. Redistributions of source code must retain the above copyright 14 1.91 agc * notice, this list of conditions and the following disclaimer. 15 1.91 agc * 2. Redistributions in binary form must reproduce the above copyright 16 1.91 agc * notice, this list of conditions and the following disclaimer in the 17 1.91 agc * documentation and/or other materials provided with the distribution. 18 1.91 agc * 3. Neither the name of the University nor the names of its contributors 19 1.91 agc * may be used to endorse or promote products derived from this software 20 1.91 agc * without specific prior written permission. 21 1.91 agc * 22 1.91 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.91 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.91 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.91 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.91 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.91 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.91 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.91 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.91 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.91 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.91 agc * SUCH DAMAGE. 33 1.91 agc */ 34 1.91 agc 35 1.91 agc /* 36 1.1 cgd * Copyright (c) 1989 by Berkeley Softworks 37 1.1 cgd * All rights reserved. 38 1.1 cgd * 39 1.1 cgd * This code is derived from software contributed to Berkeley by 40 1.1 cgd * Adam de Boor. 41 1.1 cgd * 42 1.1 cgd * Redistribution and use in source and binary forms, with or without 43 1.1 cgd * modification, are permitted provided that the following conditions 44 1.1 cgd * are met: 45 1.1 cgd * 1. Redistributions of source code must retain the above copyright 46 1.1 cgd * notice, this list of conditions and the following disclaimer. 47 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 48 1.1 cgd * notice, this list of conditions and the following disclaimer in the 49 1.1 cgd * documentation and/or other materials provided with the distribution. 50 1.1 cgd * 3. All advertising materials mentioning features or use of this software 51 1.1 cgd * must display the following acknowledgement: 52 1.1 cgd * This product includes software developed by the University of 53 1.1 cgd * California, Berkeley and its contributors. 54 1.1 cgd * 4. Neither the name of the University nor the names of its contributors 55 1.1 cgd * may be used to endorse or promote products derived from this software 56 1.1 cgd * without specific prior written permission. 57 1.1 cgd * 58 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 1.1 cgd * SUCH DAMAGE. 69 1.1 cgd */ 70 1.1 cgd 71 1.507 rillig /* 72 1.507 rillig * The main file for this entire program. Exit routines etc. reside here. 73 1.1 cgd * 74 1.1 cgd * Utility functions defined in this file: 75 1.1 cgd * 76 1.521 rillig * Main_ParseArgLine 77 1.521 rillig * Parse and process command line arguments from a 78 1.521 rillig * single string. Used to implement the special targets 79 1.521 rillig * .MFLAGS and .MAKEFLAGS. 80 1.438 rillig * 81 1.521 rillig * Error Print a tagged error message. 82 1.438 rillig * 83 1.521 rillig * Fatal Print an error message and exit. 84 1.1 cgd * 85 1.521 rillig * Punt Abort all jobs and exit with a message. 86 1.1 cgd */ 87 1.1 cgd 88 1.13 cgd #include <sys/types.h> 89 1.13 cgd #include <sys/time.h> 90 1.1 cgd #include <sys/param.h> 91 1.13 cgd #include <sys/resource.h> 92 1.1 cgd #include <sys/stat.h> 93 1.225 matt #ifdef MAKE_NATIVE 94 1.225 matt #include <sys/sysctl.h> 95 1.225 matt #endif 96 1.17 gwr #include <sys/utsname.h> 97 1.29 christos #include <sys/wait.h> 98 1.85 wiz 99 1.1 cgd #include <errno.h> 100 1.215 christos #include <signal.h> 101 1.85 wiz #include <stdarg.h> 102 1.42 kleink #include <time.h> 103 1.85 wiz 104 1.1 cgd #include "make.h" 105 1.13 cgd #include "dir.h" 106 1.13 cgd #include "job.h" 107 1.642 rillig #ifdef USE_META 108 1.642 rillig # include "meta.h" 109 1.642 rillig #endif 110 1.1 cgd #include "pathnames.h" 111 1.58 sommerfe #include "trace.h" 112 1.1 cgd 113 1.337 rillig /* "@(#)main.c 8.3 (Berkeley) 3/19/94" */ 114 1.662 rillig MAKE_RCSID("$NetBSD: main.c,v 1.662 2025/08/09 23:13:28 rillig Exp $"); 115 1.603 rillig #if defined(MAKE_NATIVE) 116 1.369 rillig __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 " 117 1.369 rillig "The Regents of the University of California. " 118 1.369 rillig "All rights reserved."); 119 1.337 rillig #endif 120 1.337 rillig 121 1.391 rillig CmdOpts opts; 122 1.453 rillig time_t now; /* Time at start of make */ 123 1.459 rillig GNode *defaultNode; /* .DEFAULT node */ 124 1.602 rillig bool allPrecious; /* .PRECIOUS given on a line by itself */ 125 1.534 rillig bool deleteOnError; /* .DELETE_ON_ERROR: set */ 126 1.1 cgd 127 1.453 rillig static int maxJobTokens; /* -j argument */ 128 1.593 rillig static bool enterFlagObj; /* -w and objdir != srcdir */ 129 1.655 sjg static bool bogusJflag; /* -J invalid */ 130 1.391 rillig 131 1.646 rillig static int tokenPoolReader = -1, tokenPoolWriter = -1; 132 1.534 rillig bool doing_depend; /* Set while reading .depend */ 133 1.534 rillig static bool jobsRunning; /* true if the jobs might be running */ 134 1.453 rillig static const char *tracefile; 135 1.553 rillig static bool ReadMakefile(const char *); 136 1.469 rillig static void purge_relative_cached_realpaths(void); 137 1.453 rillig 138 1.547 rillig static bool ignorePWD; /* if we use -C, PWD is meaningless */ 139 1.453 rillig static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */ 140 1.453 rillig char curdir[MAXPATHLEN + 1]; /* Startup directory */ 141 1.497 rillig const char *progname; 142 1.176 sjg char *makeDependfile; 143 1.183 sjg pid_t myPid; 144 1.220 christos int makelevel; 145 1.1 cgd 146 1.534 rillig bool forceJobs = false; 147 1.481 rillig static int main_errors = 0; 148 1.469 rillig static HashTable cached_realpaths; 149 1.58 sommerfe 150 1.220 christos /* 151 1.220 christos * For compatibility with the POSIX version of MAKEFLAGS that includes 152 1.602 rillig * all the options without '-', convert 'flags' to '-f -l -a -g -s '. 153 1.220 christos */ 154 1.220 christos static char * 155 1.220 christos explode(const char *flags) 156 1.220 christos { 157 1.551 rillig char *exploded, *ep; 158 1.551 rillig const char *p; 159 1.453 rillig 160 1.453 rillig if (flags == NULL) 161 1.453 rillig return NULL; 162 1.453 rillig 163 1.551 rillig for (p = flags; *p != '\0'; p++) 164 1.551 rillig if (!ch_isalpha(*p)) 165 1.551 rillig return bmake_strdup(flags); 166 1.551 rillig 167 1.551 rillig exploded = bmake_malloc((size_t)(p - flags) * 3 + 1); 168 1.551 rillig for (p = flags, ep = exploded; *p != '\0'; p++) { 169 1.551 rillig *ep++ = '-'; 170 1.551 rillig *ep++ = *p; 171 1.551 rillig *ep++ = ' '; 172 1.453 rillig } 173 1.551 rillig *ep = '\0'; 174 1.551 rillig return exploded; 175 1.220 christos } 176 1.279 rillig 177 1.450 rillig MAKE_ATTR_DEAD static void 178 1.450 rillig usage(void) 179 1.450 rillig { 180 1.466 rillig size_t prognameLen = strcspn(progname, "["); 181 1.450 rillig 182 1.450 rillig (void)fprintf(stderr, 183 1.468 rillig "usage: %.*s [-BeikNnqrSstWwX]\n" 184 1.450 rillig " [-C directory] [-D variable] [-d flags] [-f makefile]\n" 185 1.450 rillig " [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n" 186 1.450 rillig " [-V variable] [-v variable] [variable=value] [target ...]\n", 187 1.466 rillig (int)prognameLen, progname); 188 1.450 rillig exit(2); 189 1.450 rillig } 190 1.450 rillig 191 1.133 dsl static void 192 1.522 rillig MainParseArgDebugFile(const char *arg) 193 1.344 rillig { 194 1.453 rillig const char *mode; 195 1.453 rillig size_t len; 196 1.453 rillig char *fname; 197 1.453 rillig 198 1.453 rillig if (opts.debug_file != stdout && opts.debug_file != stderr) 199 1.453 rillig fclose(opts.debug_file); 200 1.453 rillig 201 1.522 rillig if (*arg == '+') { 202 1.522 rillig arg++; 203 1.453 rillig mode = "a"; 204 1.453 rillig } else 205 1.453 rillig mode = "w"; 206 1.344 rillig 207 1.522 rillig if (strcmp(arg, "stdout") == 0) { 208 1.453 rillig opts.debug_file = stdout; 209 1.453 rillig return; 210 1.453 rillig } 211 1.522 rillig if (strcmp(arg, "stderr") == 0) { 212 1.453 rillig opts.debug_file = stderr; 213 1.453 rillig return; 214 1.453 rillig } 215 1.344 rillig 216 1.522 rillig len = strlen(arg); 217 1.453 rillig fname = bmake_malloc(len + 20); 218 1.522 rillig memcpy(fname, arg, len + 1); 219 1.453 rillig 220 1.555 rillig /* Replace the trailing '%d' after '.%d' with the pid. */ 221 1.555 rillig if (len >= 3 && memcmp(fname + len - 3, ".%d", 3) == 0) 222 1.453 rillig snprintf(fname + len - 2, 20, "%d", getpid()); 223 1.453 rillig 224 1.453 rillig opts.debug_file = fopen(fname, mode); 225 1.453 rillig if (opts.debug_file == NULL) { 226 1.608 rillig fprintf(stderr, "Cannot open debug file \"%s\"\n", fname); 227 1.554 rillig exit(2); 228 1.453 rillig } 229 1.453 rillig free(fname); 230 1.344 rillig } 231 1.344 rillig 232 1.344 rillig static void 233 1.522 rillig MainParseArgDebug(const char *argvalue) 234 1.133 dsl { 235 1.133 dsl const char *modules; 236 1.470 rillig DebugFlags debug = opts.debug; 237 1.133 dsl 238 1.523 rillig for (modules = argvalue; *modules != '\0'; modules++) { 239 1.133 dsl switch (*modules) { 240 1.369 rillig case '0': /* undocumented, only intended for tests */ 241 1.543 rillig memset(&debug, 0, sizeof(debug)); 242 1.369 rillig break; 243 1.133 dsl case 'A': 244 1.543 rillig memset(&debug, ~0, sizeof(debug)); 245 1.133 dsl break; 246 1.133 dsl case 'a': 247 1.543 rillig debug.DEBUG_ARCH = true; 248 1.133 dsl break; 249 1.155 christos case 'C': 250 1.543 rillig debug.DEBUG_CWD = true; 251 1.155 christos break; 252 1.133 dsl case 'c': 253 1.543 rillig debug.DEBUG_COND = true; 254 1.133 dsl break; 255 1.133 dsl case 'd': 256 1.543 rillig debug.DEBUG_DIR = true; 257 1.133 dsl break; 258 1.133 dsl case 'e': 259 1.543 rillig debug.DEBUG_ERROR = true; 260 1.133 dsl break; 261 1.133 dsl case 'f': 262 1.543 rillig debug.DEBUG_FOR = true; 263 1.133 dsl break; 264 1.133 dsl case 'g': 265 1.133 dsl if (modules[1] == '1') { 266 1.543 rillig debug.DEBUG_GRAPH1 = true; 267 1.475 rillig modules++; 268 1.444 rillig } else if (modules[1] == '2') { 269 1.543 rillig debug.DEBUG_GRAPH2 = true; 270 1.475 rillig modules++; 271 1.444 rillig } else if (modules[1] == '3') { 272 1.543 rillig debug.DEBUG_GRAPH3 = true; 273 1.475 rillig modules++; 274 1.133 dsl } 275 1.133 dsl break; 276 1.280 sjg case 'h': 277 1.543 rillig debug.DEBUG_HASH = true; 278 1.280 sjg break; 279 1.133 dsl case 'j': 280 1.543 rillig debug.DEBUG_JOB = true; 281 1.133 dsl break; 282 1.285 sjg case 'L': 283 1.534 rillig opts.strict = true; 284 1.285 sjg break; 285 1.146 sjg case 'l': 286 1.543 rillig debug.DEBUG_LOUD = true; 287 1.146 sjg break; 288 1.190 sjg case 'M': 289 1.543 rillig debug.DEBUG_META = true; 290 1.190 sjg break; 291 1.133 dsl case 'm': 292 1.543 rillig debug.DEBUG_MAKE = true; 293 1.133 dsl break; 294 1.133 dsl case 'n': 295 1.543 rillig debug.DEBUG_SCRIPT = true; 296 1.133 dsl break; 297 1.133 dsl case 'p': 298 1.543 rillig debug.DEBUG_PARSE = true; 299 1.133 dsl break; 300 1.133 dsl case 's': 301 1.543 rillig debug.DEBUG_SUFF = true; 302 1.133 dsl break; 303 1.133 dsl case 't': 304 1.543 rillig debug.DEBUG_TARG = true; 305 1.133 dsl break; 306 1.201 sjg case 'V': 307 1.534 rillig opts.debugVflag = true; 308 1.201 sjg break; 309 1.133 dsl case 'v': 310 1.543 rillig debug.DEBUG_VAR = true; 311 1.133 dsl break; 312 1.133 dsl case 'x': 313 1.543 rillig debug.DEBUG_SHELL = true; 314 1.133 dsl break; 315 1.133 dsl case 'F': 316 1.522 rillig MainParseArgDebugFile(modules + 1); 317 1.579 rillig goto finish; 318 1.133 dsl default: 319 1.133 dsl (void)fprintf(stderr, 320 1.133 dsl "%s: illegal argument to d option -- %c\n", 321 1.133 dsl progname, *modules); 322 1.133 dsl usage(); 323 1.133 dsl } 324 1.133 dsl } 325 1.471 rillig 326 1.579 rillig finish: 327 1.470 rillig opts.debug = debug; 328 1.453 rillig 329 1.391 rillig setvbuf(opts.debug_file, NULL, _IONBF, 0); 330 1.579 rillig if (opts.debug_file != stdout) 331 1.153 apb setvbuf(stdout, NULL, _IOLBF, 0); 332 1.133 dsl } 333 1.133 dsl 334 1.579 rillig /* Is path relative or does it contain any relative component "." or ".."? */ 335 1.534 rillig static bool 336 1.522 rillig IsRelativePath(const char *path) 337 1.264 sjg { 338 1.540 rillig const char *p; 339 1.264 sjg 340 1.264 sjg if (path[0] != '/') 341 1.534 rillig return true; 342 1.540 rillig p = path; 343 1.540 rillig while ((p = strstr(p, "/.")) != NULL) { 344 1.540 rillig p += 2; 345 1.540 rillig if (*p == '.') 346 1.540 rillig p++; 347 1.540 rillig if (*p == '/' || *p == '\0') 348 1.534 rillig return true; 349 1.286 rillig } 350 1.534 rillig return false; 351 1.264 sjg } 352 1.264 sjg 353 1.355 rillig static void 354 1.355 rillig MainParseArgChdir(const char *argvalue) 355 1.355 rillig { 356 1.355 rillig struct stat sa, sb; 357 1.355 rillig 358 1.355 rillig if (chdir(argvalue) == -1) { 359 1.355 rillig (void)fprintf(stderr, "%s: chdir %s: %s\n", 360 1.355 rillig progname, argvalue, strerror(errno)); 361 1.505 rillig exit(2); /* Not 1 so -q can distinguish error */ 362 1.355 rillig } 363 1.355 rillig if (getcwd(curdir, MAXPATHLEN) == NULL) { 364 1.657 rillig (void)fprintf(stderr, "%s: getcwd: %s\n", 365 1.657 rillig progname, strerror(errno)); 366 1.355 rillig exit(2); 367 1.355 rillig } 368 1.522 rillig if (!IsRelativePath(argvalue) && 369 1.355 rillig stat(argvalue, &sa) != -1 && 370 1.355 rillig stat(curdir, &sb) != -1 && 371 1.355 rillig sa.st_ino == sb.st_ino && 372 1.355 rillig sa.st_dev == sb.st_dev) 373 1.622 rillig snprintf(curdir, MAXPATHLEN, "%s", argvalue); 374 1.534 rillig ignorePWD = true; 375 1.355 rillig } 376 1.355 rillig 377 1.356 rillig static void 378 1.356 rillig MainParseArgJobsInternal(const char *argvalue) 379 1.356 rillig { 380 1.440 rillig char end; 381 1.646 rillig if (sscanf(argvalue, "%d,%d%c", 382 1.646 rillig &tokenPoolReader, &tokenPoolWriter, &end) != 2) { 383 1.356 rillig (void)fprintf(stderr, 384 1.652 rillig "%s: error: invalid internal option " 385 1.652 rillig "\"-J %s\" in \"%s\"\n", 386 1.652 rillig progname, argvalue, curdir); 387 1.647 rillig exit(2); 388 1.356 rillig } 389 1.662 rillig if (fcntl(tokenPoolReader, F_GETFD, 0) < 0 || 390 1.662 rillig fcntl(tokenPoolWriter, F_GETFD, 0) < 0) { 391 1.646 rillig tokenPoolReader = -1; 392 1.646 rillig tokenPoolWriter = -1; 393 1.655 sjg bogusJflag = true; 394 1.356 rillig } else { 395 1.529 rillig Global_Append(MAKEFLAGS, "-J"); 396 1.529 rillig Global_Append(MAKEFLAGS, argvalue); 397 1.356 rillig } 398 1.356 rillig } 399 1.356 rillig 400 1.356 rillig static void 401 1.597 rillig MainParseArgJobs(const char *arg) 402 1.356 rillig { 403 1.597 rillig const char *p; 404 1.597 rillig char *end; 405 1.594 sjg char v[12]; 406 1.356 rillig 407 1.534 rillig forceJobs = true; 408 1.597 rillig opts.maxJobs = (int)strtol(arg, &end, 0); 409 1.600 rillig p = end; 410 1.594 sjg #ifdef _SC_NPROCESSORS_ONLN 411 1.594 sjg if (*p != '\0') { 412 1.594 sjg double d; 413 1.594 sjg 414 1.608 rillig if (*p == 'C') 415 1.594 sjg d = (opts.maxJobs > 0) ? opts.maxJobs : 1; 416 1.608 rillig else if (*p == '.') { 417 1.597 rillig d = strtod(arg, &end); 418 1.600 rillig p = end; 419 1.594 sjg } else 420 1.600 rillig d = 0.0; 421 1.600 rillig if (d > 0.0) { 422 1.597 rillig p = ""; 423 1.595 mrg opts.maxJobs = (int)sysconf(_SC_NPROCESSORS_ONLN); 424 1.594 sjg opts.maxJobs = (int)(d * (double)opts.maxJobs); 425 1.594 sjg } 426 1.594 sjg } 427 1.594 sjg #endif 428 1.391 rillig if (*p != '\0' || opts.maxJobs < 1) { 429 1.356 rillig (void)fprintf(stderr, 430 1.598 rillig "%s: argument '%s' to option '-j' " 431 1.598 rillig "must be a positive number\n", 432 1.598 rillig progname, arg); 433 1.505 rillig exit(2); /* Not 1 so -q can distinguish error */ 434 1.356 rillig } 435 1.594 sjg snprintf(v, sizeof(v), "%d", opts.maxJobs); 436 1.529 rillig Global_Append(MAKEFLAGS, "-j"); 437 1.594 sjg Global_Append(MAKEFLAGS, v); 438 1.594 sjg Global_Set(".MAKE.JOBS", v); 439 1.391 rillig maxJobTokens = opts.maxJobs; 440 1.356 rillig } 441 1.356 rillig 442 1.357 rillig static void 443 1.357 rillig MainParseArgSysInc(const char *argvalue) 444 1.357 rillig { 445 1.603 rillig if (strncmp(argvalue, ".../", 4) == 0) { 446 1.371 rillig char *found_path = Dir_FindHereOrAbove(curdir, argvalue + 4); 447 1.371 rillig if (found_path == NULL) 448 1.357 rillig return; 449 1.516 rillig (void)SearchPath_Add(sysIncPath, found_path); 450 1.371 rillig free(found_path); 451 1.357 rillig } else { 452 1.516 rillig (void)SearchPath_Add(sysIncPath, argvalue); 453 1.357 rillig } 454 1.529 rillig Global_Append(MAKEFLAGS, "-m"); 455 1.529 rillig Global_Append(MAKEFLAGS, argvalue); 456 1.588 sjg Dir_SetSYSPATH(); 457 1.357 rillig } 458 1.357 rillig 459 1.534 rillig static bool 460 1.592 rillig MainParseOption(char c, const char *argvalue) 461 1.354 rillig { 462 1.354 rillig switch (c) { 463 1.354 rillig case '\0': 464 1.354 rillig break; 465 1.354 rillig case 'B': 466 1.534 rillig opts.compatMake = true; 467 1.529 rillig Global_Append(MAKEFLAGS, "-B"); 468 1.591 rillig Global_Set(".MAKE.MODE", "compat"); 469 1.354 rillig break; 470 1.354 rillig case 'C': 471 1.355 rillig MainParseArgChdir(argvalue); 472 1.354 rillig break; 473 1.354 rillig case 'D': 474 1.546 rillig if (argvalue[0] == '\0') 475 1.546 rillig return false; 476 1.571 rillig Var_SetExpand(SCOPE_GLOBAL, argvalue, "1"); 477 1.529 rillig Global_Append(MAKEFLAGS, "-D"); 478 1.529 rillig Global_Append(MAKEFLAGS, argvalue); 479 1.354 rillig break; 480 1.354 rillig case 'I': 481 1.601 rillig SearchPath_Add(parseIncPath, argvalue); 482 1.529 rillig Global_Append(MAKEFLAGS, "-I"); 483 1.529 rillig Global_Append(MAKEFLAGS, argvalue); 484 1.354 rillig break; 485 1.354 rillig case 'J': 486 1.356 rillig MainParseArgJobsInternal(argvalue); 487 1.354 rillig break; 488 1.354 rillig case 'N': 489 1.534 rillig opts.noExecute = true; 490 1.534 rillig opts.noRecursiveExecute = true; 491 1.529 rillig Global_Append(MAKEFLAGS, "-N"); 492 1.354 rillig break; 493 1.354 rillig case 'S': 494 1.534 rillig opts.keepgoing = false; 495 1.529 rillig Global_Append(MAKEFLAGS, "-S"); 496 1.354 rillig break; 497 1.354 rillig case 'T': 498 1.354 rillig tracefile = bmake_strdup(argvalue); 499 1.529 rillig Global_Append(MAKEFLAGS, "-T"); 500 1.529 rillig Global_Append(MAKEFLAGS, argvalue); 501 1.354 rillig break; 502 1.354 rillig case 'V': 503 1.354 rillig case 'v': 504 1.437 rillig opts.printVars = c == 'v' ? PVM_EXPANDED : PVM_UNEXPANDED; 505 1.485 rillig Lst_Append(&opts.variables, bmake_strdup(argvalue)); 506 1.391 rillig /* XXX: Why always -V? */ 507 1.529 rillig Global_Append(MAKEFLAGS, "-V"); 508 1.529 rillig Global_Append(MAKEFLAGS, argvalue); 509 1.354 rillig break; 510 1.354 rillig case 'W': 511 1.534 rillig opts.parseWarnFatal = true; 512 1.550 rillig /* XXX: why no Global_Append? */ 513 1.354 rillig break; 514 1.354 rillig case 'X': 515 1.534 rillig opts.varNoExportEnv = true; 516 1.529 rillig Global_Append(MAKEFLAGS, "-X"); 517 1.354 rillig break; 518 1.354 rillig case 'd': 519 1.354 rillig /* If '-d-opts' don't pass to children */ 520 1.354 rillig if (argvalue[0] == '-') 521 1.354 rillig argvalue++; 522 1.354 rillig else { 523 1.529 rillig Global_Append(MAKEFLAGS, "-d"); 524 1.529 rillig Global_Append(MAKEFLAGS, argvalue); 525 1.354 rillig } 526 1.522 rillig MainParseArgDebug(argvalue); 527 1.354 rillig break; 528 1.354 rillig case 'e': 529 1.534 rillig opts.checkEnvFirst = true; 530 1.529 rillig Global_Append(MAKEFLAGS, "-e"); 531 1.354 rillig break; 532 1.354 rillig case 'f': 533 1.484 rillig Lst_Append(&opts.makefiles, bmake_strdup(argvalue)); 534 1.354 rillig break; 535 1.354 rillig case 'i': 536 1.534 rillig opts.ignoreErrors = true; 537 1.529 rillig Global_Append(MAKEFLAGS, "-i"); 538 1.354 rillig break; 539 1.354 rillig case 'j': 540 1.356 rillig MainParseArgJobs(argvalue); 541 1.354 rillig break; 542 1.354 rillig case 'k': 543 1.534 rillig opts.keepgoing = true; 544 1.529 rillig Global_Append(MAKEFLAGS, "-k"); 545 1.354 rillig break; 546 1.354 rillig case 'm': 547 1.357 rillig MainParseArgSysInc(argvalue); 548 1.441 rillig /* XXX: why no Var_Append? */ 549 1.354 rillig break; 550 1.354 rillig case 'n': 551 1.534 rillig opts.noExecute = true; 552 1.529 rillig Global_Append(MAKEFLAGS, "-n"); 553 1.354 rillig break; 554 1.354 rillig case 'q': 555 1.549 rillig opts.query = true; 556 1.354 rillig /* Kind of nonsensical, wot? */ 557 1.529 rillig Global_Append(MAKEFLAGS, "-q"); 558 1.354 rillig break; 559 1.354 rillig case 'r': 560 1.534 rillig opts.noBuiltins = true; 561 1.529 rillig Global_Append(MAKEFLAGS, "-r"); 562 1.354 rillig break; 563 1.354 rillig case 's': 564 1.549 rillig opts.silent = true; 565 1.529 rillig Global_Append(MAKEFLAGS, "-s"); 566 1.354 rillig break; 567 1.354 rillig case 't': 568 1.549 rillig opts.touch = true; 569 1.529 rillig Global_Append(MAKEFLAGS, "-t"); 570 1.354 rillig break; 571 1.354 rillig case 'w': 572 1.534 rillig opts.enterFlag = true; 573 1.529 rillig Global_Append(MAKEFLAGS, "-w"); 574 1.354 rillig break; 575 1.354 rillig default: 576 1.354 rillig usage(); 577 1.354 rillig } 578 1.534 rillig return true; 579 1.354 rillig } 580 1.354 rillig 581 1.507 rillig /* 582 1.507 rillig * Parse the given arguments. Called from main() and from 583 1.345 rillig * Main_ParseArgLine() when the .MAKEFLAGS target is used. 584 1.1 cgd * 585 1.345 rillig * The arguments must be treated as read-only and will be freed after the 586 1.345 rillig * call. 587 1.1 cgd * 588 1.507 rillig * XXX: Deal with command line overriding .MAKEFLAGS in makefile 589 1.507 rillig */ 590 1.1 cgd static void 591 1.149 christos MainParseArgs(int argc, char **argv) 592 1.1 cgd { 593 1.360 rillig char c; 594 1.98 ross int arginc; 595 1.133 dsl char *argvalue; 596 1.98 ross char *optscan; 597 1.534 rillig bool inOption, dashDash = false; 598 1.1 cgd 599 1.359 rillig const char *optspecs = "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrstv:w"; 600 1.662 rillig /* Can't actually use getopt(3) because rescanning is not portable */ 601 1.98 ross 602 1.279 rillig rearg: 603 1.534 rillig inOption = false; 604 1.108 lukem optscan = NULL; 605 1.358 rillig while (argc > 1) { 606 1.359 rillig const char *optspec; 607 1.358 rillig if (!inOption) 608 1.98 ross optscan = argv[1]; 609 1.98 ross c = *optscan++; 610 1.98 ross arginc = 0; 611 1.358 rillig if (inOption) { 612 1.358 rillig if (c == '\0') { 613 1.475 rillig argv++; 614 1.475 rillig argc--; 615 1.534 rillig inOption = false; 616 1.98 ross continue; 617 1.98 ross } 618 1.98 ross } else { 619 1.101 ross if (c != '-' || dashDash) 620 1.98 ross break; 621 1.534 rillig inOption = true; 622 1.98 ross c = *optscan++; 623 1.98 ross } 624 1.98 ross /* '-' found at some earlier point */ 625 1.359 rillig optspec = strchr(optspecs, c); 626 1.359 rillig if (c != '\0' && optspec != NULL && optspec[1] == ':') { 627 1.547 rillig /* 628 1.547 rillig * -<something> found, and <something> should have an 629 1.547 rillig * argument 630 1.547 rillig */ 631 1.534 rillig inOption = false; 632 1.98 ross arginc = 1; 633 1.98 ross argvalue = optscan; 634 1.358 rillig if (*argvalue == '\0') { 635 1.122 christos if (argc < 3) 636 1.122 christos goto noarg; 637 1.98 ross argvalue = argv[2]; 638 1.98 ross arginc = 2; 639 1.98 ross } 640 1.108 lukem } else { 641 1.279 rillig argvalue = NULL; 642 1.98 ross } 643 1.354 rillig switch (c) { 644 1.98 ross case '\0': 645 1.358 rillig arginc = 1; 646 1.534 rillig inOption = false; 647 1.358 rillig break; 648 1.101 ross case '-': 649 1.534 rillig dashDash = true; 650 1.358 rillig break; 651 1.1 cgd default: 652 1.592 rillig if (!MainParseOption(c, argvalue)) 653 1.358 rillig goto noarg; 654 1.1 cgd } 655 1.98 ross argv += arginc; 656 1.98 ross argc -= arginc; 657 1.1 cgd } 658 1.1 cgd 659 1.1 cgd /* 660 1.1 cgd * See if the rest of the arguments are variable assignments and 661 1.1 cgd * perform them if so. Else take them to be targets and stuff them 662 1.1 cgd * on the end of the "create" list. 663 1.1 cgd */ 664 1.523 rillig for (; argc > 1; argv++, argc--) { 665 1.563 rillig if (!Parse_VarAssign(argv[1], false, SCOPE_CMDLINE)) { 666 1.460 rillig if (argv[1][0] == '\0') 667 1.1 cgd Punt("illegal (null) argument."); 668 1.460 rillig if (argv[1][0] == '-' && !dashDash) 669 1.1 cgd goto rearg; 670 1.486 rillig Lst_Append(&opts.create, bmake_strdup(argv[1])); 671 1.1 cgd } 672 1.369 rillig } 673 1.122 christos 674 1.122 christos return; 675 1.122 christos noarg: 676 1.122 christos (void)fprintf(stderr, "%s: option requires an argument -- %c\n", 677 1.122 christos progname, c); 678 1.122 christos usage(); 679 1.1 cgd } 680 1.1 cgd 681 1.507 rillig /* 682 1.507 rillig * Break a line of arguments into words and parse them. 683 1.85 wiz * 684 1.361 rillig * Used when a .MFLAGS or .MAKEFLAGS target is encountered during parsing and 685 1.507 rillig * by main() when reading the MAKEFLAGS environment variable. 686 1.507 rillig */ 687 1.1 cgd void 688 1.161 dsl Main_ParseArgLine(const char *line) 689 1.1 cgd { 690 1.331 rillig Words words; 691 1.296 rillig char *buf; 692 1.603 rillig const char *p; 693 1.1 cgd 694 1.1 cgd if (line == NULL) 695 1.1 cgd return; 696 1.603 rillig for (p = line; *p == ' '; p++) 697 1.13 cgd continue; 698 1.603 rillig if (p[0] == '\0') 699 1.1 cgd return; 700 1.1 cgd 701 1.442 rillig { 702 1.532 rillig FStr argv0 = Var_Value(SCOPE_GLOBAL, ".MAKE"); 703 1.603 rillig buf = str_concat3(argv0.str, " ", p); 704 1.499 rillig FStr_Done(&argv0); 705 1.442 rillig } 706 1.40 christos 707 1.534 rillig words = Str_Words(buf, true); 708 1.331 rillig if (words.words == NULL) { 709 1.159 christos Error("Unterminated quoted string [%s]", buf); 710 1.159 christos free(buf); 711 1.159 christos return; 712 1.159 christos } 713 1.45 itohy free(buf); 714 1.654 rillig EvalStack_PushMakeflags(line); 715 1.331 rillig MainParseArgs((int)words.len, words.words); 716 1.654 rillig EvalStack_Pop(); 717 1.40 christos 718 1.331 rillig Words_Free(words); 719 1.1 cgd } 720 1.1 cgd 721 1.534 rillig bool 722 1.534 rillig Main_SetObjdir(bool writable, const char *fmt, ...) 723 1.31 christos { 724 1.31 christos struct stat sb; 725 1.260 christos char *path; 726 1.260 christos char buf[MAXPATHLEN + 1]; 727 1.265 sjg char buf2[MAXPATHLEN + 1]; 728 1.252 christos va_list ap; 729 1.252 christos 730 1.252 christos va_start(ap, fmt); 731 1.260 christos vsnprintf(path = buf, MAXPATHLEN, fmt, ap); 732 1.252 christos va_end(ap); 733 1.31 christos 734 1.74 tv if (path[0] != '/') { 735 1.583 sjg if (snprintf(buf2, MAXPATHLEN, "%s/%s", curdir, path) <= MAXPATHLEN) 736 1.583 sjg path = buf2; 737 1.583 sjg else 738 1.583 sjg return false; 739 1.74 tv } 740 1.74 tv 741 1.74 tv /* look for the directory and try to chdir there */ 742 1.564 rillig if (stat(path, &sb) != 0 || !S_ISDIR(sb.st_mode)) 743 1.564 rillig return false; 744 1.564 rillig 745 1.564 rillig if ((writable && access(path, W_OK) != 0) || chdir(path) != 0) { 746 1.657 rillig (void)fprintf(stderr, "%s: warning: %s: %s\n", 747 1.564 rillig progname, path, strerror(errno)); 748 1.618 sjg /* Allow debugging how we got here - not always obvious */ 749 1.618 sjg if (GetBooleanExpr("${MAKE_DEBUG_OBJDIR_CHECK_WRITABLE}", 750 1.618 sjg false)) 751 1.618 sjg PrintOnError(NULL, ""); 752 1.564 rillig return false; 753 1.31 christos } 754 1.31 christos 755 1.564 rillig snprintf(objdir, sizeof objdir, "%s", path); 756 1.564 rillig Global_Set(".OBJDIR", objdir); 757 1.564 rillig setenv("PWD", objdir, 1); 758 1.564 rillig Dir_InitDot(); 759 1.564 rillig purge_relative_cached_realpaths(); 760 1.564 rillig if (opts.enterFlag && strcmp(objdir, curdir) != 0) 761 1.564 rillig enterFlagObj = true; 762 1.564 rillig return true; 763 1.31 christos } 764 1.31 christos 765 1.534 rillig static bool 766 1.534 rillig SetVarObjdir(bool writable, const char *var, const char *suffix) 767 1.252 christos { 768 1.532 rillig FStr path = Var_Value(SCOPE_CMDLINE, var); 769 1.296 rillig 770 1.499 rillig if (path.str == NULL || path.str[0] == '\0') { 771 1.499 rillig FStr_Done(&path); 772 1.534 rillig return false; 773 1.288 rillig } 774 1.252 christos 775 1.624 rillig Var_Expand(&path, SCOPE_GLOBAL, VARE_EVAL); 776 1.260 christos 777 1.556 rillig (void)Main_SetObjdir(writable, "%s%s", path.str, suffix); 778 1.260 christos 779 1.499 rillig FStr_Done(&path); 780 1.534 rillig return true; 781 1.252 christos } 782 1.252 christos 783 1.507 rillig /* 784 1.605 rillig * Splits str into words (in-place, modifying it), adding them to the list. 785 1.507 rillig * The string must be kept alive as long as the list. 786 1.507 rillig */ 787 1.605 rillig void 788 1.605 rillig AppendWords(StringList *lp, char *str) 789 1.176 sjg { 790 1.604 rillig char *p; 791 1.462 rillig const char *sep = " \t"; 792 1.176 sjg 793 1.605 rillig for (p = strtok(str, sep); p != NULL; p = strtok(NULL, sep)) 794 1.604 rillig Lst_Append(lp, p); 795 1.176 sjg } 796 1.176 sjg 797 1.167 christos #ifdef SIGINFO 798 1.167 christos static void 799 1.200 joerg siginfo(int signo MAKE_ATTR_UNUSED) 800 1.167 christos { 801 1.167 christos char dir[MAXPATHLEN]; 802 1.167 christos char str[2 * MAXPATHLEN]; 803 1.167 christos int len; 804 1.426 rillig if (getcwd(dir, sizeof dir) == NULL) 805 1.167 christos return; 806 1.426 rillig len = snprintf(str, sizeof str, "%s: Working in: %s\n", progname, dir); 807 1.167 christos if (len > 0) 808 1.167 christos (void)write(STDERR_FILENO, str, (size_t)len); 809 1.167 christos } 810 1.167 christos #endif 811 1.167 christos 812 1.500 rillig /* Allow makefiles some control over the mode we run in. */ 813 1.500 rillig static void 814 1.500 rillig MakeMode(void) 815 1.176 sjg { 816 1.624 rillig char *mode = Var_Subst("${.MAKE.MODE:tl}", SCOPE_GLOBAL, VARE_EVAL); 817 1.524 rillig /* TODO: handle errors */ 818 1.176 sjg 819 1.524 rillig if (mode[0] != '\0') { 820 1.524 rillig if (strstr(mode, "compat") != NULL) { 821 1.534 rillig opts.compatMake = true; 822 1.534 rillig forceJobs = false; 823 1.453 rillig } 824 1.190 sjg #if USE_META 825 1.524 rillig if (strstr(mode, "meta") != NULL) 826 1.524 rillig meta_mode_init(mode); 827 1.190 sjg #endif 828 1.582 rillig if (strstr(mode, "randomize-targets") != NULL) 829 1.582 rillig opts.randomizeTargets = true; 830 1.453 rillig } 831 1.238 christos 832 1.524 rillig free(mode); 833 1.176 sjg } 834 1.176 sjg 835 1.266 christos static void 836 1.649 rillig PrintVariable(const char *varname, bool expandVars) 837 1.383 rillig { 838 1.508 rillig if (strchr(varname, '$') != NULL) { 839 1.624 rillig char *evalue = Var_Subst(varname, SCOPE_GLOBAL, VARE_EVAL); 840 1.383 rillig /* TODO: handle errors */ 841 1.384 rillig printf("%s\n", evalue); 842 1.545 rillig free(evalue); 843 1.384 rillig 844 1.383 rillig } else if (expandVars) { 845 1.383 rillig char *expr = str_concat3("${", varname, "}"); 846 1.624 rillig char *evalue = Var_Subst(expr, SCOPE_GLOBAL, VARE_EVAL); 847 1.383 rillig /* TODO: handle errors */ 848 1.383 rillig free(expr); 849 1.384 rillig printf("%s\n", evalue); 850 1.545 rillig free(evalue); 851 1.384 rillig 852 1.383 rillig } else { 853 1.532 rillig FStr value = Var_Value(SCOPE_GLOBAL, varname); 854 1.499 rillig printf("%s\n", value.str != NULL ? value.str : ""); 855 1.499 rillig FStr_Done(&value); 856 1.383 rillig } 857 1.383 rillig } 858 1.383 rillig 859 1.432 rillig /* 860 1.534 rillig * Return a bool based on a variable. 861 1.432 rillig * 862 1.432 rillig * If the knob is not set, return the fallback. 863 1.432 rillig * If set, anything that looks or smells like "No", "False", "Off", "0", etc. 864 1.534 rillig * is false, otherwise true. 865 1.432 rillig */ 866 1.576 sjg bool 867 1.538 rillig GetBooleanExpr(const char *expr, bool fallback) 868 1.432 rillig { 869 1.453 rillig char *value; 870 1.534 rillig bool res; 871 1.453 rillig 872 1.624 rillig value = Var_Subst(expr, SCOPE_GLOBAL, VARE_EVAL); 873 1.453 rillig /* TODO: handle errors */ 874 1.453 rillig res = ParseBoolean(value, fallback); 875 1.453 rillig free(value); 876 1.453 rillig return res; 877 1.432 rillig } 878 1.432 rillig 879 1.383 rillig static void 880 1.649 rillig PrintVariables(void) 881 1.266 christos { 882 1.338 rillig StringListNode *ln; 883 1.534 rillig bool expandVars; 884 1.266 christos 885 1.437 rillig if (opts.printVars == PVM_EXPANDED) 886 1.534 rillig expandVars = true; 887 1.394 rillig else if (opts.debugVflag) 888 1.534 rillig expandVars = false; 889 1.266 christos else 890 1.538 rillig expandVars = GetBooleanExpr("${.MAKE.EXPAND_VARIABLES}", 891 1.538 rillig false); 892 1.266 christos 893 1.649 rillig for (ln = opts.variables.first; ln != NULL; ln = ln->next) 894 1.649 rillig PrintVariable(ln->datum, expandVars); 895 1.266 christos } 896 1.266 christos 897 1.534 rillig static bool 898 1.649 rillig MakeTargets(void) 899 1.266 christos { 900 1.649 rillig GNodeList targets = LST_INIT; 901 1.547 rillig bool outOfDate; /* false if all targets up to date */ 902 1.266 christos 903 1.486 rillig if (Lst_IsEmpty(&opts.create)) 904 1.649 rillig Parse_MainName(&targets); 905 1.266 christos else 906 1.649 rillig Targ_FindList(&targets, &opts.create); 907 1.266 christos 908 1.391 rillig if (!opts.compatMake) { 909 1.549 rillig if (!opts.query) { 910 1.266 christos Job_Init(); 911 1.534 rillig jobsRunning = true; 912 1.266 christos } 913 1.266 christos 914 1.649 rillig outOfDate = Make_MakeParallel(&targets); 915 1.266 christos } else { 916 1.649 rillig Compat_MakeAll(&targets); 917 1.534 rillig outOfDate = false; 918 1.266 christos } 919 1.649 rillig Lst_Done(&targets); /* Don't free the targets themselves. */ 920 1.266 christos return outOfDate; 921 1.266 christos } 922 1.266 christos 923 1.343 rillig /* 924 1.574 rillig * Set up the .TARGETS variable to contain the list of targets to be created. 925 1.574 rillig * If none specified, make the variable empty for now, the parser will fill 926 1.574 rillig * in the default or .MAIN target later. 927 1.343 rillig */ 928 1.343 rillig static void 929 1.343 rillig InitVarTargets(void) 930 1.343 rillig { 931 1.343 rillig StringListNode *ln; 932 1.343 rillig 933 1.486 rillig if (Lst_IsEmpty(&opts.create)) { 934 1.528 rillig Global_Set(".TARGETS", ""); 935 1.343 rillig return; 936 1.343 rillig } 937 1.343 rillig 938 1.486 rillig for (ln = opts.create.first; ln != NULL; ln = ln->next) { 939 1.525 rillig const char *name = ln->datum; 940 1.529 rillig Global_Append(".TARGETS", name); 941 1.343 rillig } 942 1.343 rillig } 943 1.343 rillig 944 1.404 rillig static void 945 1.404 rillig InitRandom(void) 946 1.404 rillig { 947 1.404 rillig struct timeval tv; 948 1.404 rillig 949 1.404 rillig gettimeofday(&tv, NULL); 950 1.644 rillig srandom((unsigned)(tv.tv_sec + tv.tv_usec)); 951 1.404 rillig } 952 1.404 rillig 953 1.369 rillig static const char * 954 1.525 rillig InitVarMachine(const struct utsname *utsname MAKE_ATTR_UNUSED) 955 1.369 rillig { 956 1.369 rillig const char *machine = getenv("MACHINE"); 957 1.369 rillig if (machine != NULL) 958 1.369 rillig return machine; 959 1.369 rillig 960 1.458 rillig #if defined(MAKE_NATIVE) 961 1.369 rillig return utsname->machine; 962 1.458 rillig #elif defined(MAKE_MACHINE) 963 1.369 rillig return MAKE_MACHINE; 964 1.369 rillig #else 965 1.369 rillig return "unknown"; 966 1.369 rillig #endif 967 1.369 rillig } 968 1.369 rillig 969 1.369 rillig static const char * 970 1.451 rillig InitVarMachineArch(void) 971 1.369 rillig { 972 1.369 rillig const char *env = getenv("MACHINE_ARCH"); 973 1.369 rillig if (env != NULL) 974 1.369 rillig return env; 975 1.369 rillig 976 1.369 rillig #ifdef MAKE_NATIVE 977 1.369 rillig { 978 1.369 rillig struct utsname utsname; 979 1.426 rillig static char machine_arch_buf[sizeof utsname.machine]; 980 1.369 rillig const int mib[2] = { CTL_HW, HW_MACHINE_ARCH }; 981 1.426 rillig size_t len = sizeof machine_arch_buf; 982 1.369 rillig 983 1.644 rillig if (sysctl(mib, (unsigned)__arraycount(mib), 984 1.510 rillig machine_arch_buf, &len, NULL, 0) < 0) { 985 1.657 rillig (void)fprintf(stderr, "%s: sysctl: %s\n", 986 1.510 rillig progname, strerror(errno)); 987 1.510 rillig exit(2); 988 1.369 rillig } 989 1.369 rillig 990 1.369 rillig return machine_arch_buf; 991 1.369 rillig } 992 1.457 rillig #elif defined(MACHINE_ARCH) 993 1.457 rillig return MACHINE_ARCH; 994 1.457 rillig #elif defined(MAKE_MACHINE_ARCH) 995 1.369 rillig return MAKE_MACHINE_ARCH; 996 1.369 rillig #else 997 1.369 rillig return "unknown"; 998 1.369 rillig #endif 999 1.369 rillig } 1000 1.369 rillig 1001 1.381 rillig #ifndef NO_PWD_OVERRIDE 1002 1.381 rillig /* 1003 1.381 rillig * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX 1004 1.381 rillig * since the value of curdir can vary depending on how we got 1005 1.602 rillig * here. That is, sitting at a shell prompt (shell that provides $PWD) 1006 1.602 rillig * or via subdir.mk, in which case it's likely a shell which does 1007 1.381 rillig * not provide it. 1008 1.382 rillig * 1009 1.381 rillig * So, to stop it breaking this case only, we ignore PWD if 1010 1.602 rillig * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains an expression. 1011 1.381 rillig */ 1012 1.381 rillig static void 1013 1.382 rillig HandlePWD(const struct stat *curdir_st) 1014 1.381 rillig { 1015 1.382 rillig char *pwd; 1016 1.572 rillig FStr makeobjdir; 1017 1.382 rillig struct stat pwd_st; 1018 1.381 rillig 1019 1.381 rillig if (ignorePWD || (pwd = getenv("PWD")) == NULL) 1020 1.381 rillig return; 1021 1.381 rillig 1022 1.572 rillig if (Var_Exists(SCOPE_CMDLINE, "MAKEOBJDIRPREFIX")) 1023 1.382 rillig return; 1024 1.382 rillig 1025 1.532 rillig makeobjdir = Var_Value(SCOPE_CMDLINE, "MAKEOBJDIR"); 1026 1.499 rillig if (makeobjdir.str != NULL && strchr(makeobjdir.str, '$') != NULL) 1027 1.382 rillig goto ignore_pwd; 1028 1.382 rillig 1029 1.382 rillig if (stat(pwd, &pwd_st) == 0 && 1030 1.382 rillig curdir_st->st_ino == pwd_st.st_ino && 1031 1.382 rillig curdir_st->st_dev == pwd_st.st_dev) 1032 1.622 rillig snprintf(curdir, MAXPATHLEN, "%s", pwd); 1033 1.382 rillig 1034 1.382 rillig ignore_pwd: 1035 1.499 rillig FStr_Done(&makeobjdir); 1036 1.381 rillig } 1037 1.381 rillig #endif 1038 1.381 rillig 1039 1.407 rillig /* 1040 1.550 rillig * Find the .OBJDIR. If MAKEOBJDIRPREFIX, or failing that, MAKEOBJDIR is set 1041 1.550 rillig * in the environment, try only that value and fall back to .CURDIR if it 1042 1.550 rillig * does not exist. 1043 1.407 rillig * 1044 1.407 rillig * Otherwise, try _PATH_OBJDIR.MACHINE-MACHINE_ARCH, _PATH_OBJDIR.MACHINE, 1045 1.550 rillig * and finally _PATH_OBJDIRPREFIX`pwd`, in that order. If none of these 1046 1.550 rillig * paths exist, just use .CURDIR. 1047 1.407 rillig */ 1048 1.407 rillig static void 1049 1.407 rillig InitObjdir(const char *machine, const char *machine_arch) 1050 1.407 rillig { 1051 1.534 rillig bool writable; 1052 1.456 sjg 1053 1.491 rillig Dir_InitCur(curdir); 1054 1.538 rillig writable = GetBooleanExpr("${MAKE_OBJDIR_CHECK_WRITABLE}", true); 1055 1.534 rillig (void)Main_SetObjdir(false, "%s", curdir); 1056 1.407 rillig 1057 1.461 rillig if (!SetVarObjdir(writable, "MAKEOBJDIRPREFIX", curdir) && 1058 1.461 rillig !SetVarObjdir(writable, "MAKEOBJDIR", "") && 1059 1.456 sjg !Main_SetObjdir(writable, "%s.%s-%s", _PATH_OBJDIR, machine, machine_arch) && 1060 1.456 sjg !Main_SetObjdir(writable, "%s.%s", _PATH_OBJDIR, machine) && 1061 1.456 sjg !Main_SetObjdir(writable, "%s", _PATH_OBJDIR)) 1062 1.456 sjg (void)Main_SetObjdir(writable, "%s%s", _PATH_OBJDIRPREFIX, curdir); 1063 1.407 rillig } 1064 1.407 rillig 1065 1.393 rillig /* get rid of resource limit on file descriptors */ 1066 1.393 rillig static void 1067 1.393 rillig UnlimitFiles(void) 1068 1.393 rillig { 1069 1.393 rillig #if defined(MAKE_NATIVE) || (defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)) 1070 1.393 rillig struct rlimit rl; 1071 1.393 rillig if (getrlimit(RLIMIT_NOFILE, &rl) != -1 && 1072 1.393 rillig rl.rlim_cur != rl.rlim_max) { 1073 1.393 rillig rl.rlim_cur = rl.rlim_max; 1074 1.393 rillig (void)setrlimit(RLIMIT_NOFILE, &rl); 1075 1.393 rillig } 1076 1.393 rillig #endif 1077 1.393 rillig } 1078 1.393 rillig 1079 1.395 rillig static void 1080 1.395 rillig CmdOpts_Init(void) 1081 1.395 rillig { 1082 1.534 rillig opts.compatMake = false; 1083 1.543 rillig memset(&opts.debug, 0, sizeof(opts.debug)); 1084 1.525 rillig /* opts.debug_file has already been initialized earlier */ 1085 1.534 rillig opts.strict = false; 1086 1.534 rillig opts.debugVflag = false; 1087 1.534 rillig opts.checkEnvFirst = false; 1088 1.484 rillig Lst_Init(&opts.makefiles); 1089 1.534 rillig opts.ignoreErrors = false; /* Pay attention to non-zero returns */ 1090 1.493 rillig opts.maxJobs = 1; 1091 1.534 rillig opts.keepgoing = false; /* Stop on error */ 1092 1.534 rillig opts.noRecursiveExecute = false; /* Execute all .MAKE targets */ 1093 1.534 rillig opts.noExecute = false; /* Execute all commands */ 1094 1.549 rillig opts.query = false; 1095 1.534 rillig opts.noBuiltins = false; /* Read the built-in rules */ 1096 1.549 rillig opts.silent = false; /* Print commands as executed */ 1097 1.549 rillig opts.touch = false; 1098 1.437 rillig opts.printVars = PVM_NONE; 1099 1.485 rillig Lst_Init(&opts.variables); 1100 1.534 rillig opts.parseWarnFatal = false; 1101 1.534 rillig opts.enterFlag = false; 1102 1.534 rillig opts.varNoExportEnv = false; 1103 1.486 rillig Lst_Init(&opts.create); 1104 1.395 rillig } 1105 1.395 rillig 1106 1.507 rillig /* 1107 1.507 rillig * Initialize MAKE and .MAKE to the path of the executable, so that it can be 1108 1.406 rillig * found by execvp(3) and the shells, even after a chdir. 1109 1.406 rillig * 1110 1.406 rillig * If it's a relative path and contains a '/', resolve it to an absolute path. 1111 1.507 rillig * Otherwise keep it as is, assuming it will be found in the PATH. 1112 1.507 rillig */ 1113 1.397 rillig static void 1114 1.406 rillig InitVarMake(const char *argv0) 1115 1.405 rillig { 1116 1.406 rillig const char *make = argv0; 1117 1.621 rillig char pathbuf[MAXPATHLEN]; 1118 1.405 rillig 1119 1.406 rillig if (argv0[0] != '/' && strchr(argv0, '/') != NULL) { 1120 1.502 rillig const char *abspath = cached_realpath(argv0, pathbuf); 1121 1.406 rillig struct stat st; 1122 1.502 rillig if (abspath != NULL && abspath[0] == '/' && 1123 1.502 rillig stat(make, &st) == 0) 1124 1.502 rillig make = abspath; 1125 1.405 rillig } 1126 1.406 rillig 1127 1.528 rillig Global_Set("MAKE", make); 1128 1.528 rillig Global_Set(".MAKE", make); 1129 1.405 rillig } 1130 1.405 rillig 1131 1.507 rillig /* 1132 1.507 rillig * Add the directories from the colon-separated syspath to defSysIncPath. 1133 1.507 rillig * After returning, the contents of syspath is unspecified. 1134 1.507 rillig */ 1135 1.405 rillig static void 1136 1.409 rillig InitDefSysIncPath(char *syspath) 1137 1.397 rillig { 1138 1.397 rillig static char defsyspath[] = _PATH_DEFSYSPATH; 1139 1.604 rillig char *start, *p; 1140 1.397 rillig 1141 1.397 rillig /* 1142 1.397 rillig * If no user-supplied system path was given (through the -m option) 1143 1.397 rillig * add the directories from the DEFSYSPATH (more than one may be given 1144 1.397 rillig * as dir1:...:dirn) to the system include path. 1145 1.397 rillig */ 1146 1.397 rillig if (syspath == NULL || syspath[0] == '\0') 1147 1.397 rillig syspath = defsyspath; 1148 1.397 rillig else 1149 1.397 rillig syspath = bmake_strdup(syspath); 1150 1.397 rillig 1151 1.604 rillig for (start = syspath; *start != '\0'; start = p) { 1152 1.604 rillig for (p = start; *p != '\0' && *p != ':'; p++) 1153 1.397 rillig continue; 1154 1.604 rillig if (*p == ':') 1155 1.604 rillig *p++ = '\0'; 1156 1.433 rillig 1157 1.397 rillig /* look for magic parent directory search string */ 1158 1.464 rillig if (strncmp(start, ".../", 4) == 0) { 1159 1.397 rillig char *dir = Dir_FindHereOrAbove(curdir, start + 4); 1160 1.397 rillig if (dir != NULL) { 1161 1.516 rillig (void)SearchPath_Add(defSysIncPath, dir); 1162 1.397 rillig free(dir); 1163 1.397 rillig } 1164 1.464 rillig } else { 1165 1.516 rillig (void)SearchPath_Add(defSysIncPath, start); 1166 1.397 rillig } 1167 1.397 rillig } 1168 1.397 rillig 1169 1.397 rillig if (syspath != defsyspath) 1170 1.397 rillig free(syspath); 1171 1.397 rillig } 1172 1.397 rillig 1173 1.398 rillig static void 1174 1.398 rillig ReadBuiltinRules(void) 1175 1.398 rillig { 1176 1.445 rillig StringListNode *ln; 1177 1.525 rillig StringList sysMkFiles = LST_INIT; 1178 1.445 rillig 1179 1.515 rillig SearchPath_Expand( 1180 1.517 rillig Lst_IsEmpty(&sysIncPath->dirs) ? defSysIncPath : sysIncPath, 1181 1.515 rillig _PATH_DEFSYSMK, 1182 1.525 rillig &sysMkFiles); 1183 1.525 rillig if (Lst_IsEmpty(&sysMkFiles)) 1184 1.398 rillig Fatal("%s: no system rules (%s).", progname, _PATH_DEFSYSMK); 1185 1.445 rillig 1186 1.525 rillig for (ln = sysMkFiles.first; ln != NULL; ln = ln->next) 1187 1.553 rillig if (ReadMakefile(ln->datum)) 1188 1.445 rillig break; 1189 1.445 rillig 1190 1.445 rillig if (ln == NULL) 1191 1.445 rillig Fatal("%s: cannot open %s.", 1192 1.525 rillig progname, (const char *)sysMkFiles.first->datum); 1193 1.445 rillig 1194 1.613 rillig Lst_DoneFree(&sysMkFiles); 1195 1.398 rillig } 1196 1.398 rillig 1197 1.408 rillig static void 1198 1.408 rillig InitMaxJobs(void) 1199 1.408 rillig { 1200 1.408 rillig char *value; 1201 1.408 rillig int n; 1202 1.408 rillig 1203 1.655 sjg if (bogusJflag && !opts.compatMake) { 1204 1.655 sjg opts.compatMake = true; 1205 1.655 sjg Parse_Error(PARSE_WARNING, 1206 1.660 rillig "Invalid internal option \"-J\" in \"%s\"; " 1207 1.660 rillig "see the manual page", 1208 1.655 sjg curdir); 1209 1.655 sjg PrintStackTrace(true); 1210 1.655 sjg return; 1211 1.655 sjg } 1212 1.408 rillig if (forceJobs || opts.compatMake || 1213 1.532 rillig !Var_Exists(SCOPE_GLOBAL, ".MAKE.JOBS")) 1214 1.408 rillig return; 1215 1.408 rillig 1216 1.624 rillig value = Var_Subst("${.MAKE.JOBS}", SCOPE_GLOBAL, VARE_EVAL); 1217 1.408 rillig /* TODO: handle errors */ 1218 1.408 rillig n = (int)strtol(value, NULL, 0); 1219 1.408 rillig if (n < 1) { 1220 1.408 rillig (void)fprintf(stderr, 1221 1.453 rillig "%s: illegal value for .MAKE.JOBS " 1222 1.453 rillig "-- must be positive integer!\n", 1223 1.453 rillig progname); 1224 1.505 rillig exit(2); /* Not 1 so -q can distinguish error */ 1225 1.408 rillig } 1226 1.408 rillig 1227 1.408 rillig if (n != opts.maxJobs) { 1228 1.529 rillig Global_Append(MAKEFLAGS, "-j"); 1229 1.529 rillig Global_Append(MAKEFLAGS, value); 1230 1.408 rillig } 1231 1.408 rillig 1232 1.408 rillig opts.maxJobs = n; 1233 1.408 rillig maxJobTokens = opts.maxJobs; 1234 1.534 rillig forceJobs = true; 1235 1.408 rillig free(value); 1236 1.408 rillig } 1237 1.408 rillig 1238 1.400 rillig /* 1239 1.400 rillig * For compatibility, look at the directories in the VPATH variable 1240 1.400 rillig * and add them to the search path, if the variable is defined. The 1241 1.400 rillig * variable's value is in the same format as the PATH environment 1242 1.400 rillig * variable, i.e. <directory>:<directory>:<directory>... 1243 1.400 rillig */ 1244 1.400 rillig static void 1245 1.400 rillig InitVpath(void) 1246 1.400 rillig { 1247 1.400 rillig char *vpath, savec, *path; 1248 1.532 rillig if (!Var_Exists(SCOPE_CMDLINE, "VPATH")) 1249 1.400 rillig return; 1250 1.400 rillig 1251 1.624 rillig vpath = Var_Subst("${VPATH}", SCOPE_CMDLINE, VARE_EVAL); 1252 1.400 rillig /* TODO: handle errors */ 1253 1.400 rillig path = vpath; 1254 1.400 rillig do { 1255 1.604 rillig char *p; 1256 1.400 rillig /* skip to end of directory */ 1257 1.604 rillig for (p = path; *p != ':' && *p != '\0'; p++) 1258 1.400 rillig continue; 1259 1.400 rillig /* Save terminator character so know when to stop */ 1260 1.604 rillig savec = *p; 1261 1.604 rillig *p = '\0'; 1262 1.400 rillig /* Add directory to search path */ 1263 1.516 rillig (void)SearchPath_Add(&dirSearchPath, path); 1264 1.604 rillig *p = savec; 1265 1.604 rillig path = p + 1; 1266 1.400 rillig } while (savec == ':'); 1267 1.400 rillig free(vpath); 1268 1.400 rillig } 1269 1.400 rillig 1270 1.402 rillig static void 1271 1.553 rillig ReadAllMakefiles(const StringList *makefiles) 1272 1.403 rillig { 1273 1.443 rillig StringListNode *ln; 1274 1.403 rillig 1275 1.443 rillig for (ln = makefiles->first; ln != NULL; ln = ln->next) { 1276 1.443 rillig const char *fname = ln->datum; 1277 1.553 rillig if (!ReadMakefile(fname)) 1278 1.443 rillig Fatal("%s: cannot open %s.", progname, fname); 1279 1.403 rillig } 1280 1.403 rillig } 1281 1.403 rillig 1282 1.403 rillig static void 1283 1.443 rillig ReadFirstDefaultMakefile(void) 1284 1.443 rillig { 1285 1.562 rillig StringList makefiles = LST_INIT; 1286 1.446 rillig StringListNode *ln; 1287 1.591 rillig char *prefs = Var_Subst("${.MAKE.MAKEFILE_PREFERENCE}", 1288 1.624 rillig SCOPE_CMDLINE, VARE_EVAL); 1289 1.443 rillig /* TODO: handle errors */ 1290 1.443 rillig 1291 1.605 rillig AppendWords(&makefiles, prefs); 1292 1.446 rillig 1293 1.562 rillig for (ln = makefiles.first; ln != NULL; ln = ln->next) 1294 1.553 rillig if (ReadMakefile(ln->datum)) 1295 1.446 rillig break; 1296 1.446 rillig 1297 1.562 rillig Lst_Done(&makefiles); 1298 1.443 rillig free(prefs); 1299 1.443 rillig } 1300 1.443 rillig 1301 1.507 rillig /* 1302 1.507 rillig * Initialize variables such as MAKE, MACHINE, .MAKEFLAGS. 1303 1.449 rillig * Initialize a few modules. 1304 1.507 rillig * Parse the arguments from MAKEFLAGS and the command line. 1305 1.507 rillig */ 1306 1.443 rillig static void 1307 1.448 rillig main_Init(int argc, char **argv) 1308 1.402 rillig { 1309 1.381 rillig struct stat sa; 1310 1.369 rillig const char *machine; 1311 1.369 rillig const char *machine_arch; 1312 1.55 sjg char *syspath = getenv("MAKESYSPATH"); 1313 1.119 tsutsui struct utsname utsname; 1314 1.107 sjg 1315 1.154 apb /* default to writing debug to stderr */ 1316 1.391 rillig opts.debug_file = stderr; 1317 1.133 dsl 1318 1.542 rillig Str_Intern_Init(); 1319 1.469 rillig HashTable_Init(&cached_realpaths); 1320 1.469 rillig 1321 1.167 christos #ifdef SIGINFO 1322 1.188 sjg (void)bmake_signal(SIGINFO, siginfo); 1323 1.167 christos #endif 1324 1.404 rillig 1325 1.404 rillig InitRandom(); 1326 1.277 rillig 1327 1.498 rillig progname = str_basename(argv[0]); 1328 1.393 rillig 1329 1.393 rillig UnlimitFiles(); 1330 1.13 cgd 1331 1.206 christos if (uname(&utsname) == -1) { 1332 1.657 rillig (void)fprintf(stderr, "%s: uname: %s\n", progname, 1333 1.453 rillig strerror(errno)); 1334 1.447 rillig exit(2); 1335 1.206 christos } 1336 1.206 christos 1337 1.451 rillig machine = InitVarMachine(&utsname); 1338 1.451 rillig machine_arch = InitVarMachineArch(); 1339 1.33 christos 1340 1.645 rillig myPid = getpid(); 1341 1.183 sjg 1342 1.602 rillig /* Just in case MAKEOBJDIR wants us to do something tricky. */ 1343 1.476 rillig Targ_Init(); 1344 1.589 sjg Global_Set_ReadOnly(".MAKE.OS", utsname.sysname); 1345 1.528 rillig Global_Set("MACHINE", machine); 1346 1.528 rillig Global_Set("MACHINE_ARCH", machine_arch); 1347 1.170 perry #ifdef MAKE_VERSION 1348 1.528 rillig Global_Set("MAKE_VERSION", MAKE_VERSION); 1349 1.170 perry #endif 1350 1.602 rillig Global_Set_ReadOnly(".newline", "\n"); 1351 1.176 sjg #ifndef MAKEFILE_PREFERENCE_LIST 1352 1.550 rillig /* This is the traditional preference for makefiles. */ 1353 1.176 sjg # define MAKEFILE_PREFERENCE_LIST "makefile Makefile" 1354 1.176 sjg #endif 1355 1.591 rillig Global_Set(".MAKE.MAKEFILE_PREFERENCE", MAKEFILE_PREFERENCE_LIST); 1356 1.587 rillig Global_Set(".MAKE.DEPENDFILE", ".depend"); 1357 1.599 rillig /* Tell makefiles like jobs.mk whether we support -jC */ 1358 1.596 sjg #ifdef _SC_NPROCESSORS_ONLN 1359 1.596 sjg Global_Set_ReadOnly(".MAKE.JOBS.C", "yes"); 1360 1.596 sjg #else 1361 1.596 sjg Global_Set_ReadOnly(".MAKE.JOBS.C", "no"); 1362 1.596 sjg #endif 1363 1.51 sjg 1364 1.395 rillig CmdOpts_Init(); 1365 1.534 rillig allPrecious = false; /* Remove targets when interrupted */ 1366 1.534 rillig deleteOnError = false; /* Historical default behavior */ 1367 1.534 rillig jobsRunning = false; 1368 1.1 cgd 1369 1.391 rillig maxJobTokens = opts.maxJobs; 1370 1.534 rillig ignorePWD = false; 1371 1.13 cgd 1372 1.1 cgd /* 1373 1.1 cgd * Initialize the parsing, directory and variable modules to prepare 1374 1.1 cgd * for the reading of inclusion paths and variable settings on the 1375 1.1 cgd * command line 1376 1.1 cgd */ 1377 1.36 gwr 1378 1.36 gwr /* 1379 1.1 cgd * Initialize various variables. 1380 1.1 cgd * MAKE also gets this name, for compatibility 1381 1.1 cgd * .MAKEFLAGS gets set to the empty string just in case. 1382 1.1 cgd * MFLAGS also gets initialized empty, for compatibility. 1383 1.1 cgd */ 1384 1.79 tv Parse_Init(); 1385 1.406 rillig InitVarMake(argv[0]); 1386 1.528 rillig Global_Set(MAKEFLAGS, ""); 1387 1.591 rillig Global_Set(".MAKEOVERRIDES", ""); 1388 1.528 rillig Global_Set("MFLAGS", ""); 1389 1.528 rillig Global_Set(".ALLTARGETS", ""); 1390 1.615 sjg Global_Set_ReadOnly(".MAKE.LEVEL.ENV", MAKE_LEVEL_ENV); 1391 1.1 cgd 1392 1.447 rillig /* Set some other useful variables. */ 1393 1.142 sjg { 1394 1.636 rillig char buf[64]; 1395 1.636 rillig const char *ep = getenv(MAKE_LEVEL_ENV); 1396 1.142 sjg 1397 1.447 rillig makelevel = ep != NULL && ep[0] != '\0' ? atoi(ep) : 0; 1398 1.447 rillig if (makelevel < 0) 1399 1.447 rillig makelevel = 0; 1400 1.552 rillig snprintf(buf, sizeof buf, "%d", makelevel); 1401 1.591 rillig Global_Set(".MAKE.LEVEL", buf); 1402 1.552 rillig snprintf(buf, sizeof buf, "%u", myPid); 1403 1.589 sjg Global_Set_ReadOnly(".MAKE.PID", buf); 1404 1.552 rillig snprintf(buf, sizeof buf, "%u", getppid()); 1405 1.589 sjg Global_Set_ReadOnly(".MAKE.PPID", buf); 1406 1.552 rillig snprintf(buf, sizeof buf, "%u", getuid()); 1407 1.589 sjg Global_Set_ReadOnly(".MAKE.UID", buf); 1408 1.552 rillig snprintf(buf, sizeof buf, "%u", getgid()); 1409 1.589 sjg Global_Set_ReadOnly(".MAKE.GID", buf); 1410 1.142 sjg } 1411 1.220 christos if (makelevel > 0) { 1412 1.220 christos char pn[1024]; 1413 1.426 rillig snprintf(pn, sizeof pn, "%s[%d]", progname, makelevel); 1414 1.221 christos progname = bmake_strdup(pn); 1415 1.220 christos } 1416 1.142 sjg 1417 1.210 sjg #ifdef USE_META 1418 1.210 sjg meta_init(); 1419 1.210 sjg #endif 1420 1.306 rillig Dir_Init(); 1421 1.255 sjg 1422 1.653 rillig if (getcwd(curdir, MAXPATHLEN) == NULL) { 1423 1.657 rillig (void)fprintf(stderr, "%s: getcwd: %s\n", 1424 1.653 rillig progname, strerror(errno)); 1425 1.653 rillig exit(2); 1426 1.653 rillig } 1427 1.653 rillig 1428 1.412 rillig { 1429 1.561 rillig char *makeflags = explode(getenv("MAKEFLAGS")); 1430 1.561 rillig Main_ParseArgLine(makeflags); 1431 1.561 rillig free(makeflags); 1432 1.412 rillig } 1433 1.31 christos 1434 1.175 sjg MainParseArgs(argc, argv); 1435 1.175 sjg 1436 1.391 rillig if (opts.enterFlag) 1437 1.220 christos printf("%s: Entering directory `%s'\n", progname, curdir); 1438 1.220 christos 1439 1.174 sjg if (stat(curdir, &sa) == -1) { 1440 1.657 rillig (void)fprintf(stderr, "%s: stat %s: %s\n", 1441 1.453 rillig progname, curdir, strerror(errno)); 1442 1.447 rillig exit(2); 1443 1.174 sjg } 1444 1.174 sjg 1445 1.222 sjg #ifndef NO_PWD_OVERRIDE 1446 1.381 rillig HandlePWD(&sa); 1447 1.222 sjg #endif 1448 1.528 rillig Global_Set(".CURDIR", curdir); 1449 1.174 sjg 1450 1.407 rillig InitObjdir(machine, machine_arch); 1451 1.174 sjg 1452 1.1 cgd Arch_Init(); 1453 1.1 cgd Suff_Init(); 1454 1.58 sommerfe Trace_Init(tracefile); 1455 1.1 cgd 1456 1.459 rillig defaultNode = NULL; 1457 1.1 cgd (void)time(&now); 1458 1.1 cgd 1459 1.58 sommerfe Trace_Log(MAKESTART, NULL); 1460 1.279 rillig 1461 1.343 rillig InitVarTargets(); 1462 1.25 christos 1463 1.409 rillig InitDefSysIncPath(syspath); 1464 1.448 rillig } 1465 1.25 christos 1466 1.507 rillig /* 1467 1.507 rillig * Read the system makefile followed by either makefile, Makefile or the 1468 1.507 rillig * files given by the -f option. Exit on parse errors. 1469 1.507 rillig */ 1470 1.448 rillig static void 1471 1.448 rillig main_ReadFiles(void) 1472 1.448 rillig { 1473 1.452 rillig 1474 1.588 sjg if (Lst_IsEmpty(&sysIncPath->dirs)) 1475 1.588 sjg SearchPath_AddAll(sysIncPath, defSysIncPath); 1476 1.588 sjg 1477 1.588 sjg Dir_SetSYSPATH(); 1478 1.398 rillig if (!opts.noBuiltins) 1479 1.398 rillig ReadBuiltinRules(); 1480 1.452 rillig 1481 1.580 rillig posix_state = PS_MAYBE_NEXT_LINE; 1482 1.484 rillig if (!Lst_IsEmpty(&opts.makefiles)) 1483 1.484 rillig ReadAllMakefiles(&opts.makefiles); 1484 1.443 rillig else 1485 1.443 rillig ReadFirstDefaultMakefile(); 1486 1.448 rillig } 1487 1.436 rillig 1488 1.449 rillig /* Compute the dependency graph. */ 1489 1.448 rillig static void 1490 1.448 rillig main_PrepareMaking(void) 1491 1.448 rillig { 1492 1.138 dsl /* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */ 1493 1.437 rillig if (!opts.noBuiltins || opts.printVars == PVM_NONE) { 1494 1.590 rillig makeDependfile = Var_Subst("${.MAKE.DEPENDFILE}", 1495 1.624 rillig SCOPE_CMDLINE, VARE_EVAL); 1496 1.447 rillig if (makeDependfile[0] != '\0') { 1497 1.447 rillig /* TODO: handle errors */ 1498 1.534 rillig doing_depend = true; 1499 1.447 rillig (void)ReadMakefile(makeDependfile); 1500 1.534 rillig doing_depend = false; 1501 1.447 rillig } 1502 1.145 dsl } 1503 1.1 cgd 1504 1.233 sjg if (enterFlagObj) 1505 1.233 sjg printf("%s: Entering directory `%s'\n", progname, objdir); 1506 1.279 rillig 1507 1.500 rillig MakeMode(); 1508 1.176 sjg 1509 1.412 rillig { 1510 1.532 rillig FStr makeflags = Var_Value(SCOPE_GLOBAL, MAKEFLAGS); 1511 1.529 rillig Global_Append("MFLAGS", makeflags.str); 1512 1.499 rillig FStr_Done(&makeflags); 1513 1.412 rillig } 1514 1.1 cgd 1515 1.408 rillig InitMaxJobs(); 1516 1.243 matthias 1517 1.447 rillig if (!opts.compatMake && !forceJobs) 1518 1.534 rillig opts.compatMake = true; 1519 1.243 matthias 1520 1.391 rillig if (!opts.compatMake) 1521 1.646 rillig TokenPool_Init(maxJobTokens, tokenPoolReader, tokenPoolWriter); 1522 1.352 rillig DEBUG5(JOB, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n", 1523 1.646 rillig tokenPoolReader, tokenPoolWriter, opts.maxJobs, maxJobTokens, 1524 1.646 rillig opts.compatMake ? 1 : 0); 1525 1.58 sommerfe 1526 1.437 rillig if (opts.printVars == PVM_NONE) 1527 1.534 rillig Main_ExportMAKEFLAGS(true); /* initial export */ 1528 1.279 rillig 1529 1.400 rillig InitVpath(); 1530 1.1 cgd 1531 1.1 cgd /* 1532 1.1 cgd * Now that all search paths have been read for suffixes et al, it's 1533 1.1 cgd * time to add the default search path to their lists... 1534 1.1 cgd */ 1535 1.535 rillig Suff_ExtendPaths(); 1536 1.50 mycroft 1537 1.50 mycroft /* 1538 1.50 mycroft * Propagate attributes through :: dependency lists. 1539 1.50 mycroft */ 1540 1.50 mycroft Targ_Propagate(); 1541 1.1 cgd 1542 1.1 cgd /* print the initial graph, if the user requested it */ 1543 1.1 cgd if (DEBUG(GRAPH1)) 1544 1.1 cgd Targ_PrintGraph(1); 1545 1.448 rillig } 1546 1.1 cgd 1547 1.507 rillig /* 1548 1.648 rillig * Make the targets, or print variables. 1549 1.507 rillig * Return whether any of the targets is out-of-date. 1550 1.507 rillig */ 1551 1.534 rillig static bool 1552 1.448 rillig main_Run(void) 1553 1.448 rillig { 1554 1.437 rillig if (opts.printVars != PVM_NONE) { 1555 1.649 rillig PrintVariables(); 1556 1.534 rillig return false; 1557 1.649 rillig } else 1558 1.649 rillig return MakeTargets(); 1559 1.448 rillig } 1560 1.448 rillig 1561 1.449 rillig /* Clean up after making the targets. */ 1562 1.448 rillig static void 1563 1.448 rillig main_CleanUp(void) 1564 1.448 rillig { 1565 1.448 rillig #ifdef CLEANUP 1566 1.613 rillig Lst_DoneFree(&opts.variables); 1567 1.613 rillig Lst_DoneFree(&opts.makefiles); 1568 1.613 rillig Lst_DoneFree(&opts.create); 1569 1.448 rillig #endif 1570 1.448 rillig 1571 1.448 rillig if (DEBUG(GRAPH2)) 1572 1.448 rillig Targ_PrintGraph(2); 1573 1.31 christos 1574 1.448 rillig Trace_Log(MAKEEND, NULL); 1575 1.448 rillig 1576 1.448 rillig if (enterFlagObj) 1577 1.448 rillig printf("%s: Leaving directory `%s'\n", progname, objdir); 1578 1.448 rillig if (opts.enterFlag) 1579 1.448 rillig printf("%s: Leaving directory `%s'\n", progname, curdir); 1580 1.14 jtc 1581 1.630 rillig Var_Stats(); 1582 1.630 rillig Targ_Stats(); 1583 1.630 rillig 1584 1.448 rillig #ifdef USE_META 1585 1.448 rillig meta_finish(); 1586 1.448 rillig #endif 1587 1.629 rillig #ifdef CLEANUP 1588 1.448 rillig Suff_End(); 1589 1.448 rillig Targ_End(); 1590 1.448 rillig Arch_End(); 1591 1.448 rillig Parse_End(); 1592 1.448 rillig Dir_End(); 1593 1.448 rillig Job_End(); 1594 1.629 rillig #endif 1595 1.448 rillig Trace_End(); 1596 1.629 rillig #ifdef CLEANUP 1597 1.544 rillig Str_Intern_End(); 1598 1.629 rillig #endif 1599 1.448 rillig } 1600 1.448 rillig 1601 1.448 rillig static int 1602 1.649 rillig main_ExitCode(bool outOfDate) 1603 1.448 rillig { 1604 1.631 rillig if ((opts.strict && main_errors > 0) || parseErrors > 0) 1605 1.447 rillig return 2; /* Not 1 so -q can distinguish error */ 1606 1.137 dsl return outOfDate ? 1 : 0; 1607 1.1 cgd } 1608 1.1 cgd 1609 1.448 rillig int 1610 1.448 rillig main(int argc, char **argv) 1611 1.448 rillig { 1612 1.534 rillig bool outOfDate; 1613 1.448 rillig 1614 1.448 rillig main_Init(argc, argv); 1615 1.448 rillig main_ReadFiles(); 1616 1.448 rillig main_PrepareMaking(); 1617 1.448 rillig outOfDate = main_Run(); 1618 1.448 rillig main_CleanUp(); 1619 1.649 rillig return main_ExitCode(outOfDate); 1620 1.448 rillig } 1621 1.448 rillig 1622 1.507 rillig /* 1623 1.507 rillig * Open and parse the given makefile, with all its side effects. 1624 1.553 rillig * Return false if the file could not be opened. 1625 1.1 cgd */ 1626 1.553 rillig static bool 1627 1.325 rillig ReadMakefile(const char *fname) 1628 1.1 cgd { 1629 1.140 dsl int fd; 1630 1.304 rillig char *name, *path = NULL; 1631 1.1 cgd 1632 1.454 rillig if (strcmp(fname, "-") == 0) { 1633 1.565 rillig Parse_File("(stdin)", -1); 1634 1.532 rillig Var_Set(SCOPE_INTERNAL, "MAKEFILE", ""); 1635 1.1 cgd } else { 1636 1.635 sjg if (strncmp(fname, ".../", 4) == 0) { 1637 1.635 sjg name = Dir_FindHereOrAbove(curdir, fname + 4); 1638 1.635 sjg if (name != NULL) { 1639 1.635 sjg /* Dir_FindHereOrAbove returns dirname */ 1640 1.635 sjg path = str_concat3(name, "/", 1641 1.635 sjg str_basename(fname)); 1642 1.635 sjg free(name); 1643 1.635 sjg fd = open(path, O_RDONLY); 1644 1.635 sjg if (fd != -1) { 1645 1.635 sjg fname = path; 1646 1.635 sjg goto found; 1647 1.635 sjg } 1648 1.635 sjg } 1649 1.635 sjg } 1650 1.1 cgd /* if we've chdir'd, rebuild the path name */ 1651 1.454 rillig if (strcmp(curdir, objdir) != 0 && *fname != '/') { 1652 1.304 rillig path = str_concat3(curdir, "/", fname); 1653 1.140 dsl fd = open(path, O_RDONLY); 1654 1.140 dsl if (fd != -1) { 1655 1.1 cgd fname = path; 1656 1.1 cgd goto found; 1657 1.1 cgd } 1658 1.309 rillig free(path); 1659 1.279 rillig 1660 1.95 jmc /* If curdir failed, try objdir (ala .depend) */ 1661 1.304 rillig path = str_concat3(objdir, "/", fname); 1662 1.140 dsl fd = open(path, O_RDONLY); 1663 1.140 dsl if (fd != -1) { 1664 1.95 jmc fname = path; 1665 1.95 jmc goto found; 1666 1.95 jmc } 1667 1.140 dsl } else { 1668 1.140 dsl fd = open(fname, O_RDONLY); 1669 1.140 dsl if (fd != -1) 1670 1.140 dsl goto found; 1671 1.140 dsl } 1672 1.1 cgd /* look in -I and system include directories. */ 1673 1.1 cgd name = Dir_FindFile(fname, parseIncPath); 1674 1.454 rillig if (name == NULL) { 1675 1.517 rillig SearchPath *sysInc = Lst_IsEmpty(&sysIncPath->dirs) 1676 1.546 rillig ? defSysIncPath : sysIncPath; 1677 1.409 rillig name = Dir_FindFile(fname, sysInc); 1678 1.409 rillig } 1679 1.454 rillig if (name == NULL || (fd = open(name, O_RDONLY)) == -1) { 1680 1.238 christos free(name); 1681 1.48 christos free(path); 1682 1.553 rillig return false; 1683 1.48 christos } 1684 1.1 cgd fname = name; 1685 1.1 cgd /* 1686 1.1 cgd * set the MAKEFILE variable desired by System V fans -- the 1687 1.1 cgd * placement of the setting here means it gets set to the last 1688 1.1 cgd * makefile specified, as it is set by SysV make. 1689 1.1 cgd */ 1690 1.662 rillig found: 1691 1.176 sjg if (!doing_depend) 1692 1.532 rillig Var_Set(SCOPE_INTERNAL, "MAKEFILE", fname); 1693 1.140 dsl Parse_File(fname, fd); 1694 1.1 cgd } 1695 1.48 christos free(path); 1696 1.553 rillig return true; 1697 1.54 sjg } 1698 1.54 sjg 1699 1.632 sjg /* populate av for Cmd_Exec and Compat_RunCommand */ 1700 1.661 rillig void 1701 1.661 rillig Cmd_Argv(const char *cmd, size_t cmd_len, const char *av[5], 1702 1.632 sjg char *cmd_file, size_t cmd_filesz, bool eflag, bool xflag) 1703 1.632 sjg { 1704 1.632 sjg int cmd_fd = -1; 1705 1.632 sjg 1706 1.632 sjg if (shellPath == NULL) 1707 1.632 sjg Shell_Init(); 1708 1.632 sjg 1709 1.632 sjg if (cmd_file != NULL) { 1710 1.632 sjg if (cmd_len == 0) 1711 1.632 sjg cmd_len = strlen(cmd); 1712 1.632 sjg 1713 1.632 sjg if (cmd_len > MAKE_CMDLEN_LIMIT) { 1714 1.632 sjg cmd_fd = mkTempFile(NULL, cmd_file, cmd_filesz); 1715 1.632 sjg if (cmd_fd >= 0) { 1716 1.632 sjg ssize_t n; 1717 1.632 sjg 1718 1.632 sjg n = write(cmd_fd, cmd, cmd_len); 1719 1.632 sjg close(cmd_fd); 1720 1.632 sjg if (n < (ssize_t)cmd_len) { 1721 1.632 sjg unlink(cmd_file); 1722 1.632 sjg cmd_fd = -1; 1723 1.632 sjg } 1724 1.632 sjg } 1725 1.632 sjg } else 1726 1.632 sjg cmd_file[0] = '\0'; 1727 1.632 sjg } 1728 1.632 sjg 1729 1.632 sjg /* The following works for any of the builtin shell specs. */ 1730 1.661 rillig *av++ = shellPath; 1731 1.632 sjg if (eflag) 1732 1.661 rillig *av++ = shellErrFlag; 1733 1.632 sjg if (cmd_fd >= 0) { 1734 1.632 sjg if (xflag) 1735 1.661 rillig *av++ = "-x"; 1736 1.661 rillig *av++ = cmd_file; 1737 1.632 sjg } else { 1738 1.661 rillig *av++ = xflag ? "-xc" : "-c"; 1739 1.661 rillig *av++ = cmd; 1740 1.632 sjg } 1741 1.661 rillig *av = NULL; 1742 1.632 sjg } 1743 1.632 sjg 1744 1.514 rillig /* 1745 1.550 rillig * Execute the command in cmd, and return its output (only stdout, not 1746 1.568 rillig * stderr, possibly empty). In the output, replace newlines with spaces. 1747 1.29 christos */ 1748 1.29 christos char * 1749 1.568 rillig Cmd_Exec(const char *cmd, char **error) 1750 1.29 christos { 1751 1.661 rillig const char *args[5]; /* Arguments for invoking the shell */ 1752 1.482 rillig int pipefds[2]; 1753 1.453 rillig int cpid; /* Child PID */ 1754 1.453 rillig int pid; /* PID from wait() */ 1755 1.453 rillig int status; /* command exit status */ 1756 1.453 rillig Buffer buf; /* buffer to store the result */ 1757 1.453 rillig ssize_t bytes_read; 1758 1.568 rillig char *output; 1759 1.604 rillig char *p; 1760 1.559 rillig int saved_errno; 1761 1.607 sjg char cmd_file[MAXPATHLEN]; 1762 1.550 rillig 1763 1.569 rillig DEBUG1(VAR, "Capturing the output of command \"%s\"\n", cmd); 1764 1.31 christos 1765 1.661 rillig Cmd_Argv(cmd, 0, args, cmd_file, sizeof(cmd_file), false, false); 1766 1.661 rillig if (pipe(pipefds) == -1) { 1767 1.568 rillig *error = str_concat3( 1768 1.568 rillig "Couldn't create pipe for \"", cmd, "\""); 1769 1.573 rillig return bmake_strdup(""); 1770 1.453 rillig } 1771 1.453 rillig 1772 1.611 sjg Var_ReexportVars(SCOPE_GLOBAL); 1773 1.658 rillig Var_ExportStackTrace(NULL, cmd); 1774 1.504 rillig 1775 1.637 rillig switch (cpid = FORK_FUNCTION()) { 1776 1.453 rillig case 0: 1777 1.550 rillig (void)close(pipefds[0]); 1778 1.561 rillig (void)dup2(pipefds[1], STDOUT_FILENO); 1779 1.482 rillig (void)close(pipefds[1]); 1780 1.143 sjg 1781 1.453 rillig (void)execv(shellPath, UNCONST(args)); 1782 1.453 rillig _exit(1); 1783 1.453 rillig 1784 1.453 rillig case -1: 1785 1.568 rillig *error = str_concat3("Couldn't exec \"", cmd, "\""); 1786 1.558 rillig return bmake_strdup(""); 1787 1.558 rillig } 1788 1.29 christos 1789 1.558 rillig (void)close(pipefds[1]); /* No need for the writing half */ 1790 1.31 christos 1791 1.559 rillig saved_errno = 0; 1792 1.558 rillig Buf_Init(&buf); 1793 1.558 rillig 1794 1.558 rillig do { 1795 1.558 rillig char result[BUFSIZ]; 1796 1.558 rillig bytes_read = read(pipefds[0], result, sizeof result); 1797 1.558 rillig if (bytes_read > 0) 1798 1.558 rillig Buf_AddBytes(&buf, result, (size_t)bytes_read); 1799 1.558 rillig } while (bytes_read > 0 || (bytes_read == -1 && errno == EINTR)); 1800 1.558 rillig if (bytes_read == -1) 1801 1.559 rillig saved_errno = errno; 1802 1.558 rillig 1803 1.558 rillig (void)close(pipefds[0]); /* Close the input side of the pipe. */ 1804 1.558 rillig 1805 1.558 rillig while ((pid = waitpid(cpid, &status, 0)) != cpid && pid >= 0) 1806 1.558 rillig JobReapChild(pid, status, false); 1807 1.558 rillig 1808 1.559 rillig if (Buf_EndsWith(&buf, '\n')) 1809 1.559 rillig buf.data[buf.len - 1] = '\0'; 1810 1.558 rillig 1811 1.568 rillig output = Buf_DoneData(&buf); 1812 1.604 rillig for (p = output; *p != '\0'; p++) 1813 1.604 rillig if (*p == '\n') 1814 1.604 rillig *p = ' '; 1815 1.558 rillig 1816 1.558 rillig if (WIFSIGNALED(status)) 1817 1.568 rillig *error = str_concat3("\"", cmd, "\" exited on a signal"); 1818 1.625 rillig else if (WEXITSTATUS(status) != 0) { 1819 1.625 rillig Buffer errBuf; 1820 1.625 rillig Buf_Init(&errBuf); 1821 1.625 rillig Buf_AddStr(&errBuf, "Command \""); 1822 1.625 rillig Buf_AddStr(&errBuf, cmd); 1823 1.625 rillig Buf_AddStr(&errBuf, "\" exited with status "); 1824 1.625 rillig Buf_AddInt(&errBuf, WEXITSTATUS(status)); 1825 1.625 rillig *error = Buf_DoneData(&errBuf); 1826 1.625 rillig } else if (saved_errno != 0) 1827 1.568 rillig *error = str_concat3( 1828 1.568 rillig "Couldn't read shell's output for \"", cmd, "\""); 1829 1.568 rillig else 1830 1.568 rillig *error = NULL; 1831 1.607 sjg if (cmd_file[0] != '\0') 1832 1.607 sjg unlink(cmd_file); 1833 1.568 rillig return output; 1834 1.1 cgd } 1835 1.1 cgd 1836 1.507 rillig /* 1837 1.507 rillig * Print a printf-style error message. 1838 1.1 cgd * 1839 1.550 rillig * In default mode, this error message has no consequences, for compatibility 1840 1.550 rillig * reasons, in particular it does not affect the exit status. Only in lint 1841 1.550 rillig * mode (-dL) it does. 1842 1.507 rillig */ 1843 1.1 cgd void 1844 1.89 christos Error(const char *fmt, ...) 1845 1.1 cgd { 1846 1.1 cgd va_list ap; 1847 1.566 rillig FILE *f; 1848 1.85 wiz 1849 1.566 rillig f = opts.debug_file; 1850 1.566 rillig if (f == stdout) 1851 1.566 rillig f = stderr; 1852 1.184 sjg (void)fflush(stdout); 1853 1.567 rillig 1854 1.162 dsl for (;;) { 1855 1.567 rillig fprintf(f, "%s: ", progname); 1856 1.162 dsl va_start(ap, fmt); 1857 1.566 rillig (void)vfprintf(f, fmt, ap); 1858 1.162 dsl va_end(ap); 1859 1.566 rillig (void)fprintf(f, "\n"); 1860 1.566 rillig (void)fflush(f); 1861 1.566 rillig if (f == stderr) 1862 1.162 dsl break; 1863 1.566 rillig f = stderr; 1864 1.162 dsl } 1865 1.481 rillig main_errors++; 1866 1.1 cgd } 1867 1.1 cgd 1868 1.507 rillig /* 1869 1.507 rillig * Wait for any running jobs to finish, then produce an error message, 1870 1.465 rillig * finally exit immediately. 1871 1.1 cgd * 1872 1.465 rillig * Exiting immediately differs from Parse_Error, which exits only after the 1873 1.507 rillig * current top-level makefile has been parsed completely. 1874 1.507 rillig */ 1875 1.1 cgd void 1876 1.89 christos Fatal(const char *fmt, ...) 1877 1.1 cgd { 1878 1.1 cgd va_list ap; 1879 1.85 wiz 1880 1.634 rillig if (jobsRunning) 1881 1.634 rillig Job_Wait(); 1882 1.1 cgd 1883 1.184 sjg (void)fflush(stdout); 1884 1.609 sjg fprintf(stderr, "%s: ", progname); 1885 1.465 rillig va_start(ap, fmt); 1886 1.1 cgd (void)vfprintf(stderr, fmt, ap); 1887 1.1 cgd va_end(ap); 1888 1.1 cgd (void)fprintf(stderr, "\n"); 1889 1.1 cgd (void)fflush(stderr); 1890 1.577 rillig PrintStackTrace(true); 1891 1.1 cgd 1892 1.575 rillig PrintOnError(NULL, "\n"); 1893 1.67 sjg 1894 1.94 dsl if (DEBUG(GRAPH2) || DEBUG(GRAPH3)) 1895 1.1 cgd Targ_PrintGraph(2); 1896 1.433 rillig Trace_Log(MAKEERROR, NULL); 1897 1.1 cgd exit(2); /* Not 1 so -q can distinguish error */ 1898 1.1 cgd } 1899 1.1 cgd 1900 1.507 rillig /* 1901 1.507 rillig * Major exception once jobs are being created. 1902 1.507 rillig * Kills all jobs, prints a message and exits. 1903 1.507 rillig */ 1904 1.1 cgd void 1905 1.89 christos Punt(const char *fmt, ...) 1906 1.1 cgd { 1907 1.1 cgd va_list ap; 1908 1.85 wiz 1909 1.184 sjg (void)fflush(stdout); 1910 1.63 christos (void)fprintf(stderr, "%s: ", progname); 1911 1.567 rillig va_start(ap, fmt); 1912 1.1 cgd (void)vfprintf(stderr, fmt, ap); 1913 1.1 cgd va_end(ap); 1914 1.1 cgd (void)fprintf(stderr, "\n"); 1915 1.1 cgd (void)fflush(stderr); 1916 1.1 cgd 1917 1.575 rillig PrintOnError(NULL, "\n"); 1918 1.67 sjg 1919 1.1 cgd DieHorribly(); 1920 1.1 cgd } 1921 1.1 cgd 1922 1.392 rillig /* Exit without giving a message. */ 1923 1.1 cgd void 1924 1.85 wiz DieHorribly(void) 1925 1.1 cgd { 1926 1.1 cgd if (jobsRunning) 1927 1.1 cgd Job_AbortAll(); 1928 1.1 cgd if (DEBUG(GRAPH2)) 1929 1.1 cgd Targ_PrintGraph(2); 1930 1.433 rillig Trace_Log(MAKEERROR, NULL); 1931 1.505 rillig exit(2); /* Not 1 so -q can distinguish error */ 1932 1.1 cgd } 1933 1.1 cgd 1934 1.585 rillig int 1935 1.548 rillig unlink_file(const char *file) 1936 1.21 christos { 1937 1.21 christos struct stat st; 1938 1.21 christos 1939 1.21 christos if (lstat(file, &st) == -1) 1940 1.585 rillig return -1; 1941 1.21 christos 1942 1.21 christos if (S_ISDIR(st.st_mode)) { 1943 1.584 rillig /* 1944 1.584 rillig * POSIX says for unlink: "The path argument shall not name 1945 1.584 rillig * a directory unless [...]". 1946 1.584 rillig */ 1947 1.21 christos errno = EISDIR; 1948 1.585 rillig return -1; 1949 1.21 christos } 1950 1.585 rillig return unlink(file); 1951 1.1 cgd } 1952 1.1 cgd 1953 1.373 rillig static void 1954 1.373 rillig write_all(int fd, const void *data, size_t n) 1955 1.373 rillig { 1956 1.373 rillig const char *mem = data; 1957 1.373 rillig 1958 1.373 rillig while (n > 0) { 1959 1.373 rillig ssize_t written = write(fd, mem, n); 1960 1.561 rillig /* XXX: Should this EAGAIN be EINTR? */ 1961 1.373 rillig if (written == -1 && errno == EAGAIN) 1962 1.373 rillig continue; 1963 1.373 rillig if (written == -1) 1964 1.373 rillig break; 1965 1.373 rillig mem += written; 1966 1.375 rillig n -= (size_t)written; 1967 1.373 rillig } 1968 1.373 rillig } 1969 1.373 rillig 1970 1.550 rillig /* Print why exec failed, avoiding stdio. */ 1971 1.372 rillig void MAKE_ATTR_DEAD 1972 1.638 rillig execDie(const char *func, const char *arg) 1973 1.66 christos { 1974 1.638 rillig char msg[1024]; 1975 1.638 rillig int len; 1976 1.66 christos 1977 1.657 rillig len = snprintf(msg, sizeof(msg), "%s: %s(%s): %s\n", 1978 1.638 rillig progname, func, arg, strerror(errno)); 1979 1.638 rillig write_all(STDERR_FILENO, msg, (size_t)len); 1980 1.372 rillig _exit(1); 1981 1.66 christos } 1982 1.66 christos 1983 1.262 riastrad static void 1984 1.469 rillig purge_relative_cached_realpaths(void) 1985 1.262 riastrad { 1986 1.453 rillig HashIter hi; 1987 1.620 sjg bool more; 1988 1.453 rillig 1989 1.469 rillig HashIter_Init(&hi, &cached_realpaths); 1990 1.620 sjg more = HashIter_Next(&hi); 1991 1.620 sjg while (more) { 1992 1.619 rillig HashEntry *he = hi.entry; 1993 1.620 sjg more = HashIter_Next(&hi); 1994 1.453 rillig if (he->key[0] != '/') { 1995 1.469 rillig DEBUG1(DIR, "cached_realpath: purging %s\n", he->key); 1996 1.623 rillig free(he->value); 1997 1.469 rillig HashTable_DeleteEntry(&cached_realpaths, he); 1998 1.453 rillig } 1999 1.262 riastrad } 2000 1.262 riastrad } 2001 1.262 riastrad 2002 1.560 rillig const char * 2003 1.245 sjg cached_realpath(const char *pathname, char *resolved) 2004 1.245 sjg { 2005 1.453 rillig const char *rp; 2006 1.453 rillig 2007 1.453 rillig if (pathname == NULL || pathname[0] == '\0') 2008 1.453 rillig return NULL; 2009 1.453 rillig 2010 1.469 rillig rp = HashTable_FindValue(&cached_realpaths, pathname); 2011 1.469 rillig if (rp != NULL) { 2012 1.622 rillig snprintf(resolved, MAXPATHLEN, "%s", rp); 2013 1.469 rillig return resolved; 2014 1.469 rillig } 2015 1.469 rillig 2016 1.469 rillig rp = realpath(pathname, resolved); 2017 1.469 rillig if (rp != NULL) { 2018 1.469 rillig HashTable_Set(&cached_realpaths, pathname, bmake_strdup(rp)); 2019 1.469 rillig DEBUG2(DIR, "cached_realpath: %s -> %s\n", pathname, rp); 2020 1.469 rillig return resolved; 2021 1.469 rillig } 2022 1.248 christos 2023 1.469 rillig /* should we negative-cache? */ 2024 1.469 rillig return NULL; 2025 1.245 sjg } 2026 1.245 sjg 2027 1.275 sjg /* 2028 1.275 sjg * Return true if we should die without noise. 2029 1.429 rillig * For example our failing child was a sub-make or failure happened elsewhere. 2030 1.275 sjg */ 2031 1.534 rillig bool 2032 1.429 rillig shouldDieQuietly(GNode *gn, int bf) 2033 1.275 sjg { 2034 1.453 rillig static int quietly = -1; 2035 1.275 sjg 2036 1.453 rillig if (quietly < 0) { 2037 1.538 rillig if (DEBUG(JOB) || 2038 1.538 rillig !GetBooleanExpr("${.MAKE.DIE_QUIETLY}", true)) 2039 1.453 rillig quietly = 0; 2040 1.453 rillig else if (bf >= 0) 2041 1.453 rillig quietly = bf; 2042 1.453 rillig else 2043 1.661 rillig quietly = gn != NULL && gn->type & OP_MAKE ? 1 : 0; 2044 1.453 rillig } 2045 1.513 rillig return quietly != 0; 2046 1.275 sjg } 2047 1.275 sjg 2048 1.385 rillig static void 2049 1.385 rillig SetErrorVars(GNode *gn) 2050 1.385 rillig { 2051 1.453 rillig StringListNode *ln; 2052 1.612 sjg char sts[16]; 2053 1.385 rillig 2054 1.453 rillig /* 2055 1.453 rillig * We can print this even if there is no .ERROR target. 2056 1.453 rillig */ 2057 1.612 sjg snprintf(sts, sizeof(sts), "%d", gn->exit_status); 2058 1.612 sjg Global_Set(".ERROR_EXIT", sts); 2059 1.528 rillig Global_Set(".ERROR_TARGET", gn->name); 2060 1.531 rillig Global_Delete(".ERROR_CMD"); 2061 1.453 rillig 2062 1.483 rillig for (ln = gn->commands.first; ln != NULL; ln = ln->next) { 2063 1.453 rillig const char *cmd = ln->datum; 2064 1.453 rillig 2065 1.453 rillig if (cmd == NULL) 2066 1.453 rillig break; 2067 1.529 rillig Global_Append(".ERROR_CMD", cmd); 2068 1.453 rillig } 2069 1.385 rillig } 2070 1.385 rillig 2071 1.507 rillig /* 2072 1.507 rillig * Print some helpful information in case of an error. 2073 1.507 rillig * The caller should exit soon after calling this function. 2074 1.507 rillig */ 2075 1.67 sjg void 2076 1.472 rillig PrintOnError(GNode *gn, const char *msg) 2077 1.67 sjg { 2078 1.472 rillig static GNode *errorNode = NULL; 2079 1.626 rillig StringListNode *ln; 2080 1.283 sjg 2081 1.453 rillig if (DEBUG(HASH)) { 2082 1.453 rillig Targ_Stats(); 2083 1.453 rillig Var_Stats(); 2084 1.453 rillig } 2085 1.453 rillig 2086 1.509 sjg if (errorNode != NULL) 2087 1.509 sjg return; /* we've been here! */ 2088 1.453 rillig 2089 1.626 rillig printf("%s%s: stopped", msg, progname); 2090 1.626 rillig ln = opts.create.first; 2091 1.626 rillig if (ln != NULL || mainNode != NULL) { 2092 1.626 rillig printf(" making \""); 2093 1.626 rillig if (ln != NULL) { 2094 1.626 rillig printf("%s", (const char *)ln->datum); 2095 1.626 rillig for (ln = ln->next; ln != NULL; ln = ln->next) 2096 1.626 rillig printf(" %s", (const char *)ln->datum); 2097 1.628 rillig } else 2098 1.626 rillig printf("%s", mainNode->name); 2099 1.626 rillig printf("\""); 2100 1.626 rillig } 2101 1.626 rillig printf(" in %s\n", curdir); 2102 1.279 rillig 2103 1.509 sjg /* we generally want to keep quiet if a sub-make died */ 2104 1.509 sjg if (shouldDieQuietly(gn, -1)) 2105 1.509 sjg return; 2106 1.472 rillig 2107 1.472 rillig if (gn != NULL) 2108 1.453 rillig SetErrorVars(gn); 2109 1.472 rillig 2110 1.472 rillig { 2111 1.640 sjg char *errorVarsValues; 2112 1.640 sjg enum PosixState p_s = posix_state; 2113 1.641 riastrad 2114 1.640 sjg posix_state = PS_TOO_LATE; 2115 1.640 sjg errorVarsValues = Var_Subst( 2116 1.590 rillig "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}", 2117 1.624 rillig SCOPE_GLOBAL, VARE_EVAL); 2118 1.472 rillig /* TODO: handle errors */ 2119 1.472 rillig printf("%s", errorVarsValues); 2120 1.472 rillig free(errorVarsValues); 2121 1.640 sjg posix_state = p_s; 2122 1.472 rillig } 2123 1.472 rillig 2124 1.453 rillig fflush(stdout); 2125 1.176 sjg 2126 1.453 rillig /* 2127 1.453 rillig * Finally, see if there is a .ERROR target, and run it if so. 2128 1.453 rillig */ 2129 1.472 rillig errorNode = Targ_FindNode(".ERROR"); 2130 1.472 rillig if (errorNode != NULL) { 2131 1.472 rillig errorNode->type |= OP_SPECIAL; 2132 1.472 rillig Compat_Make(errorNode, errorNode); 2133 1.453 rillig } 2134 1.68 sjg } 2135 1.68 sjg 2136 1.68 sjg void 2137 1.534 rillig Main_ExportMAKEFLAGS(bool first) 2138 1.68 sjg { 2139 1.534 rillig static bool once = true; 2140 1.640 sjg enum PosixState p_s; 2141 1.566 rillig char *flags; 2142 1.68 sjg 2143 1.453 rillig if (once != first) 2144 1.453 rillig return; 2145 1.534 rillig once = false; 2146 1.279 rillig 2147 1.640 sjg p_s = posix_state; 2148 1.640 sjg posix_state = PS_TOO_LATE; 2149 1.590 rillig flags = Var_Subst( 2150 1.566 rillig "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}", 2151 1.624 rillig SCOPE_CMDLINE, VARE_EVAL); 2152 1.453 rillig /* TODO: handle errors */ 2153 1.610 rillig if (flags[0] != '\0') 2154 1.566 rillig setenv("MAKEFLAGS", flags, 1); 2155 1.617 rillig free(flags); 2156 1.640 sjg posix_state = p_s; 2157 1.1 cgd } 2158 1.180 sjg 2159 1.191 sjg char * 2160 1.191 sjg getTmpdir(void) 2161 1.180 sjg { 2162 1.453 rillig static char *tmpdir = NULL; 2163 1.473 rillig struct stat st; 2164 1.473 rillig 2165 1.473 rillig if (tmpdir != NULL) 2166 1.473 rillig return tmpdir; 2167 1.180 sjg 2168 1.566 rillig /* Honor $TMPDIR if it is valid, strip a trailing '/'. */ 2169 1.590 rillig tmpdir = Var_Subst("${TMPDIR:tA:U" _PATH_TMP ":S,/$,,W}/", 2170 1.624 rillig SCOPE_GLOBAL, VARE_EVAL); 2171 1.473 rillig /* TODO: handle errors */ 2172 1.180 sjg 2173 1.473 rillig if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) { 2174 1.473 rillig free(tmpdir); 2175 1.473 rillig tmpdir = bmake_strdup(_PATH_TMP); 2176 1.180 sjg } 2177 1.453 rillig return tmpdir; 2178 1.191 sjg } 2179 1.191 sjg 2180 1.191 sjg /* 2181 1.191 sjg * Create and open a temp file using "pattern". 2182 1.607 sjg * If tfile is provided, set it to a copy of the filename created. 2183 1.191 sjg * Otherwise unlink the file once open. 2184 1.191 sjg */ 2185 1.191 sjg int 2186 1.533 sjg mkTempFile(const char *pattern, char *tfile, size_t tfile_sz) 2187 1.191 sjg { 2188 1.453 rillig static char *tmpdir = NULL; 2189 1.533 sjg char tbuf[MAXPATHLEN]; 2190 1.453 rillig int fd; 2191 1.453 rillig 2192 1.453 rillig if (pattern == NULL) 2193 1.644 rillig pattern = "makeXXXXXX"; 2194 1.453 rillig if (tmpdir == NULL) 2195 1.453 rillig tmpdir = getTmpdir(); 2196 1.533 sjg if (tfile == NULL) { 2197 1.546 rillig tfile = tbuf; 2198 1.546 rillig tfile_sz = sizeof tbuf; 2199 1.533 sjg } 2200 1.561 rillig 2201 1.561 rillig if (pattern[0] == '/') 2202 1.533 sjg snprintf(tfile, tfile_sz, "%s", pattern); 2203 1.561 rillig else 2204 1.533 sjg snprintf(tfile, tfile_sz, "%s%s", tmpdir, pattern); 2205 1.561 rillig 2206 1.453 rillig if ((fd = mkstemp(tfile)) < 0) 2207 1.657 rillig Punt("mkstemp %s: %s", tfile, strerror(errno)); 2208 1.561 rillig if (tfile == tbuf) 2209 1.479 rillig unlink(tfile); /* we just want the descriptor */ 2210 1.561 rillig 2211 1.453 rillig return fd; 2212 1.180 sjg } 2213 1.201 sjg 2214 1.240 sjg /* 2215 1.474 rillig * Convert a string representation of a boolean into a boolean value. 2216 1.534 rillig * Anything that looks like "No", "False", "Off", "0" etc. is false, 2217 1.534 rillig * the empty string is the fallback, everything else is true. 2218 1.240 sjg */ 2219 1.534 rillig bool 2220 1.534 rillig ParseBoolean(const char *s, bool fallback) 2221 1.240 sjg { 2222 1.474 rillig char ch = ch_tolower(s[0]); 2223 1.474 rillig if (ch == '\0') 2224 1.474 rillig return fallback; 2225 1.474 rillig if (ch == '0' || ch == 'f' || ch == 'n') 2226 1.534 rillig return false; 2227 1.474 rillig if (ch == 'o') 2228 1.474 rillig return ch_tolower(s[1]) != 'f'; 2229 1.534 rillig return true; 2230 1.240 sjg } 2231