1 /* $NetBSD: main.c,v 1.533 2021/02/05 19:19:17 sjg Exp $ */
4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * Copyright (c) 1989 by Berkeley Softworks
37 * All rights reserved.
39 * This code is derived from software contributed to Berkeley by
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement:
52 * This product includes software developed by the University of
53 * California, Berkeley and its contributors.
54 * 4. Neither the name of the University nor the names of its contributors
55 * may be used to endorse or promote products derived from this software
56 * without specific prior written permission.
58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72 * The main file for this entire program. Exit routines etc. reside here.
74 * Utility functions defined in this file:
77 * Parse and process command line arguments from a
78 * single string. Used to implement the special targets
79 * .MFLAGS and .MAKEFLAGS.
81 * Error Print a tagged error message.
83 * Fatal Print an error message and exit.
85 * Punt Abort all jobs and exit with a message.
87 * Finish Finish things up by printing the number of errors
88 * that occurred, and exit.
91 #include <sys/types.h>
93 #include <sys/param.h>
94 #include <sys/resource.h>
96 #if defined(MAKE_NATIVE) && defined(HAVE_SYSCTL)
97 #include <sys/sysctl.h>
99 #include <sys/utsname.h>
110 #include "pathnames.h"
113 /* "@(#)main.c 8.3 (Berkeley) 3/19/94" */
114 MAKE_RCSID("$NetBSD: main.c,v 1.533 2021/02/05 19:19:17 sjg Exp $");
115 #if defined(MAKE_NATIVE) && !defined(lint)
116 __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
117 "The Regents of the University of California. "
118 "All rights reserved.");
122 # define __arraycount(__x) (sizeof(__x) / sizeof(__x[0]))
126 time_t now; /* Time at start of make */
127 GNode *defaultNode; /* .DEFAULT node */
128 Boolean allPrecious; /* .PRECIOUS given on line by itself */
129 Boolean deleteOnError; /* .DELETE_ON_ERROR: set */
131 static int maxJobTokens; /* -j argument */
132 Boolean enterFlagObj; /* -w and objdir != srcdir */
134 static int jp_0 = -1, jp_1 = -1; /* ends of parent job pipe */
135 Boolean doing_depend; /* Set while reading .depend */
136 static Boolean jobsRunning; /* TRUE if the jobs might be running */
137 static const char *tracefile;
138 static int ReadMakefile(const char *);
139 static void purge_relative_cached_realpaths(void);
141 static Boolean ignorePWD; /* if we use -C, PWD is meaningless */
142 static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */
143 char curdir[MAXPATHLEN + 1]; /* Startup directory */
144 const char *progname;
145 char *makeDependfile;
149 Boolean forceJobs = FALSE;
150 static int main_errors = 0;
151 static HashTable cached_realpaths;
154 * For compatibility with the POSIX version of MAKEFLAGS that includes
155 * all the options without '-', convert 'flags' to '-f -l -a -g -s'.
158 explode(const char *flags)
167 for (f = flags; *f != '\0'; f++)
172 return bmake_strdup(flags);
175 st = nf = bmake_malloc(len * 3 + 1);
176 while (*flags != '\0') {
187 * exit with usage message
189 MAKE_ATTR_DEAD static void
192 size_t prognameLen = strcspn(progname, "[");
194 (void)fprintf(stderr,
195 "usage: %.*s [-BeikNnqrSstWwX]\n"
196 " [-C directory] [-D variable] [-d flags] [-f makefile]\n"
197 " [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n"
198 " [-V variable] [-v variable] [variable=value] [target ...]\n",
199 (int)prognameLen, progname);
204 MainParseArgDebugFile(const char *arg)
210 if (opts.debug_file != stdout && opts.debug_file != stderr)
211 fclose(opts.debug_file);
219 if (strcmp(arg, "stdout") == 0) {
220 opts.debug_file = stdout;
223 if (strcmp(arg, "stderr") == 0) {
224 opts.debug_file = stderr;
229 fname = bmake_malloc(len + 20);
230 memcpy(fname, arg, len + 1);
232 /* Let the filename be modified by the pid */
233 if (strcmp(fname + len - 3, ".%d") == 0)
234 snprintf(fname + len - 2, 20, "%d", getpid());
236 opts.debug_file = fopen(fname, mode);
237 if (opts.debug_file == NULL) {
238 fprintf(stderr, "Cannot open debug file %s\n",
246 MainParseArgDebug(const char *argvalue)
249 DebugFlags debug = opts.debug;
251 for (modules = argvalue; *modules != '\0'; modules++) {
253 case '0': /* undocumented, only intended for tests */
272 debug |= DEBUG_ERROR;
278 if (modules[1] == '1') {
279 debug |= DEBUG_GRAPH1;
281 } else if (modules[1] == '2') {
282 debug |= DEBUG_GRAPH2;
284 } else if (modules[1] == '3') {
285 debug |= DEBUG_GRAPH3;
308 debug |= DEBUG_SCRIPT;
311 debug |= DEBUG_PARSE;
320 opts.debugVflag = TRUE;
326 debug |= DEBUG_SHELL;
329 MainParseArgDebugFile(modules + 1);
332 (void)fprintf(stderr,
333 "%s: illegal argument to d option -- %c\n",
343 * Make the debug_file unbuffered, and make
344 * stdout line buffered (unless debugfile == stdout).
346 setvbuf(opts.debug_file, NULL, _IONBF, 0);
347 if (opts.debug_file != stdout) {
348 setvbuf(stdout, NULL, _IOLBF, 0);
352 /* Is path relative, or does it contain any relative component "." or ".."? */
354 IsRelativePath(const char *path)
361 while ((cp = strstr(cp, "/.")) != NULL) {
365 if (cp[0] == '/' || cp[0] == '\0')
372 MainParseArgChdir(const char *argvalue)
376 if (chdir(argvalue) == -1) {
377 (void)fprintf(stderr, "%s: chdir %s: %s\n",
378 progname, argvalue, strerror(errno));
379 exit(2); /* Not 1 so -q can distinguish error */
381 if (getcwd(curdir, MAXPATHLEN) == NULL) {
382 (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
385 if (!IsRelativePath(argvalue) &&
386 stat(argvalue, &sa) != -1 &&
387 stat(curdir, &sb) != -1 &&
388 sa.st_ino == sb.st_ino &&
389 sa.st_dev == sb.st_dev)
390 strncpy(curdir, argvalue, MAXPATHLEN);
395 MainParseArgJobsInternal(const char *argvalue)
398 if (sscanf(argvalue, "%d,%d%c", &jp_0, &jp_1, &end) != 2) {
399 (void)fprintf(stderr,
400 "%s: internal error -- J option malformed (%s)\n",
404 if ((fcntl(jp_0, F_GETFD, 0) < 0) ||
405 (fcntl(jp_1, F_GETFD, 0) < 0)) {
407 (void)fprintf(stderr,
408 "%s: ###### warning -- J descriptors were closed!\n",
414 opts.compatMake = TRUE;
416 Global_Append(MAKEFLAGS, "-J");
417 Global_Append(MAKEFLAGS, argvalue);
422 MainParseArgJobs(const char *argvalue)
427 opts.maxJobs = (int)strtol(argvalue, &p, 0);
428 if (*p != '\0' || opts.maxJobs < 1) {
429 (void)fprintf(stderr,
430 "%s: illegal argument to -j -- must be positive integer!\n",
432 exit(2); /* Not 1 so -q can distinguish error */
434 Global_Append(MAKEFLAGS, "-j");
435 Global_Append(MAKEFLAGS, argvalue);
436 Global_Set(".MAKE.JOBS", argvalue);
437 maxJobTokens = opts.maxJobs;
441 MainParseArgSysInc(const char *argvalue)
443 /* look for magic parent directory search string */
444 if (strncmp(".../", argvalue, 4) == 0) {
445 char *found_path = Dir_FindHereOrAbove(curdir, argvalue + 4);
446 if (found_path == NULL)
448 (void)SearchPath_Add(sysIncPath, found_path);
451 (void)SearchPath_Add(sysIncPath, argvalue);
453 Global_Append(MAKEFLAGS, "-m");
454 Global_Append(MAKEFLAGS, argvalue);
458 MainParseArg(char c, const char *argvalue)
464 opts.compatMake = TRUE;
465 Global_Append(MAKEFLAGS, "-B");
466 Global_Set(MAKE_MODE, "compat");
469 MainParseArgChdir(argvalue);
472 if (argvalue[0] == '\0') return FALSE;
473 Global_SetExpand(argvalue, "1");
474 Global_Append(MAKEFLAGS, "-D");
475 Global_Append(MAKEFLAGS, argvalue);
478 Parse_AddIncludeDir(argvalue);
479 Global_Append(MAKEFLAGS, "-I");
480 Global_Append(MAKEFLAGS, argvalue);
483 MainParseArgJobsInternal(argvalue);
486 opts.noExecute = TRUE;
487 opts.noRecursiveExecute = TRUE;
488 Global_Append(MAKEFLAGS, "-N");
491 opts.keepgoing = FALSE;
492 Global_Append(MAKEFLAGS, "-S");
495 tracefile = bmake_strdup(argvalue);
496 Global_Append(MAKEFLAGS, "-T");
497 Global_Append(MAKEFLAGS, argvalue);
501 opts.printVars = c == 'v' ? PVM_EXPANDED : PVM_UNEXPANDED;
502 Lst_Append(&opts.variables, bmake_strdup(argvalue));
503 /* XXX: Why always -V? */
504 Global_Append(MAKEFLAGS, "-V");
505 Global_Append(MAKEFLAGS, argvalue);
508 opts.parseWarnFatal = TRUE;
509 /* XXX: why no Var_Append? */
512 opts.varNoExportEnv = TRUE;
513 Global_Append(MAKEFLAGS, "-X");
516 /* If '-d-opts' don't pass to children */
517 if (argvalue[0] == '-')
520 Global_Append(MAKEFLAGS, "-d");
521 Global_Append(MAKEFLAGS, argvalue);
523 MainParseArgDebug(argvalue);
526 opts.checkEnvFirst = TRUE;
527 Global_Append(MAKEFLAGS, "-e");
530 Lst_Append(&opts.makefiles, bmake_strdup(argvalue));
533 opts.ignoreErrors = TRUE;
534 Global_Append(MAKEFLAGS, "-i");
537 MainParseArgJobs(argvalue);
540 opts.keepgoing = TRUE;
541 Global_Append(MAKEFLAGS, "-k");
544 MainParseArgSysInc(argvalue);
545 /* XXX: why no Var_Append? */
548 opts.noExecute = TRUE;
549 Global_Append(MAKEFLAGS, "-n");
552 opts.queryFlag = TRUE;
553 /* Kind of nonsensical, wot? */
554 Global_Append(MAKEFLAGS, "-q");
557 opts.noBuiltins = TRUE;
558 Global_Append(MAKEFLAGS, "-r");
561 opts.beSilent = TRUE;
562 Global_Append(MAKEFLAGS, "-s");
565 opts.touchFlag = TRUE;
566 Global_Append(MAKEFLAGS, "-t");
569 opts.enterFlag = TRUE;
570 Global_Append(MAKEFLAGS, "-w");
580 * Parse the given arguments. Called from main() and from
581 * Main_ParseArgLine() when the .MAKEFLAGS target is used.
583 * The arguments must be treated as read-only and will be freed after the
586 * XXX: Deal with command line overriding .MAKEFLAGS in makefile
589 MainParseArgs(int argc, char **argv)
595 Boolean inOption, dashDash = FALSE;
597 const char *optspecs = "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrstv:w";
598 /* Can't actually use getopt(3) because rescanning is not portable */
617 if (c != '-' || dashDash)
622 /* '-' found at some earlier point */
623 optspec = strchr(optspecs, c);
624 if (c != '\0' && optspec != NULL && optspec[1] == ':') {
625 /* -<something> found, and <something> should have an arg */
629 if (*argvalue == '\0') {
647 if (!MainParseArg(c, argvalue))
655 * See if the rest of the arguments are variable assignments and
656 * perform them if so. Else take them to be targets and stuff them
657 * on the end of the "create" list.
659 for (; argc > 1; argv++, argc--) {
661 if (Parse_IsVar(argv[1], &var)) {
662 Parse_DoVar(&var, SCOPE_CMDLINE);
664 if (argv[1][0] == '\0')
665 Punt("illegal (null) argument.");
666 if (argv[1][0] == '-' && !dashDash)
668 Lst_Append(&opts.create, bmake_strdup(argv[1]));
674 (void)fprintf(stderr, "%s: option requires an argument -- %c\n",
680 * Break a line of arguments into words and parse them.
682 * Used when a .MFLAGS or .MAKEFLAGS target is encountered during parsing and
683 * by main() when reading the MAKEFLAGS environment variable.
686 Main_ParseArgLine(const char *line)
693 /* XXX: don't use line as an iterator variable */
694 for (; *line == ' '; line++)
702 * $MAKE may simply be naming the make(1) binary
706 if (!(cp = strrchr(line, '/')))
708 if ((cp = strstr(cp, "make")) &&
709 strcmp(cp, "make") == 0)
714 FStr argv0 = Var_Value(SCOPE_GLOBAL, ".MAKE");
715 buf = str_concat3(argv0.str, " ", line);
719 words = Str_Words(buf, TRUE);
720 if (words.words == NULL) {
721 Error("Unterminated quoted string [%s]", buf);
726 MainParseArgs((int)words.len, words.words);
732 Main_SetObjdir(Boolean writable, const char *fmt, ...)
736 char buf[MAXPATHLEN + 1];
737 char buf2[MAXPATHLEN + 1];
742 vsnprintf(path = buf, MAXPATHLEN, fmt, ap);
745 if (path[0] != '/') {
746 snprintf(buf2, MAXPATHLEN, "%s/%s", curdir, path);
750 /* look for the directory and try to chdir there */
751 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
752 if ((writable && access(path, W_OK) != 0) ||
753 (chdir(path) != 0)) {
754 (void)fprintf(stderr, "%s warning: %s: %s.\n",
755 progname, path, strerror(errno));
757 snprintf(objdir, sizeof objdir, "%s", path);
758 Global_Set(".OBJDIR", objdir);
759 setenv("PWD", objdir, 1);
761 purge_relative_cached_realpaths();
763 if (opts.enterFlag && strcmp(objdir, curdir) != 0)
772 SetVarObjdir(Boolean writable, const char *var, const char *suffix)
774 FStr path = Var_Value(SCOPE_CMDLINE, var);
777 if (path.str == NULL || path.str[0] == '\0') {
782 /* expand variable substitutions */
783 xpath = FStr_InitRefer(path.str);
784 if (strchr(path.str, '$') != 0) {
786 (void)Var_Subst(path.str, SCOPE_GLOBAL, VARE_WANTRES, &expanded);
787 /* TODO: handle errors */
788 xpath = FStr_InitOwn(expanded);
791 (void)Main_SetObjdir(writable, "%s%s", xpath.str, suffix);
799 * Splits str into words, adding them to the list.
800 * The string must be kept alive as long as the list.
803 str2Lst_Append(StringList *lp, char *str)
808 const char *sep = " \t";
810 for (n = 0, cp = strtok(str, sep); cp != NULL; cp = strtok(NULL, sep)) {
820 siginfo(int signo MAKE_ATTR_UNUSED)
822 char dir[MAXPATHLEN];
823 char str[2 * MAXPATHLEN];
825 if (getcwd(dir, sizeof dir) == NULL)
827 len = snprintf(str, sizeof str, "%s: Working in: %s\n", progname, dir);
829 (void)write(STDERR_FILENO, str, (size_t)len);
833 /* Allow makefiles some control over the mode we run in. */
839 (void)Var_Subst("${" MAKE_MODE ":tl}", SCOPE_GLOBAL, VARE_WANTRES, &mode);
840 /* TODO: handle errors */
842 if (mode[0] != '\0') {
843 if (strstr(mode, "compat") != NULL) {
844 opts.compatMake = TRUE;
848 if (strstr(mode, "meta") != NULL)
849 meta_mode_init(mode);
857 PrintVar(const char *varname, Boolean expandVars)
859 if (strchr(varname, '$') != NULL) {
861 (void)Var_Subst(varname, SCOPE_GLOBAL, VARE_WANTRES, &evalue);
862 /* TODO: handle errors */
863 printf("%s\n", evalue);
866 } else if (expandVars) {
867 char *expr = str_concat3("${", varname, "}");
869 (void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &evalue);
870 /* TODO: handle errors */
872 printf("%s\n", evalue);
876 FStr value = Var_Value(SCOPE_GLOBAL, varname);
877 printf("%s\n", value.str != NULL ? value.str : "");
883 * Return a Boolean based on a variable.
885 * If the knob is not set, return the fallback.
886 * If set, anything that looks or smells like "No", "False", "Off", "0", etc.
887 * is FALSE, otherwise TRUE.
890 GetBooleanVar(const char *varname, Boolean fallback)
892 char *expr = str_concat3("${", varname, ":U}");
896 (void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &value);
897 /* TODO: handle errors */
898 res = ParseBoolean(value, fallback);
910 if (opts.printVars == PVM_EXPANDED)
912 else if (opts.debugVflag)
915 expandVars = GetBooleanVar(".MAKE.EXPAND_VARIABLES", FALSE);
917 for (ln = opts.variables.first; ln != NULL; ln = ln->next) {
918 const char *varname = ln->datum;
919 PrintVar(varname, expandVars);
926 GNodeList targs = LST_INIT; /* target nodes to create */
927 Boolean outOfDate; /* FALSE if all targets up to date */
930 * Have now read the entire graph and need to make a list of
931 * targets to create. If none was given on the command line,
932 * we consult the parsing module to find the main target(s)
935 if (Lst_IsEmpty(&opts.create))
936 Parse_MainName(&targs);
938 Targ_FindList(&targs, &opts.create);
940 if (!opts.compatMake) {
942 * Initialize job module before traversing the graph
943 * now that any .BEGIN and .END targets have been read.
944 * This is done only if the -q flag wasn't given
945 * (to prevent the .BEGIN from being executed should
948 if (!opts.queryFlag) {
953 /* Traverse the graph, checking on all the targets */
954 outOfDate = Make_Run(&targs);
957 * Compat_Init will take care of creating all the
958 * targets as well as initializing the module.
963 Lst_Done(&targs); /* Don't free the targets themselves. */
968 * Set up the .TARGETS variable to contain the list of targets to be
969 * created. If none specified, make the variable empty -- the parser
970 * will fill the thing in with the default or .MAIN target.
977 if (Lst_IsEmpty(&opts.create)) {
978 Global_Set(".TARGETS", "");
982 for (ln = opts.create.first; ln != NULL; ln = ln->next) {
983 const char *name = ln->datum;
984 Global_Append(".TARGETS", name);
993 gettimeofday(&tv, NULL);
994 srandom((unsigned int)(tv.tv_sec + tv.tv_usec));
998 InitVarMachine(const struct utsname *utsname MAKE_ATTR_UNUSED)
1000 #ifdef FORCE_MACHINE
1001 return FORCE_MACHINE;
1003 const char *machine = getenv("MACHINE");
1005 if (machine != NULL)
1008 #if defined(MAKE_NATIVE)
1009 return utsname->machine;
1010 #elif defined(MAKE_MACHINE)
1011 return MAKE_MACHINE;
1019 InitVarMachineArch(void)
1021 #ifdef FORCE_MACHINE_ARCH
1022 return FORCE_MACHINE_ARCH;
1024 const char *env = getenv("MACHINE_ARCH");
1028 #if defined(MAKE_NATIVE) && defined(CTL_HW)
1030 struct utsname utsname;
1031 static char machine_arch_buf[sizeof utsname.machine];
1032 const int mib[2] = { CTL_HW, HW_MACHINE_ARCH };
1033 size_t len = sizeof machine_arch_buf;
1035 if (sysctl(mib, (unsigned int)__arraycount(mib),
1036 machine_arch_buf, &len, NULL, 0) < 0) {
1037 (void)fprintf(stderr, "%s: sysctl failed (%s).\n",
1038 progname, strerror(errno));
1042 return machine_arch_buf;
1044 #elif defined(MACHINE_ARCH)
1045 return MACHINE_ARCH;
1046 #elif defined(MAKE_MACHINE_ARCH)
1047 return MAKE_MACHINE_ARCH;
1054 #ifndef NO_PWD_OVERRIDE
1056 * All this code is so that we know where we are when we start up
1057 * on a different machine with pmake.
1059 * XXX: Make no longer has "local" and "remote" mode. Is this code still
1062 * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX
1063 * since the value of curdir can vary depending on how we got
1064 * here. Ie sitting at a shell prompt (shell that provides $PWD)
1065 * or via subdir.mk in which case its likely a shell which does
1068 * So, to stop it breaking this case only, we ignore PWD if
1069 * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a variable expression.
1072 HandlePWD(const struct stat *curdir_st)
1075 FStr prefix, makeobjdir;
1078 if (ignorePWD || (pwd = getenv("PWD")) == NULL)
1081 prefix = Var_Value(SCOPE_CMDLINE, "MAKEOBJDIRPREFIX");
1082 if (prefix.str != NULL) {
1087 makeobjdir = Var_Value(SCOPE_CMDLINE, "MAKEOBJDIR");
1088 if (makeobjdir.str != NULL && strchr(makeobjdir.str, '$') != NULL)
1091 if (stat(pwd, &pwd_st) == 0 &&
1092 curdir_st->st_ino == pwd_st.st_ino &&
1093 curdir_st->st_dev == pwd_st.st_dev)
1094 (void)strncpy(curdir, pwd, MAXPATHLEN);
1097 FStr_Done(&makeobjdir);
1102 * Find the .OBJDIR. If MAKEOBJDIRPREFIX, or failing that,
1103 * MAKEOBJDIR is set in the environment, try only that value
1104 * and fall back to .CURDIR if it does not exist.
1106 * Otherwise, try _PATH_OBJDIR.MACHINE-MACHINE_ARCH, _PATH_OBJDIR.MACHINE,
1107 * and * finally _PATH_OBJDIRPREFIX`pwd`, in that order. If none
1108 * of these paths exist, just use .CURDIR.
1111 InitObjdir(const char *machine, const char *machine_arch)
1115 Dir_InitCur(curdir);
1116 writable = GetBooleanVar("MAKE_OBJDIR_CHECK_WRITABLE", TRUE);
1117 (void)Main_SetObjdir(FALSE, "%s", curdir);
1119 if (!SetVarObjdir(writable, "MAKEOBJDIRPREFIX", curdir) &&
1120 !SetVarObjdir(writable, "MAKEOBJDIR", "") &&
1121 !Main_SetObjdir(writable, "%s.%s-%s", _PATH_OBJDIR, machine, machine_arch) &&
1122 !Main_SetObjdir(writable, "%s.%s", _PATH_OBJDIR, machine) &&
1123 !Main_SetObjdir(writable, "%s", _PATH_OBJDIR))
1124 (void)Main_SetObjdir(writable, "%s%s", _PATH_OBJDIRPREFIX, curdir);
1127 /* get rid of resource limit on file descriptors */
1131 #if defined(MAKE_NATIVE) || (defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE))
1133 if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
1134 rl.rlim_cur != rl.rlim_max) {
1135 rl.rlim_cur = rl.rlim_max;
1136 (void)setrlimit(RLIMIT_NOFILE, &rl);
1144 opts.compatMake = FALSE;
1145 opts.debug = DEBUG_NONE;
1146 /* opts.debug_file has already been initialized earlier */
1147 opts.strict = FALSE;
1148 opts.debugVflag = FALSE;
1149 opts.checkEnvFirst = FALSE;
1150 Lst_Init(&opts.makefiles);
1151 opts.ignoreErrors = FALSE; /* Pay attention to non-zero returns */
1153 opts.keepgoing = FALSE; /* Stop on error */
1154 opts.noRecursiveExecute = FALSE; /* Execute all .MAKE targets */
1155 opts.noExecute = FALSE; /* Execute all commands */
1156 opts.queryFlag = FALSE;
1157 opts.noBuiltins = FALSE; /* Read the built-in rules */
1158 opts.beSilent = FALSE; /* Print commands as executed */
1159 opts.touchFlag = FALSE;
1160 opts.printVars = PVM_NONE;
1161 Lst_Init(&opts.variables);
1162 opts.parseWarnFatal = FALSE;
1163 opts.enterFlag = FALSE;
1164 opts.varNoExportEnv = FALSE;
1165 Lst_Init(&opts.create);
1169 * Initialize MAKE and .MAKE to the path of the executable, so that it can be
1170 * found by execvp(3) and the shells, even after a chdir.
1172 * If it's a relative path and contains a '/', resolve it to an absolute path.
1173 * Otherwise keep it as is, assuming it will be found in the PATH.
1176 InitVarMake(const char *argv0)
1178 const char *make = argv0;
1180 if (argv0[0] != '/' && strchr(argv0, '/') != NULL) {
1181 char pathbuf[MAXPATHLEN];
1182 const char *abspath = cached_realpath(argv0, pathbuf);
1184 if (abspath != NULL && abspath[0] == '/' &&
1185 stat(make, &st) == 0)
1189 Global_Set("MAKE", make);
1190 Global_Set(".MAKE", make);
1194 * Add the directories from the colon-separated syspath to defSysIncPath.
1195 * After returning, the contents of syspath is unspecified.
1198 InitDefSysIncPath(char *syspath)
1200 static char defsyspath[] = _PATH_DEFSYSPATH;
1204 * If no user-supplied system path was given (through the -m option)
1205 * add the directories from the DEFSYSPATH (more than one may be given
1206 * as dir1:...:dirn) to the system include path.
1208 if (syspath == NULL || syspath[0] == '\0')
1209 syspath = defsyspath;
1211 syspath = bmake_strdup(syspath);
1213 for (start = syspath; *start != '\0'; start = cp) {
1214 for (cp = start; *cp != '\0' && *cp != ':'; cp++)
1219 /* look for magic parent directory search string */
1220 if (strncmp(start, ".../", 4) == 0) {
1221 char *dir = Dir_FindHereOrAbove(curdir, start + 4);
1223 (void)SearchPath_Add(defSysIncPath, dir);
1227 (void)SearchPath_Add(defSysIncPath, start);
1231 if (syspath != defsyspath)
1236 ReadBuiltinRules(void)
1239 StringList sysMkFiles = LST_INIT;
1242 Lst_IsEmpty(&sysIncPath->dirs) ? defSysIncPath : sysIncPath,
1245 if (Lst_IsEmpty(&sysMkFiles))
1246 Fatal("%s: no system rules (%s).", progname, _PATH_DEFSYSMK);
1248 for (ln = sysMkFiles.first; ln != NULL; ln = ln->next)
1249 if (ReadMakefile(ln->datum) == 0)
1253 Fatal("%s: cannot open %s.",
1254 progname, (const char *)sysMkFiles.first->datum);
1256 /* Free the list nodes but not the actual filenames since these may
1257 * still be used in GNodes. */
1258 Lst_Done(&sysMkFiles);
1267 if (forceJobs || opts.compatMake ||
1268 !Var_Exists(SCOPE_GLOBAL, ".MAKE.JOBS"))
1271 (void)Var_Subst("${.MAKE.JOBS}", SCOPE_GLOBAL, VARE_WANTRES, &value);
1272 /* TODO: handle errors */
1273 n = (int)strtol(value, NULL, 0);
1275 (void)fprintf(stderr,
1276 "%s: illegal value for .MAKE.JOBS "
1277 "-- must be positive integer!\n",
1279 exit(2); /* Not 1 so -q can distinguish error */
1282 if (n != opts.maxJobs) {
1283 Global_Append(MAKEFLAGS, "-j");
1284 Global_Append(MAKEFLAGS, value);
1288 maxJobTokens = opts.maxJobs;
1294 * For compatibility, look at the directories in the VPATH variable
1295 * and add them to the search path, if the variable is defined. The
1296 * variable's value is in the same format as the PATH environment
1297 * variable, i.e. <directory>:<directory>:<directory>...
1302 char *vpath, savec, *path;
1303 if (!Var_Exists(SCOPE_CMDLINE, "VPATH"))
1306 (void)Var_Subst("${VPATH}", SCOPE_CMDLINE, VARE_WANTRES, &vpath);
1307 /* TODO: handle errors */
1311 /* skip to end of directory */
1312 for (cp = path; *cp != ':' && *cp != '\0'; cp++)
1314 /* Save terminator character so know when to stop */
1317 /* Add directory to search path */
1318 (void)SearchPath_Add(&dirSearchPath, path);
1321 } while (savec == ':');
1326 ReadAllMakefiles(StringList *makefiles)
1330 for (ln = makefiles->first; ln != NULL; ln = ln->next) {
1331 const char *fname = ln->datum;
1332 if (ReadMakefile(fname) != 0)
1333 Fatal("%s: cannot open %s.", progname, fname);
1338 ReadFirstDefaultMakefile(void)
1343 (void)Var_Subst("${" MAKE_MAKEFILE_PREFERENCE "}",
1344 SCOPE_CMDLINE, VARE_WANTRES, &prefs);
1345 /* TODO: handle errors */
1347 /* XXX: This should use a local list instead of opts.makefiles
1348 * since these makefiles do not come from the command line. They
1349 * also have different semantics in that only the first file that
1350 * is found is processed. See ReadAllMakefiles. */
1351 (void)str2Lst_Append(&opts.makefiles, prefs);
1353 for (ln = opts.makefiles.first; ln != NULL; ln = ln->next)
1354 if (ReadMakefile(ln->datum) == 0)
1361 * Initialize variables such as MAKE, MACHINE, .MAKEFLAGS.
1362 * Initialize a few modules.
1363 * Parse the arguments from MAKEFLAGS and the command line.
1366 main_Init(int argc, char **argv)
1369 const char *machine;
1370 const char *machine_arch;
1371 char *syspath = getenv("MAKESYSPATH");
1372 struct utsname utsname;
1374 /* default to writing debug to stderr */
1375 opts.debug_file = stderr;
1377 HashTable_Init(&cached_realpaths);
1380 (void)bmake_signal(SIGINFO, siginfo);
1385 progname = str_basename(argv[0]);
1389 if (uname(&utsname) == -1) {
1390 (void)fprintf(stderr, "%s: uname failed (%s).\n", progname,
1396 * Get the name of this type of MACHINE from utsname
1397 * so we can share an executable for similar machines.
1398 * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
1400 * Note that both MACHINE and MACHINE_ARCH are decided at
1403 machine = InitVarMachine(&utsname);
1404 machine_arch = InitVarMachineArch();
1406 myPid = getpid(); /* remember this for vFork() */
1409 * Just in case MAKEOBJDIR wants us to do something tricky.
1413 Global_Set(".MAKE.OS", utsname.sysname);
1414 Global_Set("MACHINE", machine);
1415 Global_Set("MACHINE_ARCH", machine_arch);
1417 Global_Set("MAKE_VERSION", MAKE_VERSION);
1419 Global_Set(".newline", "\n"); /* handy for :@ loops */
1421 * This is the traditional preference for makefiles.
1423 #ifndef MAKEFILE_PREFERENCE_LIST
1424 # define MAKEFILE_PREFERENCE_LIST "makefile Makefile"
1426 Global_Set(MAKE_MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST);
1427 Global_Set(MAKE_DEPENDFILE, ".depend");
1430 allPrecious = FALSE; /* Remove targets when interrupted */
1431 deleteOnError = FALSE; /* Historical default behavior */
1432 jobsRunning = FALSE;
1434 maxJobTokens = opts.maxJobs;
1438 * Initialize the parsing, directory and variable modules to prepare
1439 * for the reading of inclusion paths and variable settings on the
1444 * Initialize various variables.
1445 * MAKE also gets this name, for compatibility
1446 * .MAKEFLAGS gets set to the empty string just in case.
1447 * MFLAGS also gets initialized empty, for compatibility.
1450 InitVarMake(argv[0]);
1451 Global_Set(MAKEFLAGS, "");
1452 Global_Set(MAKEOVERRIDES, "");
1453 Global_Set("MFLAGS", "");
1454 Global_Set(".ALLTARGETS", "");
1455 /* some makefiles need to know this */
1456 Var_Set(SCOPE_CMDLINE, MAKE_LEVEL ".ENV", MAKE_LEVEL_ENV);
1458 /* Set some other useful variables. */
1460 char tmp[64], *ep = getenv(MAKE_LEVEL_ENV);
1462 makelevel = ep != NULL && ep[0] != '\0' ? atoi(ep) : 0;
1465 snprintf(tmp, sizeof tmp, "%d", makelevel);
1466 Global_Set(MAKE_LEVEL, tmp);
1467 snprintf(tmp, sizeof tmp, "%u", myPid);
1468 Global_Set(".MAKE.PID", tmp);
1469 snprintf(tmp, sizeof tmp, "%u", getppid());
1470 Global_Set(".MAKE.PPID", tmp);
1471 snprintf(tmp, sizeof tmp, "%u", getuid());
1472 Global_Set(".MAKE.UID", tmp);
1473 snprintf(tmp, sizeof tmp, "%u", getgid());
1474 Global_Set(".MAKE.GID", tmp);
1476 /* DragonFly BSD specific global variables */
1479 * It was used to identify the compiler that built world so that
1480 * a c++ issue during an ABI change could be worked around.
1481 * More info on commit: 673bdc16bff3eec8
1483 Global_Set(".MAKE.BUILT.BY", CCVER);
1486 * Added to speed up dports builds since there would be no
1487 * evaluation needed if already defined.
1488 * More info on commit: a4cce4724800c918
1490 Global_Set(".MAKE.DF.VERSION", DFVER);
1491 Global_Set(".MAKE.DF.OSREL", OSREL);
1493 if (makelevel > 0) {
1495 snprintf(pn, sizeof pn, "%s[%d]", progname, makelevel);
1496 progname = bmake_strdup(pn);
1505 * First snag any flags out of the MAKE environment variable.
1506 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
1507 * in a different format).
1511 char *p1 = explode(getenv("MAKEFLAGS"));
1512 Main_ParseArgLine(p1);
1516 Main_ParseArgLine(getenv("MAKE"));
1520 * Find where we are (now).
1521 * We take care of PWD for the automounter below...
1523 if (getcwd(curdir, MAXPATHLEN) == NULL) {
1524 (void)fprintf(stderr, "%s: getcwd: %s.\n",
1525 progname, strerror(errno));
1529 MainParseArgs(argc, argv);
1532 printf("%s: Entering directory `%s'\n", progname, curdir);
1535 * Verify that cwd is sane.
1537 if (stat(curdir, &sa) == -1) {
1538 (void)fprintf(stderr, "%s: %s: %s.\n",
1539 progname, curdir, strerror(errno));
1543 #ifndef NO_PWD_OVERRIDE
1546 Global_Set(".CURDIR", curdir);
1548 InitObjdir(machine, machine_arch);
1551 * Initialize archive, target and suffix modules in preparation for
1552 * parsing the makefile(s)
1556 Trace_Init(tracefile);
1561 Trace_Log(MAKESTART, NULL);
1565 InitDefSysIncPath(syspath);
1569 * Read the system makefile followed by either makefile, Makefile or the
1570 * files given by the -f option. Exit on parse errors.
1573 main_ReadFiles(void)
1576 if (!opts.noBuiltins)
1579 if (!Lst_IsEmpty(&opts.makefiles))
1580 ReadAllMakefiles(&opts.makefiles);
1582 ReadFirstDefaultMakefile();
1585 /* Compute the dependency graph. */
1587 main_PrepareMaking(void)
1589 /* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
1590 if (!opts.noBuiltins || opts.printVars == PVM_NONE) {
1591 (void)Var_Subst("${.MAKE.DEPENDFILE}",
1592 SCOPE_CMDLINE, VARE_WANTRES, &makeDependfile);
1593 if (makeDependfile[0] != '\0') {
1594 /* TODO: handle errors */
1595 doing_depend = TRUE;
1596 (void)ReadMakefile(makeDependfile);
1597 doing_depend = FALSE;
1602 printf("%s: Entering directory `%s'\n", progname, objdir);
1607 FStr makeflags = Var_Value(SCOPE_GLOBAL, MAKEFLAGS);
1608 Global_Append("MFLAGS", makeflags.str);
1609 FStr_Done(&makeflags);
1615 * Be compatible if the user did not specify -j and did not explicitly
1616 * turn compatibility on.
1618 if (!opts.compatMake && !forceJobs)
1619 opts.compatMake = TRUE;
1621 if (!opts.compatMake)
1622 Job_ServerStart(maxJobTokens, jp_0, jp_1);
1623 DEBUG5(JOB, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n",
1624 jp_0, jp_1, opts.maxJobs, maxJobTokens, opts.compatMake ? 1 : 0);
1626 if (opts.printVars == PVM_NONE)
1627 Main_ExportMAKEFLAGS(TRUE); /* initial export */
1632 * Now that all search paths have been read for suffixes et al, it's
1633 * time to add the default search path to their lists...
1638 * Propagate attributes through :: dependency lists.
1642 /* print the initial graph, if the user requested it */
1649 * If the -v or -V options are given, print variables instead.
1650 * Return whether any of the targets is out-of-date.
1655 if (opts.printVars != PVM_NONE) {
1656 /* print the values of any variables requested by the user */
1660 return runTargets();
1664 /* Clean up after making the targets. */
1669 Lst_DoneCall(&opts.variables, free);
1671 * Don't free the actual strings from opts.makefiles, they may be
1674 Lst_Done(&opts.makefiles);
1675 Lst_DoneCall(&opts.create, free);
1678 /* print the graph now it's been processed if the user requested it */
1682 Trace_Log(MAKEEND, NULL);
1685 printf("%s: Leaving directory `%s'\n", progname, objdir);
1687 printf("%s: Leaving directory `%s'\n", progname, curdir);
1702 /* Determine the exit code. */
1704 main_Exit(Boolean outOfDate)
1706 if (opts.strict && (main_errors > 0 || Parse_GetFatals() > 0))
1707 return 2; /* Not 1 so -q can distinguish error */
1708 return outOfDate ? 1 : 0;
1712 main(int argc, char **argv)
1716 main_Init(argc, argv);
1718 main_PrepareMaking();
1719 outOfDate = main_Run();
1721 return main_Exit(outOfDate);
1725 * Open and parse the given makefile, with all its side effects.
1728 * 0 if ok. -1 if couldn't open file.
1731 ReadMakefile(const char *fname)
1734 char *name, *path = NULL;
1736 if (strcmp(fname, "-") == 0) {
1737 Parse_File(NULL /*stdin*/, -1);
1738 Var_Set(SCOPE_INTERNAL, "MAKEFILE", "");
1740 /* if we've chdir'd, rebuild the path name */
1741 if (strcmp(curdir, objdir) != 0 && *fname != '/') {
1742 path = str_concat3(curdir, "/", fname);
1743 fd = open(path, O_RDONLY);
1750 /* If curdir failed, try objdir (ala .depend) */
1751 path = str_concat3(objdir, "/", fname);
1752 fd = open(path, O_RDONLY);
1758 fd = open(fname, O_RDONLY);
1762 /* look in -I and system include directories. */
1763 name = Dir_FindFile(fname, parseIncPath);
1765 SearchPath *sysInc = Lst_IsEmpty(&sysIncPath->dirs)
1766 ? defSysIncPath : sysIncPath;
1767 name = Dir_FindFile(fname, sysInc);
1769 if (name == NULL || (fd = open(name, O_RDONLY)) == -1) {
1776 * set the MAKEFILE variable desired by System V fans -- the
1777 * placement of the setting here means it gets set to the last
1778 * makefile specified, as it is set by SysV make.
1782 Var_Set(SCOPE_INTERNAL, "MAKEFILE", fname);
1783 Parse_File(fname, fd);
1791 * Execute the command in cmd, and return the output of that command
1792 * in a string. In the output, newlines are replaced with spaces.
1795 * A string containing the output of the command, or the empty string.
1796 * *errfmt returns a format string describing the command failure,
1797 * if any, using a single %s conversion specification.
1800 * The string must be freed by the caller.
1803 Cmd_Exec(const char *cmd, const char **errfmt)
1805 const char *args[4]; /* Args for invoking the shell */
1807 int cpid; /* Child PID */
1808 int pid; /* PID from wait() */
1809 int status; /* command exit status */
1810 Buffer buf; /* buffer to store the result */
1812 char *res; /* result */
1815 int savederr; /* saved errno */
1819 if (shellName == NULL)
1822 * Set up arguments for shell
1824 args[0] = shellName;
1830 * Open a pipe for fetching its output
1832 if (pipe(pipefds) == -1) {
1833 *errfmt = "Couldn't create pipe for \"%s\"";
1842 switch (cpid = vfork()) {
1844 (void)close(pipefds[0]); /* Close input side of pipe */
1847 * Duplicate the output stream to the shell's output, then
1848 * shut the extra thing down. Note we don't fetch the error
1849 * stream...why not? Why?
1851 (void)dup2(pipefds[1], 1);
1852 (void)close(pipefds[1]);
1854 (void)execv(shellPath, UNCONST(args));
1859 *errfmt = "Couldn't exec \"%s\"";
1863 (void)close(pipefds[1]); /* No need for the writing half */
1869 char result[BUFSIZ];
1870 bytes_read = read(pipefds[0], result, sizeof result);
1872 Buf_AddBytes(&buf, result, (size_t)bytes_read);
1873 } while (bytes_read > 0 ||
1874 (bytes_read == -1 && errno == EINTR));
1875 if (bytes_read == -1)
1878 (void)close(pipefds[0]); /* Close the input side of the pipe. */
1880 /* Wait for the process to exit. */
1881 while ((pid = waitpid(cpid, &status, 0)) != cpid && pid >= 0)
1882 JobReapChild(pid, status, FALSE);
1885 res = Buf_DoneData(&buf);
1888 *errfmt = "Couldn't read shell's output for \"%s\"";
1890 if (WIFSIGNALED(status))
1891 *errfmt = "\"%s\" exited on a signal";
1892 else if (WEXITSTATUS(status) != 0)
1893 *errfmt = "\"%s\" returned non-zero status";
1895 /* Convert newlines to spaces. A final newline is just stripped */
1896 if (res_len > 0 && res[res_len - 1] == '\n')
1897 res[res_len - 1] = '\0';
1898 for (cp = res; *cp != '\0'; cp++)
1905 return bmake_strdup("");
1909 * Print a printf-style error message.
1911 * In default mode, this error message has no consequences, in particular it
1912 * does not affect the exit status. Only in lint mode (-dL) it does.
1915 Error(const char *fmt, ...)
1920 err_file = opts.debug_file;
1921 if (err_file == stdout)
1923 (void)fflush(stdout);
1926 fprintf(err_file, "%s: ", progname);
1927 (void)vfprintf(err_file, fmt, ap);
1929 (void)fprintf(err_file, "\n");
1930 (void)fflush(err_file);
1931 if (err_file == stderr)
1939 * Wait for any running jobs to finish, then produce an error message,
1940 * finally exit immediately.
1942 * Exiting immediately differs from Parse_Error, which exits only after the
1943 * current top-level makefile has been parsed completely.
1946 Fatal(const char *fmt, ...)
1953 (void)fflush(stdout);
1955 (void)vfprintf(stderr, fmt, ap);
1957 (void)fprintf(stderr, "\n");
1958 (void)fflush(stderr);
1960 PrintOnError(NULL, NULL);
1962 if (DEBUG(GRAPH2) || DEBUG(GRAPH3))
1964 Trace_Log(MAKEERROR, NULL);
1965 exit(2); /* Not 1 so -q can distinguish error */
1969 * Major exception once jobs are being created.
1970 * Kills all jobs, prints a message and exits.
1973 Punt(const char *fmt, ...)
1978 (void)fflush(stdout);
1979 (void)fprintf(stderr, "%s: ", progname);
1980 (void)vfprintf(stderr, fmt, ap);
1982 (void)fprintf(stderr, "\n");
1983 (void)fflush(stderr);
1985 PrintOnError(NULL, NULL);
1990 /* Exit without giving a message. */
1998 Trace_Log(MAKEERROR, NULL);
1999 exit(2); /* Not 1 so -q can distinguish error */
2003 * Called when aborting due to errors in child shell to signal abnormal exit.
2004 * The program exits.
2005 * Errors is the number of errors encountered in Make_Make.
2010 if (shouldDieQuietly(NULL, -1))
2012 Fatal("%d error%s", errs, errs == 1 ? "" : "s");
2017 * Remove a file carefully, avoiding directories.
2020 eunlink(const char *file)
2024 if (lstat(file, &st) == -1)
2027 if (S_ISDIR(st.st_mode)) {
2031 return unlink(file);
2035 write_all(int fd, const void *data, size_t n)
2037 const char *mem = data;
2040 ssize_t written = write(fd, mem, n);
2041 if (written == -1 && errno == EAGAIN)
2046 n -= (size_t)written;
2052 * Print why exec failed, avoiding stdio.
2055 execDie(const char *af, const char *av)
2060 Buf_AddStr(&buf, progname);
2061 Buf_AddStr(&buf, ": ");
2062 Buf_AddStr(&buf, af);
2063 Buf_AddStr(&buf, "(");
2064 Buf_AddStr(&buf, av);
2065 Buf_AddStr(&buf, ") failed (");
2066 Buf_AddStr(&buf, strerror(errno));
2067 Buf_AddStr(&buf, ")\n");
2069 write_all(STDERR_FILENO, buf.data, buf.len);
2075 /* purge any relative paths */
2077 purge_relative_cached_realpaths(void)
2079 HashEntry *he, *nhe;
2082 HashIter_Init(&hi, &cached_realpaths);
2083 he = HashIter_Next(&hi);
2084 while (he != NULL) {
2085 nhe = HashIter_Next(&hi);
2086 if (he->key[0] != '/') {
2087 DEBUG1(DIR, "cached_realpath: purging %s\n", he->key);
2088 HashTable_DeleteEntry(&cached_realpaths, he);
2089 /* XXX: What about the allocated he->value? Either
2090 * free them or document why they cannot be freed. */
2097 cached_realpath(const char *pathname, char *resolved)
2101 if (pathname == NULL || pathname[0] == '\0')
2104 rp = HashTable_FindValue(&cached_realpaths, pathname);
2107 strncpy(resolved, rp, MAXPATHLEN);
2108 resolved[MAXPATHLEN - 1] = '\0';
2112 rp = realpath(pathname, resolved);
2114 HashTable_Set(&cached_realpaths, pathname, bmake_strdup(rp));
2115 DEBUG2(DIR, "cached_realpath: %s -> %s\n", pathname, rp);
2119 /* should we negative-cache? */
2124 * Return true if we should die without noise.
2125 * For example our failing child was a sub-make or failure happened elsewhere.
2128 shouldDieQuietly(GNode *gn, int bf)
2130 static int quietly = -1;
2133 if (DEBUG(JOB) || !GetBooleanVar(".MAKE.DIE_QUIETLY", TRUE))
2138 quietly = (gn != NULL && (gn->type & OP_MAKE)) ? 1 : 0;
2140 return quietly != 0;
2144 SetErrorVars(GNode *gn)
2149 * We can print this even if there is no .ERROR target.
2151 Global_Set(".ERROR_TARGET", gn->name);
2152 Global_Delete(".ERROR_CMD");
2154 for (ln = gn->commands.first; ln != NULL; ln = ln->next) {
2155 const char *cmd = ln->datum;
2159 Global_Append(".ERROR_CMD", cmd);
2164 * Print some helpful information in case of an error.
2165 * The caller should exit soon after calling this function.
2168 PrintOnError(GNode *gn, const char *msg)
2170 static GNode *errorNode = NULL;
2177 if (errorNode != NULL)
2178 return; /* we've been here! */
2182 printf("\n%s: stopped in %s\n", progname, curdir);
2184 /* we generally want to keep quiet if a sub-make died */
2185 if (shouldDieQuietly(gn, -1))
2192 char *errorVarsValues;
2193 (void)Var_Subst("${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
2194 SCOPE_GLOBAL, VARE_WANTRES, &errorVarsValues);
2195 /* TODO: handle errors */
2196 printf("%s", errorVarsValues);
2197 free(errorVarsValues);
2203 * Finally, see if there is a .ERROR target, and run it if so.
2205 errorNode = Targ_FindNode(".ERROR");
2206 if (errorNode != NULL) {
2207 errorNode->type |= OP_SPECIAL;
2208 Compat_Make(errorNode, errorNode);
2213 Main_ExportMAKEFLAGS(Boolean first)
2215 static Boolean once = TRUE;
2223 expr = "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}";
2224 (void)Var_Subst(expr, SCOPE_CMDLINE, VARE_WANTRES, &s);
2225 /* TODO: handle errors */
2228 setenv("MAKEFLAGS", s, 1);
2230 setenv("MAKE", s, 1);
2238 static char *tmpdir = NULL;
2244 /* Honor $TMPDIR but only if it is valid. Ensure it ends with '/'. */
2245 (void)Var_Subst("${TMPDIR:tA:U" _PATH_TMP "}/",
2246 SCOPE_GLOBAL, VARE_WANTRES, &tmpdir);
2247 /* TODO: handle errors */
2249 if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
2251 tmpdir = bmake_strdup(_PATH_TMP);
2257 * Create and open a temp file using "pattern".
2258 * If out_fname is provided, set it to a copy of the filename created.
2259 * Otherwise unlink the file once open.
2262 mkTempFile(const char *pattern, char *tfile, size_t tfile_sz)
2264 static char *tmpdir = NULL;
2265 char tbuf[MAXPATHLEN];
2268 if (pattern == NULL)
2271 tmpdir = getTmpdir();
2272 if (tfile == NULL) {
2274 tfile_sz = sizeof tbuf;
2276 if (pattern[0] == '/') {
2277 snprintf(tfile, tfile_sz, "%s", pattern);
2279 snprintf(tfile, tfile_sz, "%s%s", tmpdir, pattern);
2281 if ((fd = mkstemp(tfile)) < 0)
2282 Punt("Could not create temporary file %s: %s", tfile,
2284 if (tfile == tbuf) {
2285 unlink(tfile); /* we just want the descriptor */
2291 * Convert a string representation of a boolean into a boolean value.
2292 * Anything that looks like "No", "False", "Off", "0" etc. is FALSE,
2293 * the empty string is the fallback, everything else is TRUE.
2296 ParseBoolean(const char *s, Boolean fallback)
2298 char ch = ch_tolower(s[0]);
2301 if (ch == '0' || ch == 'f' || ch == 'n')
2304 return ch_tolower(s[1]) != 'f';