bug 2450: Allow build of RELEASE 3.2 from master's bmake
[dragonfly.git] / usr.bin / make / main.c
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.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Adam de Boor.
9  *
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.
25  *
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.
37  *
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 $
42  */
43
44 /*
45  * main.c
46  *      The main file for this entire program. Exit routines etc
47  *      reside here.
48  *
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.
55  */
56
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>
72
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"
88
89 extern char **environ;  /* XXX what header declares this variable? */
90
91 /*
92  * DEFMAXJOBS
93  *      This control the default concurrency. On no occasion will more
94  *      than DEFMAXJOBS targets be created at once.
95  */
96 #define DEFMAXJOBS      1
97
98 typedef struct CLI {
99         /** ordered list of makefiles to read */
100         Lst makefiles;
101
102         /** list of variables to print */
103         Lst variables;
104
105         /** Targets to be made */
106         Lst create;
107
108         /** directories to search when looking for includes */
109         struct Path     parseIncPath;
110
111         /** directories to search when looking for system includes */
112         struct Path     sysIncPath;
113
114         bool    expandVars;     /* fully expand printed variables */
115         bool    builtins;       /* -r flag */
116         bool    forceJobs;      /* -j argument given */
117
118         /**
119          * -q flag:
120          * true if we aren't supposed to really make anything, just
121          * see if the targets are out-of-date
122          */
123         bool            queryFlag;
124 } CLI;
125
126 /* (-E) vars to override from env */
127 Lst envFirstVars = Lst_Initializer(envFirstVars);
128
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 */
144
145 time_t          now;            /* Time at start of make */
146 struct GNode    *DEFAULT;       /* .DEFAULT node */
147
148
149 /**
150  * Exit with usage message.
151  */
152 static void
153 usage(void)
154 {
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);
161 }
162
163 /**
164  * MFLAGS_append
165  *      Append a flag with an optional argument to MAKEFLAGS and MFLAGS
166  */
167 static void
168 MFLAGS_append(const char *flag, char *arg)
169 {
170         char *str;
171
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);
177         }
178
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);
184         }
185 }
186
187 /**
188  * Open and parse the given makefile.
189  *
190  * Results:
191  *      true if ok. false if couldn't open file.
192  */
193 static bool
194 ReadMakefile(Parser *parser, CLI *cli, const char file[], const char curdir[], const char objdir[])
195 {
196         char    path[MAXPATHLEN];
197         FILE    *stream;
198         char    *fname;
199         char    *name;
200
201         if (!strcmp(file, "-")) {
202                 Parse_File(parser, cli, "(stdin)", stdin);
203                 Var_SetGlobal("MAKEFILE", "");
204                 return (true);
205         }
206
207         if (strcmp(curdir, objdir) == 0 || file[0] == '/') {
208                 strcpy(path, file);
209         } else {
210                 /*
211                  * we've chdir'd, rebuild the path name
212                  */
213                 snprintf(path, MAXPATHLEN, "%s/%s", curdir, file);
214         }
215 #if THIS_BREAKS_THINGS
216         /*
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.
230          */
231         if (realpath(path, path) == NULL) {
232                 stream = NULL;
233         } else {
234                 stream = fopen(path, "r");
235         }
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);
245         }
246
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);
254
255         if (name != NULL) {
256                 stream = fopen(name, "r");
257                 if (stream != NULL) {
258                         /*
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.
263                          */
264                         if (strcmp(file, ".depend") != 0)
265                                 Var_SetGlobal("MAKEFILE", name);
266                         Parse_File(parser, cli, name, stream);
267                         fclose(stream);
268                         return (true);
269                 }
270         }
271
272         return (false); /* no makefile found */
273 }
274
275 /**
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.
279  */
280 static void
281 ReadInputFiles(Parser *parser, CLI *cli, const char curdir[], const char objdir[])
282 {
283         if (cli->builtins) {
284                 char    defsysmk[] = PATH_DEFSYSMK;     /* Path of sys.mk */
285                 Lst     sysMkPath = Lst_Initializer(sysMkPath);
286                 LstNode *ln;
287
288                 Path_Expand(defsysmk, &cli->sysIncPath, &sysMkPath);
289                 if (Lst_IsEmpty(&sysMkPath))
290                         Fatal("make: no system rules (%s).", PATH_DEFSYSMK);
291
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);
296                 }
297                 Lst_Destroy(&sysMkPath, free);
298         }
299
300         if (!Lst_IsEmpty(&cli->makefiles)) {
301                 LstNode *ln;
302
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);
307                 }
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 */
316         }
317
318         ReadMakefile(parser, cli, ".depend", curdir, objdir);
319 }
320
321 /**
322  * Main_ParseWarn
323  *
324  *      Handle argument to warning option.
325  */
326 int
327 Main_ParseWarn(const char *arg, int iscmd)
328 {
329         int i, neg;
330
331         static const struct {
332                 const char      *option;
333                 uint32_t        flag;
334         } options[] = {
335                 { "dirsyntax",  WARN_DIRSYNTAX },
336                 { NULL,         0 }
337         };
338
339         neg = 0;
340         if (arg[0] == 'n' && arg[1] == 'o') {
341                 neg = 1;
342                 arg += 2;
343         }
344
345         for (i = 0; options[i].option != NULL; i++)
346                 if (strcmp(arg, options[i].option) == 0)
347                         break;
348
349         if (options[i].option == NULL)
350                 /* unknown option */
351                 return (-1);
352
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;
362                 }
363         } else {
364                 if (!neg) {
365                         warn_flags |= (options[i].flag & ~warn_nocmd);
366                 } else {
367                         warn_flags &= ~(options[i].flag | warn_cmd);
368                 }
369         }
370         return (0);
371 }
372
373 /**
374  * MainParseArgs
375  *      Parse a given argument vector. Called from main() and from
376  *      Main_ParseArgLine() when the .MAKEFLAGS target is used.
377  *
378  *      XXX: Deal with command line overriding .MAKEFLAGS in makefile
379  *
380  * Side Effects:
381  *      Various global and local flags will be set depending on the flags
382  *      given
383  */
384 static void
385 MainParseArgs(CLI *cli, int argc, char **argv)
386 {
387         int c;
388         bool    found_dd = false;
389
390 rearg:
391         optind = 1;     /* since we're called more than once */
392         optreset = 1;
393 #define OPTFLAGS "ABC:D:E:I:J:PSV:Xd:ef:ij:km:nqrstvx:"
394         for (;;) {
395                 if ((optind < argc) && strcmp(argv[optind], "--") == 0) {
396                         found_dd = true;
397                 }
398                 if ((c = getopt(argc, argv, OPTFLAGS)) == -1) {
399                         break;
400                 }
401                 switch(c) {
402
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 'J':
420                         /* Allow make child of bmake parent (No-op) */
421                         break;
422                 case 'V':
423                         Lst_AtEnd(&cli->variables, estrdup(optarg));
424                         MFLAGS_append("-V", optarg);
425                         break;
426                 case 'X':
427                         cli->expandVars = false;
428                         break;
429                 case 'B':
430                         compatMake = true;
431                         MFLAGS_append("-B", NULL);
432                         unsetenv("MAKE_JOBS_FIFO");
433                         break;
434                 case 'P':
435                         usePipes = false;
436                         MFLAGS_append("-P", NULL);
437                         break;
438                 case 'S':
439                         keepgoing = false;
440                         MFLAGS_append("-S", NULL);
441                         break;
442                 case 'd': {
443                         char *modules = optarg;
444
445                         for (; *modules; ++modules)
446                                 switch (*modules) {
447                                 case 'A':
448                                         debug = ~0;
449                                         break;
450                                 case 'a':
451                                         debug |= DEBUG_ARCH;
452                                         break;
453                                 case 'c':
454                                         debug |= DEBUG_COND;
455                                         break;
456                                 case 'd':
457                                         debug |= DEBUG_DIR;
458                                         break;
459                                 case 'f':
460                                         debug |= DEBUG_FOR;
461                                         break;
462                                 case 'g':
463                                         if (modules[1] == '1') {
464                                                 debug |= DEBUG_GRAPH1;
465                                                 ++modules;
466                                         }
467                                         else if (modules[1] == '2') {
468                                                 debug |= DEBUG_GRAPH2;
469                                                 ++modules;
470                                         }
471                                         break;
472                                 case 'j':
473                                         debug |= DEBUG_JOB;
474                                         break;
475                                 case 'l':
476                                         debug |= DEBUG_LOUD;
477                                         break;
478                                 case 'm':
479                                         debug |= DEBUG_MAKE;
480                                         break;
481                                 case 's':
482                                         debug |= DEBUG_SUFF;
483                                         break;
484                                 case 't':
485                                         debug |= DEBUG_TARG;
486                                         break;
487                                 case 'v':
488                                         debug |= DEBUG_VAR;
489                                         break;
490                                 default:
491                                         warnx("illegal argument to d option "
492                                             "-- %c", *modules);
493                                         usage();
494                                 }
495                         MFLAGS_append("-d", optarg);
496                         break;
497                 }
498                 case 'E':
499                         Lst_AtEnd(&envFirstVars, estrdup(optarg));
500                         MFLAGS_append("-E", optarg);
501                         break;
502                 case 'e':
503                         checkEnvFirst = true;
504                         MFLAGS_append("-e", NULL);
505                         break;
506                 case 'f':
507                         Lst_AtEnd(&cli->makefiles, estrdup(optarg));
508                         break;
509                 case 'i':
510                         ignoreErrors = true;
511                         MFLAGS_append("-i", NULL);
512                         break;
513                 case 'j': {
514                         char *endptr;
515
516                         cli->forceJobs = true;
517                         jobLimit = strtol(optarg, &endptr, 10);
518                         if (jobLimit <= 0 || *endptr != '\0') {
519                                 warnx("illegal number, -j argument -- %s",
520                                     optarg);
521                                 usage();
522                         }
523                         MFLAGS_append("-j", optarg);
524                         break;
525                 }
526                 case 'k':
527                         keepgoing = true;
528                         MFLAGS_append("-k", NULL);
529                         break;
530                 case 'm':
531                         Path_AddDir(&cli->sysIncPath, optarg);
532                         MFLAGS_append("-m", optarg);
533                         break;
534                 case 'n':
535                         noExecute = true;
536                         MFLAGS_append("-n", NULL);
537                         break;
538                 case 'q':
539                         cli->queryFlag = true;
540                         /* Kind of nonsensical, wot? */
541                         MFLAGS_append("-q", NULL);
542                         break;
543                 case 'r':
544                         cli->builtins = false;
545                         MFLAGS_append("-r", NULL);
546                         break;
547                 case 's':
548                         beSilent = true;
549                         MFLAGS_append("-s", NULL);
550                         break;
551                 case 't':
552                         touchFlag = true;
553                         MFLAGS_append("-t", NULL);
554                         break;
555                 case 'v':
556                         beVerbose = true;
557                         MFLAGS_append("-v", NULL);
558                         break;
559                 case 'x':
560                         if (Main_ParseWarn(optarg, 1) != -1)
561                                 MFLAGS_append("-x", optarg);
562                         break;
563                 default:
564                 case '?':
565                         usage();
566                 }
567         }
568         argv += optind;
569         argc -= optind;
570
571         oldVars = true;
572
573         /*
574          * Parse the rest of the arguments.
575          *      o Check for variable assignments and perform them if so.
576          *      o Check for more flags and restart getopt if so.
577          *      o Anything else is taken to be a target and added
578          *        to the end of the "create" list.
579          */
580         for (; *argv != NULL; ++argv, --argc) {
581                 if (Parse_IsVar(*argv)) {
582                         char *ptr = MAKEFLAGS_quote(*argv);
583
584                         Var_Append(".MAKEFLAGS", ptr, VAR_GLOBAL);
585                         Parse_DoVar(*argv, VAR_CMD);
586                         free(ptr);
587
588                 } else if ((*argv)[0] == '-') {
589                         if ((*argv)[1] == '\0') {
590                                 /*
591                                  * (*argv) is a single dash, so we
592                                  * just ignore it.
593                                  */
594                         } else if (found_dd) {
595                                 /*
596                                  * Double dash has been found, ignore
597                                  * any more options.  But what do we do
598                                  * with it?  For now treat it like a target.
599                                  */
600                                 Lst_AtEnd(&cli->create, estrdup(*argv));
601                         } else {
602                                 /*
603                                  * (*argv) is a -flag, so backup argv and
604                                  * argc.  getopt() expects options to start
605                                  * in the 2nd position.
606                                  */
607                                 argc++;
608                                 argv--;
609                                 goto rearg;
610                         }
611
612                 } else if ((*argv)[0] == '\0') {
613                         Punt("illegal (null) argument.");
614
615                 } else {
616                         Lst_AtEnd(&cli->create, estrdup(*argv));
617                 }
618         }
619 }
620
621 /**
622  * Main_ParseArgLine
623  *      Used by the parse module when a .MFLAGS or .MAKEFLAGS target
624  *      is encountered and by main() when reading the .MAKEFLAGS envariable.
625  *      Takes a line of arguments and breaks it into its
626  *      component words and passes those words and the number of them to the
627  *      MainParseArgs function.
628  *      The line should have all its leading whitespace removed.
629  *
630  * Side Effects:
631  *      Only those that come from the various arguments.
632  */
633 void
634 Main_ParseArgLine(CLI *cli, const char line[], int mflags)
635 {
636         ArgArray        aa;
637
638         if (mflags) {
639                 MAKEFLAGS_break(&aa, line);
640         } else {
641                 brk_string(&aa, line, true);
642         }
643         MainParseArgs(cli, aa.argc, aa.argv);
644         ArgArray_Done(&aa);
645 }
646
647 /**
648  * Try to change the current working directory to path, and return
649  * the whole path using getcwd().
650  *
651  * @note for amd managed mount points we really should use pawd(1).
652  */
653 static int
654 CheckDir(const char path[], char newdir[])
655 {
656         struct stat sb;
657
658         /*
659          * Check if the path is a directory.  If not fail without reporting
660          * an error.
661          */
662         if (stat(path, &sb) < 0) {
663                 return (0);
664         }
665         if (S_ISDIR(sb.st_mode) == 0) {
666                 return (0);
667         }
668
669         /*
670          * The path refers to a directory, so we try to change into it. If we
671          * fail, or we fail to obtain the path from root to the directory,
672          * then report an error and fail.
673          */
674         if (chdir(path) < 0) {
675                 warn("warning: %s", path);
676                 return (0);
677         }
678         if (getcwd(newdir, MAXPATHLEN) == NULL) {
679                 warn("warning: %s", path);
680                 return (0);
681         }
682
683         /*
684          * Directory in path is accessable, newdir should now contain the
685          * path to it.
686          */
687         return (1);
688 }
689
690 /**
691  * Determine location of the object directory.
692  */
693 static void
694 FindObjDir(const char machine[], char curdir[], char objdir[])
695 {
696         struct stat     sa;
697         char            newdir[MAXPATHLEN];
698         char            mdpath[MAXPATHLEN];
699         const char      *env;
700
701         /*
702          * Find a path to where we are... [-C directory] might have changed
703          * our current directory.
704          */
705         if (getcwd(curdir, MAXPATHLEN) == NULL)
706                 err(2, NULL);
707
708         if (stat(curdir, &sa) == -1)
709                 err(2, "%s", curdir);
710
711         /*
712          * The object directory location is determined using the
713          * following order of preference:
714          *
715          *      1. MAKEOBJDIRPREFIX`cwd`
716          *      2. MAKEOBJDIR
717          *      3. PATH_OBJDIR.${MACHINE}
718          *      4. PATH_OBJDIR
719          *      5. PATH_OBJDIRPREFIX`cwd`
720          *
721          * If one of the first two fails, use the current directory.
722          * If the remaining three all fail, use the current directory.
723          */
724         if ((env = getenv("MAKEOBJDIRPREFIX")) != NULL) {
725                 snprintf(mdpath, MAXPATHLEN, "%s%s", env, curdir);
726                 if (CheckDir(mdpath, newdir)) {
727                         strcpy(objdir, newdir);
728                         return;
729                 }
730                 strcpy(objdir, curdir);
731                 return;
732         }
733
734         if ((env = getenv("MAKEOBJDIR")) != NULL) {
735                 if (CheckDir(env, newdir)) {
736                         strcpy(objdir, newdir);
737                         return;
738                 }
739                 strcpy(objdir, curdir);
740                 return;
741         }
742
743         snprintf(mdpath, MAXPATHLEN, "%s.%s", PATH_OBJDIR, machine);
744         if (CheckDir(mdpath, newdir)) {
745                 strcpy(objdir, newdir);
746                 return;
747         }
748
749         if (CheckDir(PATH_OBJDIR, newdir)) {
750                 strcpy(objdir, newdir);
751                 return;
752         }
753
754         snprintf(mdpath, MAXPATHLEN, "%s%s", PATH_OBJDIRPREFIX, curdir);
755         if (CheckDir(mdpath, newdir)) {
756                 strcpy(objdir, newdir);
757                 return;
758         }
759
760         strcpy(objdir, curdir);
761 }
762
763 /**
764  * Initialize various make variables.
765  *      MAKE also gets this name, for compatibility
766  *      .MAKEFLAGS gets set to the empty string just in case.
767  *      MFLAGS also gets initialized empty, for compatibility.
768  */
769 static void
770 InitVariables(const char progname[])
771 {
772         const char      *machine_platform;
773         const char      *machine_arch;
774         const char      *machine;
775         char buf[256];
776         size_t bufsiz;
777
778         Var_SetGlobal("MAKE", progname);
779         Var_SetGlobal(".MAKEFLAGS", "");
780         Var_SetGlobal("MFLAGS", "");
781
782         Var_SetGlobal(".DIRECTIVE_MAKEENV", "YES");
783         Var_SetGlobal(".ST_EXPORTVAR", "YES");
784 #ifdef MAKE_VERSION
785         Var_SetGlobal("MAKE_VERSION", MAKE_VERSION);
786 #endif
787
788         /*
789          * The make program defines MACHINE_PLATFORM, MACHINE and MACHINE_ARCH.
790          * These parameters are taken from the running system but can be
791          * overridden by environment variables.
792          *
793          * MACHINE_PLATFORM     
794          *              - This is the platform, e.g. "vkernel", "pc32", 
795          *                and so forth.
796          *
797          * MACHINE      - This is the machine architecture and in most
798          *                cases is the same as the cpu architecture.
799          *
800          * MACHINE_ARCH - This is the cpu architecture, for example "i386".
801          *                Several different platforms may use the same
802          *                cpu architecture.
803          *
804          * In most, but not all cases, MACHINE == MACHINE_ARCH.
805          *
806          * PLATFORM distinguishes differences between, say, a virtual kernel
807          * build and a real kernel build.
808          */
809         if ((machine_platform = getenv("MACHINE_PLATFORM")) == NULL) {
810                 bufsiz = sizeof(buf);
811                 if (sysctlbyname("hw.platform", buf, &bufsiz, NULL, 0) < 0)
812                         machine_platform = "unknown";
813                 else
814                         machine_platform = strdup(buf);
815         }
816
817         if ((machine = getenv("MACHINE")) == NULL) {
818                 bufsiz = sizeof(buf);
819                 if (sysctlbyname("hw.machine", buf, &bufsiz, NULL, 0) < 0)
820                         machine = "unknown";
821                 else
822                         machine = strdup(buf);
823         }
824
825         if ((machine_arch = getenv("MACHINE_ARCH")) == NULL) {
826                 bufsiz = sizeof(buf);
827                 if (sysctlbyname("hw.machine_arch", buf, &bufsiz, NULL, 0) < 0)
828                         machine_arch = "unknown";
829                 else
830                         machine_arch = strdup(buf);
831         }
832
833         Var_SetGlobal("MACHINE_PLATFORM", machine_platform);
834         Var_SetGlobal("MACHINE", machine);
835         Var_SetGlobal("MACHINE_ARCH", machine_arch);
836 }
837
838 /**
839  * Build targets given in the command line or if none were given
840  * use the main target determined by the parsing module.
841  */
842 static int
843 BuildStuff(CLI *cli)
844 {
845         int     status;
846         Lst     targs = Lst_Initializer(targs);
847
848         if (Lst_IsEmpty(&cli->create))
849                 Parse_MainName(&targs);
850         else
851                 Targ_FindList(&targs, &cli->create, TARG_CREATE);
852
853         /* Traverse the graph, checking on all the targets */
854         if (compatMake) {
855                 Sig_Init(true);
856                 status = Compat_Run(&targs, cli->queryFlag);
857         } else {
858                 Sig_Init(false);
859                 status = Make_Run(&targs, cli->queryFlag);
860         }
861
862         Lst_Destroy(&targs, NOFREE);
863         return (status);
864 }
865
866 /**
867  * main
868  *      The main function, for obvious reasons. Initializes variables
869  *      and a few modules, then parses the arguments give it in the
870  *      environment and on the command line. Reads the system makefile
871  *      followed by either Makefile, makefile or the file given by the
872  *      -f argument. Sets the .MAKEFLAGS PMake variable based on all the
873  *      flags it has received by then uses either the Make or the Compat
874  *      module to create the initial list of targets.
875  *
876  * Results:
877  *      If -q was given, exits -1 if anything was out-of-date. Else it exits
878  *      0.
879  *
880  * Side Effects:
881  *      The program exits when done. Targets are created. etc. etc. etc.
882  */
883 int
884 main(int argc, char **argv)
885 {
886         CLI             cli;
887         Parser          parser;
888         Shell           *shell;
889         int             status;         /* exit status */
890         char            curdir[MAXPATHLEN];     /* startup directory */
891         char            objdir[MAXPATHLEN];     /* where we chdir'ed to */
892         const char      *make_flags;
893
894         /*------------------------------------------------------------*
895          * This section initializes stuff that require no input.
896          *------------------------------------------------------------*/
897         /*
898          * Initialize program globals.
899          */
900         beSilent = false;               /* Print commands as executed */
901         ignoreErrors = false;           /* Pay attention to non-zero returns */
902         noExecute = false;              /* Execute all commands */
903         keepgoing = false;              /* Stop on error */
904         allPrecious = false;            /* Remove targets when interrupted */
905         touchFlag = false;              /* Actually update targets */
906         usePipes = true;                /* Catch child output in pipes */
907         debug = 0;                      /* No debug verbosity, please. */
908         jobsRunning = false;
909
910         jobLimit = DEFMAXJOBS;
911         compatMake = false;             /* No compat mode */
912
913         /*
914          * Initialize program flags.
915          */
916         Lst_Init(&cli.makefiles);
917         Lst_Init(&cli.variables);
918         Lst_Init(&cli.create);
919         TAILQ_INIT(&cli.parseIncPath);
920         TAILQ_INIT(&cli.sysIncPath);
921
922         cli.expandVars = true;
923         cli.builtins = true;            /* Read the built-in rules */
924         cli.queryFlag = false;
925         cli.forceJobs = false;
926
927         shell = Shell_Match(DEFSHELLNAME);
928
929         /*
930          * Initialize the various modules.
931          */
932         Proc_Init();
933         commandShell = shell;
934         Targ_Init();
935         Suff_Init();
936         Dir_Init();
937
938         /*------------------------------------------------------------*
939          * This section initializes stuff that depend on things
940          * in the enviornment, command line, or a input file.
941          *------------------------------------------------------------*/
942         Var_Init(environ);
943
944         InitVariables(argv[0]);
945
946         /*
947          * First snag things out of the MAKEFLAGS environment
948          * variable.  Then parse the command line arguments.
949          */
950         if ((make_flags = getenv("MAKEFLAGS")) != NULL) {
951                 Main_ParseArgLine(&cli, make_flags, 1);
952         }
953         MainParseArgs(&cli, argc, argv);
954
955         FindObjDir(Var_Value("MACHINE", VAR_GLOBAL), curdir, objdir);
956         Var_SetGlobal(".CURDIR", curdir);
957         Var_SetGlobal(".OBJDIR", objdir);
958
959         /*
960          * Set up the .TARGETS variable to contain the list of targets to be
961          * created. If none specified, make the variable empty -- the parser
962          * will fill the thing in with the default or .MAIN target.
963          */
964         if (Lst_IsEmpty(&cli.create)) {
965                 Var_SetGlobal(".TARGETS", "");
966         } else {
967                 LstNode *ln;
968
969                 LST_FOREACH(ln, &cli.create) {
970                         char *name = Lst_Datum(ln);
971
972                         Var_Append(".TARGETS", name, VAR_GLOBAL);
973                 }
974         }
975
976         Dir_CurObj(curdir, objdir);
977
978         /*
979          * If no user-supplied system path was given (through the -m option)
980          * add the directories from the DEFSYSPATH (more than one may be given
981          * as dir1:...:dirn) to the system include path.
982          */
983         if (TAILQ_EMPTY(&cli.sysIncPath)) {
984                 char syspath[] = PATH_DEFSYSPATH;
985                 char *start = syspath;
986                 char *cp;
987
988                 while ((cp = strsep(&start, ":")) != NULL) {
989                         Path_AddDir(&cli.sysIncPath, cp);
990                 }
991         }
992
993         if (getenv("MAKE_JOBS_FIFO") != NULL)
994                 cli.forceJobs = true;
995
996         /*
997          * Be compatible if user did not specify -j and did not explicitly
998          * turned compatibility on
999          */
1000         if (compatMake == false && cli.forceJobs == false)
1001                 compatMake = true;
1002
1003         DEFAULT = NULL;
1004         time(&now);
1005
1006         parser.create = &cli.create;
1007         parser.parseIncPath = &cli.parseIncPath;
1008         parser.sysIncPath = &cli.sysIncPath;
1009
1010         ReadInputFiles(&parser, &cli, curdir, objdir);
1011
1012         /*------------------------------------------------------------*
1013          * We are finished processing inputs.
1014          *------------------------------------------------------------*/
1015
1016         /* Install all the flags into the MAKE envariable. */
1017         {
1018                 const char *p;
1019
1020                 p = Var_Value(".MAKEFLAGS", VAR_GLOBAL);
1021                 if (p != NULL && *p != '\0') {
1022                         if (setenv("MAKEFLAGS", p, 1) == -1)
1023                                 Punt("setenv: MAKEFLAGS: can't allocate memory");
1024                 }
1025         }
1026
1027         /*
1028          * For compatibility, look at the directories in the VPATH variable
1029          * and add them to the search path, if the variable is defined. The
1030          * variable's value is in the same format as the PATH envariable, i.e.
1031          * <directory>:<directory>:<directory>...
1032          */
1033         if (Var_Value("VPATH", VAR_CMD) != NULL) {
1034                 Buffer  *buf = Var_Subst("${VPATH}", VAR_CMD, false);
1035                 char    *start = Buf_Data(buf);
1036                 char    *cp;
1037
1038                 while ((cp = strsep(&start, ":")) != NULL) {
1039                         Path_AddDir(&dirSearchPath, cp);
1040                 }
1041
1042                 Buf_Destroy(buf, true);
1043         }
1044
1045         /*
1046          * Now that all search paths have been read for suffixes et al, it's
1047          * time to add the default search path to their lists...
1048          */
1049         Suff_DoPaths();
1050
1051         /* print the initial graph, if the user requested it */
1052         if (DEBUG(GRAPH1))
1053                 Targ_PrintGraph(1);
1054
1055         if (Lst_IsEmpty(&cli.variables)) {
1056                 status = BuildStuff(&cli);
1057         } else {
1058                 /* Print the values of variables requested by the user. */
1059                 Var_Print(&cli.variables, cli.expandVars);
1060
1061                 /*
1062                  * XXX
1063                  * This should be a "don't care", we do not check
1064                  * the status of any files.  It might make sense to
1065                  * modify Var_Print() to indicate that one of the
1066                  * requested variables did not exist, and use that
1067                  * as the return status.
1068                  * XXX
1069                  */
1070                 status = cli.queryFlag ? 1 : 0;
1071         }
1072
1073         /* print the graph now it's been processed if the user requested it */
1074         if (DEBUG(GRAPH2))
1075                 Targ_PrintGraph(2);
1076
1077 #if 0
1078         TAILQ_DESTROY(&cli.sysIncPath);
1079         TAILQ_DESTROY(&cli.parseIncPath);
1080 #endif
1081         Lst_Destroy(&cli.create, free);
1082         Lst_Destroy(&cli.variables, free);
1083         Lst_Destroy(&cli.makefiles, free);
1084
1085         return (status);
1086 }
1087