Add ifmedia(4) reference.
[dragonfly/netmp.git] / usr.bin / make / main.c
blob5294f03675351485619771521b8c497fdf5d6712
1 /*-
2 * Copyright (c) 1988, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1989 by Berkeley Softworks
5 * All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
38 * @(#) Copyright (c) 1988, 1989, 1990, 1993 The Regents of the University of California. All rights reserved.
39 * @(#)main.c 8.3 (Berkeley) 3/19/94
40 * $FreeBSD: src/usr.bin/make/main.c,v 1.118 2005/02/13 13:33:56 harti Exp $
41 * $DragonFly: src/usr.bin/make/main.c,v 1.146 2007/01/19 07:23:43 dillon Exp $
45 * main.c
46 * The main file for this entire program. Exit routines etc
47 * reside here.
49 * Utility functions defined in this file:
50 * Main_ParseArgLine
51 * Takes a line of arguments, breaks them and
52 * treats them as if they were given when first
53 * invoked. Used by the parse module to implement
54 * the .MFLAGS target.
57 #ifndef MACHINE
58 #include <sys/utsname.h>
59 #endif
60 #include <sys/param.h>
61 #include <sys/stat.h>
62 #include <sys/sysctl.h>
63 #include <sys/time.h>
64 #include <sys/queue.h>
65 #include <sys/resource.h>
66 #include <sys/wait.h>
67 #include <err.h>
68 #include <errno.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <unistd.h>
73 #include "arch.h"
74 #include "buf.h"
75 #include "config.h"
76 #include "dir.h"
77 #include "globals.h"
78 #include "job.h"
79 #include "make.h"
80 #include "parse.h"
81 #include "pathnames.h"
82 #include "shell.h"
83 #include "str.h"
84 #include "suff.h"
85 #include "targ.h"
86 #include "util.h"
87 #include "var.h"
89 extern char **environ; /* XXX what header declares this variable? */
92 * DEFMAXJOBS
93 * This control the default concurrency. On no occasion will more
94 * than DEFMAXJOBS targets be created at once.
96 #define DEFMAXJOBS 1
98 typedef struct CLI {
99 /** ordered list of makefiles to read */
100 Lst makefiles;
102 /** list of variables to print */
103 Lst variables;
105 /** Targets to be made */
106 Lst create;
108 /** directories to search when looking for includes */
109 struct Path parseIncPath;
111 /** directories to search when looking for system includes */
112 struct Path sysIncPath;
114 bool expandVars; /* fully expand printed variables */
115 bool builtins; /* -r flag */
116 bool forceJobs; /* -j argument given */
119 * -q flag:
120 * true if we aren't supposed to really make anything, just
121 * see if the targets are out-of-date
123 bool queryFlag;
124 } CLI;
126 /* (-E) vars to override from env */
127 Lst envFirstVars = Lst_Initializer(envFirstVars);
129 bool allPrecious; /* .PRECIOUS given on line by itself */
130 bool beSilent; /* -s flag */
131 bool beVerbose; /* -v flag */
132 bool compatMake; /* -B argument */
133 int debug; /* -d flag */
134 bool ignoreErrors; /* -i flag */
135 int jobLimit; /* -j argument */
136 bool jobsRunning; /* true if the jobs might be running */
137 bool keepgoing; /* -k flag */
138 bool noExecute; /* -n flag */
139 bool touchFlag; /* -t flag */
140 bool usePipes; /* !-P flag */
141 uint32_t warn_cmd; /* command line warning flags */
142 uint32_t warn_flags; /* actual warning flags */
143 uint32_t warn_nocmd; /* command line no-warning flags */
145 time_t now; /* Time at start of make */
146 struct GNode *DEFAULT; /* .DEFAULT node */
150 * Exit with usage message.
152 static void
153 usage(void)
155 fprintf(stderr,
156 "usage: make [-BPSXeiknqrstv] [-C directory] [-D variable]\n"
157 "\t[-d flags] [-E variable] [-f makefile] [-I directory]\n"
158 "\t[-j max_jobs] [-m directory] [-V variable]\n"
159 "\t[variable=value] [target ...]\n");
160 exit(2);
164 * MFLAGS_append
165 * Append a flag with an optional argument to MAKEFLAGS and MFLAGS
167 static void
168 MFLAGS_append(const char *flag, char *arg)
170 char *str;
172 Var_Append(".MAKEFLAGS", flag, VAR_GLOBAL);
173 if (arg != NULL) {
174 str = MAKEFLAGS_quote(arg);
175 Var_Append(".MAKEFLAGS", str, VAR_GLOBAL);
176 free(str);
179 Var_Append("MFLAGS", flag, VAR_GLOBAL);
180 if (arg != NULL) {
181 str = MAKEFLAGS_quote(arg);
182 Var_Append("MFLAGS", str, VAR_GLOBAL);
183 free(str);
188 * Open and parse the given makefile.
190 * Results:
191 * true if ok. false if couldn't open file.
193 static bool
194 ReadMakefile(Parser *parser, CLI *cli, const char file[], const char curdir[], const char objdir[])
196 char path[MAXPATHLEN];
197 FILE *stream;
198 char *fname;
199 char *name;
201 if (!strcmp(file, "-")) {
202 Parse_File(parser, cli, "(stdin)", stdin);
203 Var_SetGlobal("MAKEFILE", "");
204 return (true);
207 if (strcmp(curdir, objdir) == 0 || file[0] == '/') {
208 strcpy(path, file);
209 } else {
211 * we've chdir'd, rebuild the path name
213 snprintf(path, MAXPATHLEN, "%s/%s", curdir, file);
215 #if THIS_BREAKS_THINGS
217 * XXX The realpath stuff breaks relative includes
218 * XXX in some cases. The problem likely is in
219 * XXX parse.c where it does special things in
220 * XXX ParseDoInclude if the file is relateive
221 * XXX or absolute and not a system file. There
222 * XXX it assumes that if the current file that's
223 * XXX being included is absolute, that any files
224 * XXX that it includes shouldn't do the -I path
225 * XXX stuff, which is inconsistant with historical
226 * XXX behavior. However, I can't pentrate the mists
227 * XXX further, so I'm putting this workaround in
228 * XXX here until such time as the underlying bug
229 * XXX can be fixed.
231 if (realpath(path, path) == NULL) {
232 stream = NULL;
233 } else {
234 stream = fopen(path, "r");
236 #else
237 stream = fopen(path, "r");
238 #endif
239 if (stream != NULL) {
240 if (strcmp(file, ".depend") != 0)
241 Var_SetGlobal("MAKEFILE", file);
242 Parse_File(parser, cli, path, stream);
243 fclose(stream);
244 return (true);
247 /* look in -I and system include directories. */
248 fname = estrdup(file);
249 name = NULL;
250 if (name == NULL)
251 name = Path_FindFile(fname, &cli->parseIncPath);
252 if (name == NULL)
253 name = Path_FindFile(fname, &cli->sysIncPath);
255 if (name != NULL) {
256 stream = fopen(name, "r");
257 if (stream != NULL) {
259 * set the MAKEFILE variable desired by System V fans
260 * -- the placement of the setting here means it gets
261 * set to the last makefile specified, as it is set
262 * by SysV make.
264 if (strcmp(file, ".depend") != 0)
265 Var_SetGlobal("MAKEFILE", name);
266 Parse_File(parser, cli, name, stream);
267 fclose(stream);
268 return (true);
272 return (false); /* no makefile found */
276 * Read in the built-in rules first, followed by the specified
277 * makefiles or the one of the default makefiles. Finally .depend
278 * makefile.
280 static void
281 ReadInputFiles(Parser *parser, CLI *cli, const char curdir[], const char objdir[])
283 if (cli->builtins) {
284 char defsysmk[] = PATH_DEFSYSMK; /* Path of sys.mk */
285 Lst sysMkPath = Lst_Initializer(sysMkPath);
286 LstNode *ln;
288 Path_Expand(defsysmk, &cli->sysIncPath, &sysMkPath);
289 if (Lst_IsEmpty(&sysMkPath))
290 Fatal("make: no system rules (%s).", PATH_DEFSYSMK);
292 LST_FOREACH(ln, &sysMkPath) {
293 char *name = Lst_Datum(ln);
294 if (!ReadMakefile(parser, cli, name, curdir, objdir))
295 Fatal("make: cannot open %s.", name);
297 Lst_Destroy(&sysMkPath, free);
300 if (!Lst_IsEmpty(&cli->makefiles)) {
301 LstNode *ln;
303 LST_FOREACH(ln, &cli->makefiles) {
304 char *name = Lst_Datum(ln);
305 if (!ReadMakefile(parser, cli, name, curdir, objdir))
306 Fatal("make: cannot open %s.", name);
308 } else if (ReadMakefile(parser, cli, "BSDmakefile", curdir, objdir)) {
309 /* read BSDmakefile */
310 } else if (ReadMakefile(parser, cli, "makefile", curdir, objdir)) {
311 /* read makefile */
312 } else if (ReadMakefile(parser, cli, "Makefile", curdir, objdir)) {
313 /* read Makefile */
314 } else {
315 /* No Makefile found */
318 ReadMakefile(parser, cli, ".depend", curdir, objdir);
322 * Main_ParseWarn
324 * Handle argument to warning option.
327 Main_ParseWarn(const char *arg, int iscmd)
329 int i, neg;
331 static const struct {
332 const char *option;
333 uint32_t flag;
334 } options[] = {
335 { "dirsyntax", WARN_DIRSYNTAX },
336 { NULL, 0 }
339 neg = 0;
340 if (arg[0] == 'n' && arg[1] == 'o') {
341 neg = 1;
342 arg += 2;
345 for (i = 0; options[i].option != NULL; i++)
346 if (strcmp(arg, options[i].option) == 0)
347 break;
349 if (options[i].option == NULL)
350 /* unknown option */
351 return (-1);
353 if (iscmd) {
354 if (!neg) {
355 warn_cmd |= options[i].flag;
356 warn_nocmd &= ~options[i].flag;
357 warn_flags |= options[i].flag;
358 } else {
359 warn_nocmd |= options[i].flag;
360 warn_cmd &= ~options[i].flag;
361 warn_flags &= ~options[i].flag;
363 } else {
364 if (!neg) {
365 warn_flags |= (options[i].flag & ~warn_nocmd);
366 } else {
367 warn_flags &= ~(options[i].flag | warn_cmd);
370 return (0);
374 * MainParseArgs
375 * Parse a given argument vector. Called from main() and from
376 * Main_ParseArgLine() when the .MAKEFLAGS target is used.
378 * XXX: Deal with command line overriding .MAKEFLAGS in makefile
380 * Side Effects:
381 * Various global and local flags will be set depending on the flags
382 * given
384 static void
385 MainParseArgs(CLI *cli, int argc, char **argv)
387 int c;
388 bool found_dd = false;
390 rearg:
391 optind = 1; /* since we're called more than once */
392 optreset = 1;
393 #define OPTFLAGS "ABC:D:E:I:PSV:Xd:ef:ij:km:nqrstvx:"
394 for (;;) {
395 if ((optind < argc) && strcmp(argv[optind], "--") == 0) {
396 found_dd = true;
398 if ((c = getopt(argc, argv, OPTFLAGS)) == -1) {
399 break;
401 switch(c) {
403 case 'A':
404 arch_fatal = false;
405 MFLAGS_append("-A", NULL);
406 break;
407 case 'C':
408 if (chdir(optarg) == -1)
409 err(1, "chdir %s", optarg);
410 break;
411 case 'D':
412 Var_SetGlobal(optarg, "1");
413 MFLAGS_append("-D", optarg);
414 break;
415 case 'I':
416 Path_AddDir(&cli->parseIncPath, optarg);
417 MFLAGS_append("-I", optarg);
418 break;
419 case 'V':
420 Lst_AtEnd(&cli->variables, estrdup(optarg));
421 MFLAGS_append("-V", optarg);
422 break;
423 case 'X':
424 cli->expandVars = false;
425 break;
426 case 'B':
427 compatMake = true;
428 MFLAGS_append("-B", NULL);
429 unsetenv("MAKE_JOBS_FIFO");
430 break;
431 case 'P':
432 usePipes = false;
433 MFLAGS_append("-P", NULL);
434 break;
435 case 'S':
436 keepgoing = false;
437 MFLAGS_append("-S", NULL);
438 break;
439 case 'd': {
440 char *modules = optarg;
442 for (; *modules; ++modules)
443 switch (*modules) {
444 case 'A':
445 debug = ~0;
446 break;
447 case 'a':
448 debug |= DEBUG_ARCH;
449 break;
450 case 'c':
451 debug |= DEBUG_COND;
452 break;
453 case 'd':
454 debug |= DEBUG_DIR;
455 break;
456 case 'f':
457 debug |= DEBUG_FOR;
458 break;
459 case 'g':
460 if (modules[1] == '1') {
461 debug |= DEBUG_GRAPH1;
462 ++modules;
464 else if (modules[1] == '2') {
465 debug |= DEBUG_GRAPH2;
466 ++modules;
468 break;
469 case 'j':
470 debug |= DEBUG_JOB;
471 break;
472 case 'l':
473 debug |= DEBUG_LOUD;
474 break;
475 case 'm':
476 debug |= DEBUG_MAKE;
477 break;
478 case 's':
479 debug |= DEBUG_SUFF;
480 break;
481 case 't':
482 debug |= DEBUG_TARG;
483 break;
484 case 'v':
485 debug |= DEBUG_VAR;
486 break;
487 default:
488 warnx("illegal argument to d option "
489 "-- %c", *modules);
490 usage();
492 MFLAGS_append("-d", optarg);
493 break;
495 case 'E':
496 Lst_AtEnd(&envFirstVars, estrdup(optarg));
497 MFLAGS_append("-E", optarg);
498 break;
499 case 'e':
500 checkEnvFirst = true;
501 MFLAGS_append("-e", NULL);
502 break;
503 case 'f':
504 Lst_AtEnd(&cli->makefiles, estrdup(optarg));
505 break;
506 case 'i':
507 ignoreErrors = true;
508 MFLAGS_append("-i", NULL);
509 break;
510 case 'j': {
511 char *endptr;
513 cli->forceJobs = true;
514 jobLimit = strtol(optarg, &endptr, 10);
515 if (jobLimit <= 0 || *endptr != '\0') {
516 warnx("illegal number, -j argument -- %s",
517 optarg);
518 usage();
520 MFLAGS_append("-j", optarg);
521 break;
523 case 'k':
524 keepgoing = true;
525 MFLAGS_append("-k", NULL);
526 break;
527 case 'm':
528 Path_AddDir(&cli->sysIncPath, optarg);
529 MFLAGS_append("-m", optarg);
530 break;
531 case 'n':
532 noExecute = true;
533 MFLAGS_append("-n", NULL);
534 break;
535 case 'q':
536 cli->queryFlag = true;
537 /* Kind of nonsensical, wot? */
538 MFLAGS_append("-q", NULL);
539 break;
540 case 'r':
541 cli->builtins = false;
542 MFLAGS_append("-r", NULL);
543 break;
544 case 's':
545 beSilent = true;
546 MFLAGS_append("-s", NULL);
547 break;
548 case 't':
549 touchFlag = true;
550 MFLAGS_append("-t", NULL);
551 break;
552 case 'v':
553 beVerbose = true;
554 MFLAGS_append("-v", NULL);
555 break;
556 case 'x':
557 if (Main_ParseWarn(optarg, 1) != -1)
558 MFLAGS_append("-x", optarg);
559 break;
560 default:
561 case '?':
562 usage();
565 argv += optind;
566 argc -= optind;
568 oldVars = true;
571 * Parse the rest of the arguments.
572 * o Check for variable assignments and perform them if so.
573 * o Check for more flags and restart getopt if so.
574 * o Anything else is taken to be a target and added
575 * to the end of the "create" list.
577 for (; *argv != NULL; ++argv, --argc) {
578 if (Parse_IsVar(*argv)) {
579 char *ptr = MAKEFLAGS_quote(*argv);
581 Var_Append(".MAKEFLAGS", ptr, VAR_GLOBAL);
582 Parse_DoVar(*argv, VAR_CMD);
583 free(ptr);
585 } else if ((*argv)[0] == '-') {
586 if ((*argv)[1] == '\0') {
588 * (*argv) is a single dash, so we
589 * just ignore it.
591 } else if (found_dd) {
593 * Double dash has been found, ignore
594 * any more options. But what do we do
595 * with it? For now treat it like a target.
597 Lst_AtEnd(&cli->create, estrdup(*argv));
598 } else {
600 * (*argv) is a -flag, so backup argv and
601 * argc. getopt() expects options to start
602 * in the 2nd position.
604 argc++;
605 argv--;
606 goto rearg;
609 } else if ((*argv)[0] == '\0') {
610 Punt("illegal (null) argument.");
612 } else {
613 Lst_AtEnd(&cli->create, estrdup(*argv));
619 * Main_ParseArgLine
620 * Used by the parse module when a .MFLAGS or .MAKEFLAGS target
621 * is encountered and by main() when reading the .MAKEFLAGS envariable.
622 * Takes a line of arguments and breaks it into its
623 * component words and passes those words and the number of them to the
624 * MainParseArgs function.
625 * The line should have all its leading whitespace removed.
627 * Side Effects:
628 * Only those that come from the various arguments.
630 void
631 Main_ParseArgLine(CLI *cli, const char line[], int mflags)
633 ArgArray aa;
635 if (mflags) {
636 MAKEFLAGS_break(&aa, line);
637 } else {
638 brk_string(&aa, line, true);
640 MainParseArgs(cli, aa.argc, aa.argv);
641 ArgArray_Done(&aa);
645 * Try to change the current working directory to path, and return
646 * the whole path using getcwd().
648 * @note for amd managed mount points we really should use pawd(1).
650 static int
651 CheckDir(const char path[], char newdir[])
653 struct stat sb;
656 * Check if the path is a directory. If not fail without reporting
657 * an error.
659 if (stat(path, &sb) < 0) {
660 return (0);
662 if (S_ISDIR(sb.st_mode) == 0) {
663 return (0);
667 * The path refers to a directory, so we try to change into it. If we
668 * fail, or we fail to obtain the path from root to the directory,
669 * then report an error and fail.
671 if (chdir(path) < 0) {
672 warn("warning: %s", path);
673 return (0);
675 if (getcwd(newdir, MAXPATHLEN) == NULL) {
676 warn("warning: %s", path);
677 return (0);
681 * Directory in path is accessable, newdir should now contain the
682 * path to it.
684 return (1);
688 * Determine location of the object directory.
690 static void
691 FindObjDir(const char machine[], char curdir[], char objdir[])
693 struct stat sa;
694 char newdir[MAXPATHLEN];
695 char mdpath[MAXPATHLEN];
696 const char *env;
699 * Find a path to where we are... [-C directory] might have changed
700 * our current directory.
702 if (getcwd(curdir, MAXPATHLEN) == NULL)
703 err(2, NULL);
705 if (stat(curdir, &sa) == -1)
706 err(2, "%s", curdir);
709 * The object directory location is determined using the
710 * following order of preference:
712 * 1. MAKEOBJDIRPREFIX`cwd`
713 * 2. MAKEOBJDIR
714 * 3. PATH_OBJDIR.${MACHINE}
715 * 4. PATH_OBJDIR
716 * 5. PATH_OBJDIRPREFIX`cwd`
718 * If one of the first two fails, use the current directory.
719 * If the remaining three all fail, use the current directory.
721 if ((env = getenv("MAKEOBJDIRPREFIX")) != NULL) {
722 snprintf(mdpath, MAXPATHLEN, "%s%s", env, curdir);
723 if (CheckDir(mdpath, newdir)) {
724 strcpy(objdir, newdir);
725 return;
727 strcpy(objdir, curdir);
728 return;
731 if ((env = getenv("MAKEOBJDIR")) != NULL) {
732 if (CheckDir(env, newdir)) {
733 strcpy(objdir, newdir);
734 return;
736 strcpy(objdir, curdir);
737 return;
740 snprintf(mdpath, MAXPATHLEN, "%s.%s", PATH_OBJDIR, machine);
741 if (CheckDir(mdpath, newdir)) {
742 strcpy(objdir, newdir);
743 return;
746 if (CheckDir(PATH_OBJDIR, newdir)) {
747 strcpy(objdir, newdir);
748 return;
751 snprintf(mdpath, MAXPATHLEN, "%s%s", PATH_OBJDIRPREFIX, curdir);
752 if (CheckDir(mdpath, newdir)) {
753 strcpy(objdir, newdir);
754 return;
757 strcpy(objdir, curdir);
761 * Initialize various make variables.
762 * MAKE also gets this name, for compatibility
763 * .MAKEFLAGS gets set to the empty string just in case.
764 * MFLAGS also gets initialized empty, for compatibility.
766 static void
767 InitVariables(const char progname[])
769 const char *machine_platform;
770 const char *machine_arch;
771 const char *machine;
772 char buf[256];
773 size_t bufsiz;
775 Var_SetGlobal("MAKE", progname);
776 Var_SetGlobal(".MAKEFLAGS", "");
777 Var_SetGlobal("MFLAGS", "");
779 Var_SetGlobal(".DIRECTIVE_MAKEENV", "YES");
780 Var_SetGlobal(".ST_EXPORTVAR", "YES");
781 #ifdef MAKE_VERSION
782 Var_SetGlobal("MAKE_VERSION", MAKE_VERSION);
783 #endif
786 * The make program defines MACHINE_PLATFORM, MACHINE and MACHINE_ARCH.
787 * These parameters are taken from the running system but can be
788 * overridden by environment variables.
790 * MACHINE_PLATFORM
791 * - This is the platform, e.g. "vkernel", "pc32",
792 * and so forth.
794 * MACHINE - This is the machine architecture and in most
795 * cases is the same as the cpu architecture.
797 * MACHINE_ARCH - This is the cpu architecture, for example "i386".
798 * Several different platforms may use the same
799 * cpu architecture.
801 * In most, but not all cases, MACHINE == MACHINE_ARCH.
803 * PLATFORM distinguishes differences between, say, a virtual kernel
804 * build and a real kernel build.
806 if ((machine_platform = getenv("MACHINE_PLATFORM")) == NULL) {
807 bufsiz = sizeof(buf);
808 if (sysctlbyname("hw.platform", buf, &bufsiz, NULL, 0) < 0)
809 machine_platform = "unknown";
810 else
811 machine_platform = strdup(buf);
814 if ((machine = getenv("MACHINE")) == NULL) {
815 bufsiz = sizeof(buf);
816 if (sysctlbyname("hw.machine", buf, &bufsiz, NULL, 0) < 0)
817 machine = "unknown";
818 else
819 machine = strdup(buf);
822 if ((machine_arch = getenv("MACHINE_ARCH")) == NULL) {
823 bufsiz = sizeof(buf);
824 if (sysctlbyname("hw.machine_arch", buf, &bufsiz, NULL, 0) < 0)
825 machine_arch = "unknown";
826 else
827 machine_arch = strdup(buf);
830 Var_SetGlobal("MACHINE_PLATFORM", machine_platform);
831 Var_SetGlobal("MACHINE", machine);
832 Var_SetGlobal("MACHINE_ARCH", machine_arch);
836 * Build targets given in the command line or if none were given
837 * use the main target determined by the parsing module.
839 static int
840 BuildStuff(CLI *cli)
842 int status;
843 Lst targs = Lst_Initializer(targs);
845 if (Lst_IsEmpty(&cli->create))
846 Parse_MainName(&targs);
847 else
848 Targ_FindList(&targs, &cli->create, TARG_CREATE);
850 /* Traverse the graph, checking on all the targets */
851 if (compatMake) {
852 Sig_Init(true);
853 status = Compat_Run(&targs, cli->queryFlag);
854 } else {
855 Sig_Init(false);
856 status = Make_Run(&targs, cli->queryFlag);
859 Lst_Destroy(&targs, NOFREE);
860 return (status);
864 * main
865 * The main function, for obvious reasons. Initializes variables
866 * and a few modules, then parses the arguments give it in the
867 * environment and on the command line. Reads the system makefile
868 * followed by either Makefile, makefile or the file given by the
869 * -f argument. Sets the .MAKEFLAGS PMake variable based on all the
870 * flags it has received by then uses either the Make or the Compat
871 * module to create the initial list of targets.
873 * Results:
874 * If -q was given, exits -1 if anything was out-of-date. Else it exits
875 * 0.
877 * Side Effects:
878 * The program exits when done. Targets are created. etc. etc. etc.
881 main(int argc, char **argv)
883 CLI cli;
884 Parser parser;
885 Shell *shell;
886 int status; /* exit status */
887 char curdir[MAXPATHLEN]; /* startup directory */
888 char objdir[MAXPATHLEN]; /* where we chdir'ed to */
889 const char *make_flags;
891 /*------------------------------------------------------------*
892 * This section initializes stuff that require no input.
893 *------------------------------------------------------------*/
895 * Initialize program globals.
897 beSilent = false; /* Print commands as executed */
898 ignoreErrors = false; /* Pay attention to non-zero returns */
899 noExecute = false; /* Execute all commands */
900 keepgoing = false; /* Stop on error */
901 allPrecious = false; /* Remove targets when interrupted */
902 touchFlag = false; /* Actually update targets */
903 usePipes = true; /* Catch child output in pipes */
904 debug = 0; /* No debug verbosity, please. */
905 jobsRunning = false;
907 jobLimit = DEFMAXJOBS;
908 compatMake = false; /* No compat mode */
911 * Initialize program flags.
913 Lst_Init(&cli.makefiles);
914 Lst_Init(&cli.variables);
915 Lst_Init(&cli.create);
916 TAILQ_INIT(&cli.parseIncPath);
917 TAILQ_INIT(&cli.sysIncPath);
919 cli.expandVars = true;
920 cli.builtins = true; /* Read the built-in rules */
921 cli.queryFlag = false;
922 cli.forceJobs = false;
924 shell = Shell_Match(DEFSHELLNAME);
927 * Initialize the various modules.
929 Proc_Init();
930 commandShell = shell;
931 Targ_Init();
932 Suff_Init();
933 Dir_Init();
935 /*------------------------------------------------------------*
936 * This section initializes stuff that depend on things
937 * in the enviornment, command line, or a input file.
938 *------------------------------------------------------------*/
939 Var_Init(environ);
941 InitVariables(argv[0]);
944 * First snag things out of the MAKEFLAGS environment
945 * variable. Then parse the command line arguments.
947 if ((make_flags = getenv("MAKEFLAGS")) != NULL) {
948 Main_ParseArgLine(&cli, make_flags, 1);
950 MainParseArgs(&cli, argc, argv);
952 FindObjDir(Var_Value("MACHINE", VAR_GLOBAL), curdir, objdir);
953 Var_SetGlobal(".CURDIR", curdir);
954 Var_SetGlobal(".OBJDIR", objdir);
957 * Set up the .TARGETS variable to contain the list of targets to be
958 * created. If none specified, make the variable empty -- the parser
959 * will fill the thing in with the default or .MAIN target.
961 if (Lst_IsEmpty(&cli.create)) {
962 Var_SetGlobal(".TARGETS", "");
963 } else {
964 LstNode *ln;
966 LST_FOREACH(ln, &cli.create) {
967 char *name = Lst_Datum(ln);
969 Var_Append(".TARGETS", name, VAR_GLOBAL);
973 Dir_CurObj(curdir, objdir);
976 * If no user-supplied system path was given (through the -m option)
977 * add the directories from the DEFSYSPATH (more than one may be given
978 * as dir1:...:dirn) to the system include path.
980 if (TAILQ_EMPTY(&cli.sysIncPath)) {
981 char syspath[] = PATH_DEFSYSPATH;
982 char *start = syspath;
983 char *cp;
985 while ((cp = strsep(&start, ":")) != NULL) {
986 Path_AddDir(&cli.sysIncPath, cp);
990 if (getenv("MAKE_JOBS_FIFO") != NULL)
991 cli.forceJobs = true;
994 * Be compatible if user did not specify -j and did not explicitly
995 * turned compatibility on
997 if (compatMake == false && cli.forceJobs == false)
998 compatMake = true;
1000 DEFAULT = NULL;
1001 time(&now);
1003 parser.create = &cli.create;
1004 parser.parseIncPath = &cli.parseIncPath;
1005 parser.sysIncPath = &cli.sysIncPath;
1007 ReadInputFiles(&parser, &cli, curdir, objdir);
1009 /*------------------------------------------------------------*
1010 * We are finished processing inputs.
1011 *------------------------------------------------------------*/
1013 /* Install all the flags into the MAKE envariable. */
1015 const char *p;
1017 p = Var_Value(".MAKEFLAGS", VAR_GLOBAL);
1018 if (p != NULL && *p != '\0') {
1019 if (setenv("MAKEFLAGS", p, 1) == -1)
1020 Punt("setenv: MAKEFLAGS: can't allocate memory");
1025 * For compatibility, look at the directories in the VPATH variable
1026 * and add them to the search path, if the variable is defined. The
1027 * variable's value is in the same format as the PATH envariable, i.e.
1028 * <directory>:<directory>:<directory>...
1030 if (Var_Value("VPATH", VAR_CMD) != NULL) {
1031 Buffer *buf = Var_Subst("${VPATH}", VAR_CMD, false);
1032 char *start = Buf_Data(buf);
1033 char *cp;
1035 while ((cp = strsep(&start, ":")) != NULL) {
1036 Path_AddDir(&dirSearchPath, cp);
1039 Buf_Destroy(buf, true);
1043 * Now that all search paths have been read for suffixes et al, it's
1044 * time to add the default search path to their lists...
1046 Suff_DoPaths();
1048 /* print the initial graph, if the user requested it */
1049 if (DEBUG(GRAPH1))
1050 Targ_PrintGraph(1);
1052 if (Lst_IsEmpty(&cli.variables)) {
1053 status = BuildStuff(&cli);
1054 } else {
1055 /* Print the values of variables requested by the user. */
1056 Var_Print(&cli.variables, cli.expandVars);
1059 * XXX
1060 * This should be a "don't care", we do not check
1061 * the status of any files. It might make sense to
1062 * modify Var_Print() to indicate that one of the
1063 * requested variables did not exist, and use that
1064 * as the return status.
1065 * XXX
1067 status = cli.queryFlag ? 1 : 0;
1070 /* print the graph now it's been processed if the user requested it */
1071 if (DEBUG(GRAPH2))
1072 Targ_PrintGraph(2);
1074 #if 0
1075 TAILQ_DESTROY(&cli.sysIncPath);
1076 TAILQ_DESTROY(&cli.parseIncPath);
1077 #endif
1078 Lst_Destroy(&cli.create, free);
1079 Lst_Destroy(&cli.variables, free);
1080 Lst_Destroy(&cli.makefiles, free);
1082 return (status);