o Remove out of date comment about Compat_Init()
[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.108 2005/05/23 20:04:04 okumoto 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/time.h>
63 #include <sys/queue.h>
64 #include <sys/resource.h>
65 #include <sys/wait.h>
66 #include <err.h>
67 #include <errno.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <unistd.h>
71
72 #include "arch.h"
73 #include "buf.h"
74 #include "config.h"
75 #include "dir.h"
76 #include "globals.h"
77 #include "job.h"
78 #include "make.h"
79 #include "parse.h"
80 #include "pathnames.h"
81 #include "shell.h"
82 #include "str.h"
83 #include "suff.h"
84 #include "targ.h"
85 #include "util.h"
86 #include "var.h"
87
88 extern char **environ;  /* XXX what header declares this variable? */
89
90 /*
91  * DEFMAXJOBS
92  *      This control the default concurrency. On no occasion will more
93  *      than DEFMAXJOBS targets be created at once.
94  */
95 #define DEFMAXJOBS      1
96
97 typedef struct MakeFlags {
98         /* ordered list of makefiles to read */
99         Lst makefiles;
100
101         /* list of variables to print */
102         Lst variables;
103
104         Boolean expandVars;     /* fully expand printed variables */
105         Boolean noBuiltins;     /* -r flag */
106         Boolean forceJobs;      /* -j argument given */
107
108         /**
109          * -q flag:
110          * TRUE if we aren't supposed to really make anything, just
111          * see if the targets are out-of-date
112          */
113         Boolean         queryFlag;
114 } MakeFlags;
115
116 /* (-E) vars to override from env */
117 Lst envFirstVars = Lst_Initializer(envFirstVars);
118
119 /* Targets to be made */
120 Lst create = Lst_Initializer(create);
121
122 Boolean         allPrecious;    /* .PRECIOUS given on line by itself */
123 Boolean         beSilent;       /* -s flag */
124 Boolean         beVerbose;      /* -v flag */
125 Boolean         compatMake;     /* -B argument */
126 Boolean         debug;          /* -d flag */
127 Boolean         ignoreErrors;   /* -i flag */
128 int             jobLimit;       /* -j argument */
129 Boolean         jobsRunning;    /* TRUE if the jobs might be running */
130 Boolean         keepgoing;      /* -k flag */
131 Boolean         noExecute;      /* -n flag */
132 Boolean         touchFlag;      /* -t flag */
133 Boolean         usePipes;       /* !-P flag */
134 uint32_t        warn_cmd;       /* command line warning flags */
135 uint32_t        warn_flags;     /* actual warning flags */
136 uint32_t        warn_nocmd;     /* command line no-warning flags */
137
138 time_t          now;            /* Time at start of make */
139 struct GNode    *DEFAULT;       /* .DEFAULT node */
140
141
142 /**
143  * Exit with usage message.
144  */
145 static void
146 usage(void)
147 {
148         fprintf(stderr,
149             "usage: make [-BPSXeiknqrstv] [-C directory] [-D variable]\n"
150             "\t[-d flags] [-E variable] [-f makefile] [-I directory]\n"
151             "\t[-j max_jobs] [-m directory] [-V variable]\n"
152             "\t[variable=value] [target ...]\n");
153         exit(2);
154 }
155
156 /**
157  * MFLAGS_append
158  *      Append a flag with an optional argument to MAKEFLAGS and MFLAGS
159  */
160 static void
161 MFLAGS_append(const char *flag, char *arg)
162 {
163         char *str;
164
165         Var_Append(".MAKEFLAGS", flag, VAR_GLOBAL);
166         if (arg != NULL) {
167                 str = MAKEFLAGS_quote(arg);
168                 Var_Append(".MAKEFLAGS", str, VAR_GLOBAL);
169                 free(str);
170         }
171
172         Var_Append("MFLAGS", flag, VAR_GLOBAL);
173         if (arg != NULL) {
174                 str = MAKEFLAGS_quote(arg);
175                 Var_Append("MFLAGS", str, VAR_GLOBAL);
176                 free(str);
177         }
178 }
179
180 /**
181  * Open and parse the given makefile.
182  *
183  * Results:
184  *      TRUE if ok. FALSE if couldn't open file.
185  */
186 static Boolean
187 ReadMakefile(MakeFlags *mf, const char file[], const char curdir[], const char objdir[])
188 {
189         char    path[MAXPATHLEN];
190         FILE    *stream;
191         char    *fname;
192         char    *name;
193
194         if (!strcmp(file, "-")) {
195                 Parse_File(mf, "(stdin)", stdin);
196                 Var_SetGlobal("MAKEFILE", "");
197                 return (TRUE);
198         }
199
200         if (strcmp(curdir, objdir) == 0 || file[0] == '/') {
201                 strcpy(path, file);
202         } else {
203                 /*
204                  * we've chdir'd, rebuild the path name
205                  */
206                 snprintf(path, MAXPATHLEN, "%s/%s", curdir, file);
207         }
208 #if THIS_BREAKS_THINGS
209         /*
210          * XXX The realpath stuff breaks relative includes
211          * XXX in some cases.   The problem likely is in
212          * XXX parse.c where it does special things in
213          * XXX ParseDoInclude if the file is relateive
214          * XXX or absolute and not a system file.  There
215          * XXX it assumes that if the current file that's
216          * XXX being included is absolute, that any files
217          * XXX that it includes shouldn't do the -I path
218          * XXX stuff, which is inconsistant with historical
219          * XXX behavior.  However, I can't pentrate the mists
220          * XXX further, so I'm putting this workaround in
221          * XXX here until such time as the underlying bug
222          * XXX can be fixed.
223          */
224         if (realpath(path, path) == NULL) {
225                 stream = NULL;
226         } else {
227                 stream = fopen(path, "r");
228         }
229 #else
230         stream = fopen(path, "r");
231 #endif
232         if (stream != NULL) {
233                 if (strcmp(file, ".depend") != 0)
234                         Var_SetGlobal("MAKEFILE", file);
235                 Parse_File(mf, path, stream);
236                 fclose(stream);
237                 return (TRUE);
238         }
239
240         /* look in -I and system include directories. */
241         fname = estrdup(file);
242         name = NULL;
243         if (name == NULL)
244                 name = Path_FindFile(fname, &parseIncPath);
245         if (name == NULL)
246                 name = Path_FindFile(fname, &sysIncPath);
247
248         if (name != NULL) {
249                 stream = fopen(name, "r");
250                 if (stream != NULL) {
251                         /*
252                          * set the MAKEFILE variable desired by System V fans
253                          * -- the placement of the setting here means it gets
254                          * set to the last makefile specified, as it is set
255                          * by SysV make.
256                          */
257                         if (strcmp(file, ".depend") != 0)
258                                 Var_SetGlobal("MAKEFILE", name);
259                         Parse_File(mf, name, stream);
260                         fclose(stream);
261                         return (TRUE);
262                 }
263         }
264
265         return (FALSE); /* no makefile found */
266 }
267
268 /**
269  * Read in the built-in rules first, followed by the specified
270  * makefiles or the one of the default makefiles.  Finally .depend
271  * makefile.
272  */
273 static void
274 ReadInputFiles(MakeFlags *mf, const char curdir[], const char objdir[])
275 {
276         if (!mf->noBuiltins) {
277                 /* Path of sys.mk */
278                 Lst     sysMkPath = Lst_Initializer(sysMkPath);
279                 LstNode *ln;
280                 char    defsysmk[] = PATH_DEFSYSMK;
281
282                 Path_Expand(defsysmk, &sysIncPath, &sysMkPath);
283                 if (Lst_IsEmpty(&sysMkPath))
284                         Fatal("make: no system rules (%s).", PATH_DEFSYSMK);
285                 LST_FOREACH(ln, &sysMkPath) {
286                         if (!ReadMakefile(mf, Lst_Datum(ln), curdir, objdir))
287                                 break;
288                 }
289                 if (ln != NULL)
290                         Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
291                 Lst_Destroy(&sysMkPath, free);
292         }
293
294         if (!Lst_IsEmpty(&mf->makefiles)) {
295                 LstNode *ln;
296
297                 LST_FOREACH(ln, &mf->makefiles) {
298                         if (!ReadMakefile(mf, Lst_Datum(ln), curdir, objdir))
299                                 break;
300                 }
301                 if (ln != NULL)
302                         Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
303         } else if (ReadMakefile(mf, "BSDmakefile", curdir, objdir)) {
304                 /* read BSDmakefile */
305         } else if (ReadMakefile(mf, "makefile", curdir, objdir)) {
306                 /* read makefile */
307         } else if (ReadMakefile(mf, "Makefile", curdir, objdir)) {
308                 /* read Makefile */
309         } else {
310                 /* No Makefile found */
311         }
312
313         ReadMakefile(mf, ".depend", curdir, objdir);
314 }
315
316 /**
317  * Main_ParseWarn
318  *
319  *      Handle argument to warning option.
320  */
321 int
322 Main_ParseWarn(const char *arg, int iscmd)
323 {
324         int i, neg;
325
326         static const struct {
327                 const char      *option;
328                 uint32_t        flag;
329         } options[] = {
330                 { "dirsyntax",  WARN_DIRSYNTAX },
331                 { NULL,         0 }
332         };
333
334         neg = 0;
335         if (arg[0] == 'n' && arg[1] == 'o') {
336                 neg = 1;
337                 arg += 2;
338         }
339
340         for (i = 0; options[i].option != NULL; i++)
341                 if (strcmp(arg, options[i].option) == 0)
342                         break;
343
344         if (options[i].option == NULL)
345                 /* unknown option */
346                 return (-1);
347
348         if (iscmd) {
349                 if (!neg) {
350                         warn_cmd |= options[i].flag;
351                         warn_nocmd &= ~options[i].flag;
352                         warn_flags |= options[i].flag;
353                 } else {
354                         warn_nocmd |= options[i].flag;
355                         warn_cmd &= ~options[i].flag;
356                         warn_flags &= ~options[i].flag;
357                 }
358         } else {
359                 if (!neg) {
360                         warn_flags |= (options[i].flag & ~warn_nocmd);
361                 } else {
362                         warn_flags &= ~(options[i].flag | warn_cmd);
363                 }
364         }
365         return (0);
366 }
367
368 /**
369  * MainParseArgs
370  *      Parse a given argument vector. Called from main() and from
371  *      Main_ParseArgLine() when the .MAKEFLAGS target is used.
372  *
373  *      XXX: Deal with command line overriding .MAKEFLAGS in makefile
374  *
375  * Side Effects:
376  *      Various global and local flags will be set depending on the flags
377  *      given
378  */
379 static void
380 MainParseArgs(MakeFlags *mf, int argc, char **argv)
381 {
382         int c;
383         Boolean found_dd = FALSE;
384
385 rearg:
386         optind = 1;     /* since we're called more than once */
387         optreset = 1;
388 #define OPTFLAGS "ABC:D:E:I:PSV:Xd:ef:ij:km:nqrstvx:"
389         for (;;) {
390                 if ((optind < argc) && strcmp(argv[optind], "--") == 0) {
391                         found_dd = TRUE;
392                 }
393                 if ((c = getopt(argc, argv, OPTFLAGS)) == -1) {
394                         break;
395                 }
396                 switch(c) {
397
398                 case 'A':
399                         arch_fatal = FALSE;
400                         MFLAGS_append("-A", NULL);
401                         break;
402                 case 'C':
403                         if (chdir(optarg) == -1)
404                                 err(1, "chdir %s", optarg);
405                         break;
406                 case 'D':
407                         Var_SetGlobal(optarg, "1");
408                         MFLAGS_append("-D", optarg);
409                         break;
410                 case 'I':
411                         Parse_AddIncludeDir(optarg);
412                         MFLAGS_append("-I", optarg);
413                         break;
414                 case 'V':
415                         Lst_AtEnd(&mf->variables, estrdup(optarg));
416                         MFLAGS_append("-V", optarg);
417                         break;
418                 case 'X':
419                         mf->expandVars = FALSE;
420                         break;
421                 case 'B':
422                         compatMake = TRUE;
423                         MFLAGS_append("-B", NULL);
424                         unsetenv("MAKE_JOBS_FIFO");
425                         break;
426                 case 'P':
427                         usePipes = FALSE;
428                         MFLAGS_append("-P", NULL);
429                         break;
430                 case 'S':
431                         keepgoing = FALSE;
432                         MFLAGS_append("-S", NULL);
433                         break;
434                 case 'd': {
435                         char *modules = optarg;
436
437                         for (; *modules; ++modules)
438                                 switch (*modules) {
439                                 case 'A':
440                                         debug = ~0;
441                                         break;
442                                 case 'a':
443                                         debug |= DEBUG_ARCH;
444                                         break;
445                                 case 'c':
446                                         debug |= DEBUG_COND;
447                                         break;
448                                 case 'd':
449                                         debug |= DEBUG_DIR;
450                                         break;
451                                 case 'f':
452                                         debug |= DEBUG_FOR;
453                                         break;
454                                 case 'g':
455                                         if (modules[1] == '1') {
456                                                 debug |= DEBUG_GRAPH1;
457                                                 ++modules;
458                                         }
459                                         else if (modules[1] == '2') {
460                                                 debug |= DEBUG_GRAPH2;
461                                                 ++modules;
462                                         }
463                                         break;
464                                 case 'j':
465                                         debug |= DEBUG_JOB;
466                                         break;
467                                 case 'l':
468                                         debug |= DEBUG_LOUD;
469                                         break;
470                                 case 'm':
471                                         debug |= DEBUG_MAKE;
472                                         break;
473                                 case 's':
474                                         debug |= DEBUG_SUFF;
475                                         break;
476                                 case 't':
477                                         debug |= DEBUG_TARG;
478                                         break;
479                                 case 'v':
480                                         debug |= DEBUG_VAR;
481                                         break;
482                                 default:
483                                         warnx("illegal argument to d option "
484                                             "-- %c", *modules);
485                                         usage();
486                                 }
487                         MFLAGS_append("-d", optarg);
488                         break;
489                 }
490                 case 'E':
491                         Lst_AtEnd(&envFirstVars, estrdup(optarg));
492                         MFLAGS_append("-E", optarg);
493                         break;
494                 case 'e':
495                         checkEnvFirst = TRUE;
496                         MFLAGS_append("-e", NULL);
497                         break;
498                 case 'f':
499                         Lst_AtEnd(&mf->makefiles, estrdup(optarg));
500                         break;
501                 case 'i':
502                         ignoreErrors = TRUE;
503                         MFLAGS_append("-i", NULL);
504                         break;
505                 case 'j': {
506                         char *endptr;
507
508                         mf->forceJobs = TRUE;
509                         jobLimit = strtol(optarg, &endptr, 10);
510                         if (jobLimit <= 0 || *endptr != '\0') {
511                                 warnx("illegal number, -j argument -- %s",
512                                     optarg);
513                                 usage();
514                         }
515                         MFLAGS_append("-j", optarg);
516                         break;
517                 }
518                 case 'k':
519                         keepgoing = TRUE;
520                         MFLAGS_append("-k", NULL);
521                         break;
522                 case 'm':
523                         Path_AddDir(&sysIncPath, optarg);
524                         MFLAGS_append("-m", optarg);
525                         break;
526                 case 'n':
527                         noExecute = TRUE;
528                         MFLAGS_append("-n", NULL);
529                         break;
530                 case 'q':
531                         mf->queryFlag = TRUE;
532                         /* Kind of nonsensical, wot? */
533                         MFLAGS_append("-q", NULL);
534                         break;
535                 case 'r':
536                         mf->noBuiltins = TRUE;
537                         MFLAGS_append("-r", NULL);
538                         break;
539                 case 's':
540                         beSilent = TRUE;
541                         MFLAGS_append("-s", NULL);
542                         break;
543                 case 't':
544                         touchFlag = TRUE;
545                         MFLAGS_append("-t", NULL);
546                         break;
547                 case 'v':
548                         beVerbose = TRUE;
549                         MFLAGS_append("-v", NULL);
550                         break;
551                 case 'x':
552                         if (Main_ParseWarn(optarg, 1) != -1)
553                                 MFLAGS_append("-x", optarg);
554                         break;
555                 default:
556                 case '?':
557                         usage();
558                 }
559         }
560         argv += optind;
561         argc -= optind;
562
563         oldVars = TRUE;
564
565         /*
566          * Parse the rest of the arguments.
567          *      o Check for variable assignments and perform them if so.
568          *      o Check for more flags and restart getopt if so.
569          *      o Anything else is taken to be a target and added
570          *        to the end of the "create" list.
571          */
572         for (; *argv != NULL; ++argv, --argc) {
573                 if (Parse_IsVar(*argv)) {
574                         char *ptr = MAKEFLAGS_quote(*argv);
575
576                         Var_Append(".MAKEFLAGS", ptr, VAR_GLOBAL);
577                         Parse_DoVar(*argv, VAR_CMD);
578                         free(ptr);
579
580                 } else if ((*argv)[0] == '-') {
581                         if ((*argv)[1] == '\0') {
582                                 /*
583                                  * (*argv) is a single dash, so we
584                                  * just ignore it.
585                                  */
586                         } else if (found_dd) {
587                                 /*
588                                  * Double dash has been found, ignore
589                                  * any more options.  But what do we do
590                                  * with it?  For now treat it like a target.
591                                  */
592                                 Lst_AtEnd(&create, estrdup(*argv));
593                         } else {
594                                 /*
595                                  * (*argv) is a -flag, so backup argv and
596                                  * argc.  getopt() expects options to start
597                                  * in the 2nd position.
598                                  */
599                                 argc++;
600                                 argv--;
601                                 goto rearg;
602                         }
603
604                 } else if ((*argv)[0] == '\0') {
605                         Punt("illegal (null) argument.");
606
607                 } else {
608                         Lst_AtEnd(&create, estrdup(*argv));
609                 }
610         }
611 }
612
613 /**
614  * Main_ParseArgLine
615  *      Used by the parse module when a .MFLAGS or .MAKEFLAGS target
616  *      is encountered and by main() when reading the .MAKEFLAGS envariable.
617  *      Takes a line of arguments and breaks it into its
618  *      component words and passes those words and the number of them to the
619  *      MainParseArgs function.
620  *      The line should have all its leading whitespace removed.
621  *
622  * Side Effects:
623  *      Only those that come from the various arguments.
624  */
625 void
626 Main_ParseArgLine(MakeFlags *mf, char line[], int mflags)
627 {
628         ArgArray        aa;
629
630         if (line == NULL)
631                 return;
632         for (; *line == ' '; ++line)
633                 continue;
634         if (!*line)
635                 return;
636
637         if (mflags) {
638                 MAKEFLAGS_break(&aa, line);
639         } else {
640                 brk_string(&aa, line, TRUE);
641         }
642         MainParseArgs(mf, aa.argc, aa.argv);
643         ArgArray_Done(&aa);
644 }
645
646 /**
647  * Try to change the current working directory into path.
648  */
649 static int
650 chdir_verify_path(const char path[], char newdir[])
651 {
652         struct stat sb;
653
654         /*
655          * Check if the path is a directory.  If not fail without reporting
656          * an error.
657          */
658         if (stat(path, &sb) < 0) {
659                 return (0);     /* fail but no report */
660         }
661         if (S_ISDIR(sb.st_mode) == 0) {
662                 return (0);
663         }
664
665         /*
666          * The path refers to a directory, so we try to change into it. If we
667          * fail, or we fail to obtain the path from root to the directory,
668          * then report an error and fail.
669          */
670         if (chdir(path) < 0) {
671                 warn("warning: %s", path);
672                 return (0);
673         }
674         if (getcwd(newdir, MAXPATHLEN) == NULL) {
675                 warn("warning: %s", path);
676                 return (0);
677         }
678         return (1);
679 }
680
681 static void
682 determine_objdir(const char machine[], char curdir[], char objdir[])
683 {
684         struct stat     sa;
685         char            newdir[MAXPATHLEN];
686         char            mdpath[MAXPATHLEN];
687         const char      *env;
688
689         /*
690          * Find a path to where we are... [-C directory] might have changed
691          * our current directory.
692          */
693         if (getcwd(curdir, MAXPATHLEN) == NULL)
694                 err(2, NULL);
695
696         if (stat(curdir, &sa) == -1)
697                 err(2, "%s", curdir);
698
699         /*
700          * The object directory location is determined using the
701          * following order of preference:
702          *
703          *      1. MAKEOBJDIRPREFIX`cwd`
704          *      2. MAKEOBJDIR
705          *      3. PATH_OBJDIR.${MACHINE}
706          *      4. PATH_OBJDIR
707          *      5. PATH_OBJDIRPREFIX`cwd`
708          *
709          * If one of the first two fails, use the current directory.
710          * If the remaining three all fail, use the current directory.
711          */
712         if ((env = getenv("MAKEOBJDIRPREFIX")) != NULL) {
713                 snprintf(mdpath, MAXPATHLEN, "%s%s", env, curdir);
714                 if (chdir_verify_path(mdpath, newdir)) {
715                         strcpy(objdir, newdir);
716                         return;
717                 }
718                 strcpy(objdir, curdir);
719                 return;
720         }
721
722         if ((env = getenv("MAKEOBJDIR")) != NULL) {
723                 if (chdir_verify_path(env, newdir)) {
724                         strcpy(objdir, newdir);
725                         return;
726                 }
727                 strcpy(objdir, curdir);
728                 return;
729         }
730
731         snprintf(mdpath, MAXPATHLEN, "%s.%s", PATH_OBJDIR, machine);
732         if (chdir_verify_path(mdpath, newdir)) {
733                 strcpy(objdir, newdir);
734                 return;
735         }
736
737         if (chdir_verify_path(PATH_OBJDIR, newdir)) {
738                 strcpy(objdir, newdir);
739                 return;
740         }
741
742         snprintf(mdpath, MAXPATHLEN, "%s%s", PATH_OBJDIRPREFIX, curdir);
743         if (chdir_verify_path(mdpath, newdir)) {
744                 strcpy(objdir, newdir);
745                 return;
746         }
747
748         strcpy(objdir, curdir);
749 }
750
751 /**
752  * Initialize various make variables.
753  *      MAKE also gets this name, for compatibility
754  *      .MAKEFLAGS gets set to the empty string just in case.
755  *      MFLAGS also gets initialized empty, for compatibility.
756  */
757 static void
758 InitVariables(MakeFlags *mf, int argc, char *argv[], char curdir[], char objdir[])
759 {
760         const char      *machine;
761         const char      *machine_arch;
762         const char      *machine_cpu;
763
764
765         Var_Init(environ);
766
767         Var_SetGlobal("MAKE", argv[0]);
768         Var_SetGlobal(".MAKEFLAGS", "");
769         Var_SetGlobal("MFLAGS", "");
770
771         Var_SetGlobal(".DIRECTIVE_MAKEENV", "YES");
772         Var_SetGlobal(".ST_EXPORTVAR", "YES");
773 #ifdef MAKE_VERSION
774         Var_SetGlobal("MAKE_VERSION", MAKE_VERSION);
775 #endif
776
777         /*
778          * Get the name of this type of MACHINE from utsname
779          * so we can share an executable for similar machines.
780          * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
781          *
782          * Note that while MACHINE is decided at run-time,
783          * MACHINE_ARCH is always known at compile time.
784          */
785         if ((machine = getenv("MACHINE")) == NULL) {
786 #ifdef MACHINE
787                 machine = MACHINE;
788 #else
789                 static struct utsname   utsname;
790                 if (uname(&utsname) == -1)
791                         err(2, "uname");
792                 machine = utsname.machine;
793 #endif
794         }
795
796         if ((machine_arch = getenv("MACHINE_ARCH")) == NULL) {
797 #ifdef MACHINE_ARCH
798                 machine_arch = MACHINE_ARCH;
799 #else
800                 machine_arch = "unknown";
801 #endif
802         }
803
804         /*
805          * Set machine_cpu to the minumum supported CPU revision based
806          * on the target architecture, if not already set.
807          */
808         if ((machine_cpu = getenv("MACHINE_CPU")) == NULL) {
809                 if (!strcmp(machine_arch, "i386"))
810                         machine_cpu = "i386";
811                 else if (!strcmp(machine_arch, "alpha"))
812                         machine_cpu = "ev4";
813                 else
814                         machine_cpu = "unknown";
815         }
816
817         Var_SetGlobal("MACHINE", machine);
818         Var_SetGlobal("MACHINE_ARCH", machine_arch);
819         Var_SetGlobal("MACHINE_CPU", machine_cpu);
820
821         /*
822          * First snag things out of the MAKEFLAGS environment
823          * variable.  Then parse the command line arguments.
824          */
825         Main_ParseArgLine(mf, getenv("MAKEFLAGS"), 1);
826
827         MainParseArgs(mf, argc, argv);
828
829         determine_objdir(machine, curdir, objdir);
830         Var_SetGlobal(".CURDIR", curdir);
831         Var_SetGlobal(".OBJDIR", objdir);
832
833         /*
834          * Set up the .TARGETS variable to contain the list of targets to be
835          * created. If none specified, make the variable empty -- the parser
836          * will fill the thing in with the default or .MAIN target.
837          */
838         if (Lst_IsEmpty(&create)) {
839                 Var_SetGlobal(".TARGETS", "");
840         } else {
841                 LstNode *ln;
842
843                 for (ln = Lst_First(&create); ln != NULL; ln = Lst_Succ(ln)) {
844                         char *name = Lst_Datum(ln);
845
846                         Var_Append(".TARGETS", name, VAR_GLOBAL);
847                 }
848         }
849 }
850
851 /**
852  * main
853  *      The main function, for obvious reasons. Initializes variables
854  *      and a few modules, then parses the arguments give it in the
855  *      environment and on the command line. Reads the system makefile
856  *      followed by either Makefile, makefile or the file given by the
857  *      -f argument. Sets the .MAKEFLAGS PMake variable based on all the
858  *      flags it has received by then uses either the Make or the Compat
859  *      module to create the initial list of targets.
860  *
861  * Results:
862  *      If -q was given, exits -1 if anything was out-of-date. Else it exits
863  *      0.
864  *
865  * Side Effects:
866  *      The program exits when done. Targets are created. etc. etc. etc.
867  */
868 int
869 main(int argc, char **argv)
870 {
871         MakeFlags       mf;
872         Boolean outOfDate = TRUE;       /* FALSE if all targets up to date */
873
874         char    curdir[MAXPATHLEN];     /* startup directory */
875         char    objdir[MAXPATHLEN];     /* where we chdir'ed to */
876
877         /*
878          * Initialize program global variables.
879          */
880         beSilent = FALSE;               /* Print commands as executed */
881         ignoreErrors = FALSE;           /* Pay attention to non-zero returns */
882         noExecute = FALSE;              /* Execute all commands */
883         keepgoing = FALSE;              /* Stop on error */
884         allPrecious = FALSE;            /* Remove targets when interrupted */
885         touchFlag = FALSE;              /* Actually update targets */
886         usePipes = TRUE;                /* Catch child output in pipes */
887         debug = 0;                      /* No debug verbosity, please. */
888         jobsRunning = FALSE;
889
890         jobLimit = DEFMAXJOBS;
891         compatMake = FALSE;             /* No compat mode */
892
893         /*
894          * Initialize make flags variable.
895          */
896         Lst_Init(&mf.makefiles);
897         Lst_Init(&mf.variables);
898
899         mf.expandVars = TRUE;
900         mf.noBuiltins = FALSE;          /* Read the built-in rules */
901         mf.queryFlag = FALSE;
902
903         if (getenv("MAKE_JOBS_FIFO") == NULL)
904                 mf.forceJobs = FALSE;
905         else
906                 mf.forceJobs = TRUE;
907
908         /*
909          * Initialize the parsing, directory and variable modules to prepare
910          * for the reading of inclusion paths and variable settings on the
911          * command line
912          */
913         Proc_Init();
914         Shell_Init();
915
916         InitVariables(&mf, argc, argv, curdir, objdir);
917
918         /*
919          * Once things are initialized, add the original directory to the
920          * search path. The current directory is also placed as a variable
921          * for make scripts.
922          */
923
924         Dir_Init();
925         Dir_InitDot();          /* Initialize the "." directory */
926
927         if (strcmp(objdir, curdir) != 0)
928                 Path_AddDir(&dirSearchPath, curdir);
929
930         /*
931          * Be compatible if user did not specify -j and did not explicitly
932          * turned compatibility on
933          */
934         if (!compatMake && !mf.forceJobs)
935                 compatMake = TRUE;
936
937         /*
938          * Initialize target and suffix modules in preparation for
939          * parsing the makefile(s)
940          */
941         Targ_Init();
942         Suff_Init();
943
944         DEFAULT = NULL;
945         time(&now);
946
947         /*
948          * If no user-supplied system path was given (through the -m option)
949          * add the directories from the DEFSYSPATH (more than one may be given
950          * as dir1:...:dirn) to the system include path.
951          */
952         if (TAILQ_EMPTY(&sysIncPath)) {
953                 char syspath[] = PATH_DEFSYSPATH;
954                 char *cp = NULL;
955                 char *start;
956
957                 for (start = syspath; *start != '\0'; start = cp) {
958                         for (cp = start; *cp != '\0' && *cp != ':'; cp++)
959                                 continue;
960                         if (*cp == '\0') {
961                                 Path_AddDir(&sysIncPath, start);
962                         } else {
963                                 *cp++ = '\0';
964                                 Path_AddDir(&sysIncPath, start);
965                         }
966                 }
967         }
968
969
970         ReadInputFiles(&mf, curdir, objdir);
971
972         /* Install all the flags into the MAKE envariable. */
973         {
974                 const char *p;
975
976                 if (((p = Var_Value(".MAKEFLAGS", VAR_GLOBAL)) != NULL) && *p)
977                         setenv("MAKEFLAGS", p, 1);
978         }
979
980         /*
981          * For compatibility, look at the directories in the VPATH variable
982          * and add them to the search path, if the variable is defined. The
983          * variable's value is in the same format as the PATH envariable, i.e.
984          * <directory>:<directory>:<directory>...
985          */
986         if (Var_Exists("VPATH", VAR_CMD)) {
987                 Buffer  *buf;
988                 char    *vpath;
989                 char    savec;
990
991                 buf = Var_Subst("${VPATH}", VAR_CMD, FALSE);
992                 vpath = Buf_Data(buf);
993                 do {
994                         char    *ptr;
995                         /* skip to end of directory */
996                         for (ptr = vpath; *ptr != ':' && *ptr != '\0'; ptr++)
997                                 ;
998
999                         /* Save terminator character so know when to stop */
1000                         savec = *ptr;
1001                         *ptr = '\0';
1002
1003                         /* Add directory to search path */
1004                         Path_AddDir(&dirSearchPath, vpath);
1005
1006                         vpath = ptr + 1;
1007                 } while (savec != '\0');
1008
1009                 Buf_Destroy(buf, TRUE);
1010         }
1011
1012         /*
1013          * Now that all search paths have been read for suffixes et al, it's
1014          * time to add the default search path to their lists...
1015          */
1016         Suff_DoPaths();
1017
1018         /* print the initial graph, if the user requested it */
1019         if (DEBUG(GRAPH1))
1020                 Targ_PrintGraph(1);
1021
1022         /* print the values of any variables requested by the user */
1023         if (Lst_IsEmpty(&mf.variables)) {
1024                 /*
1025                  * Since the user has not requested that any variables
1026                  * be printed, we can build targets.
1027                  *
1028                  * Have read the entire graph and need to make a list of targets
1029                  * to create. If none was given on the command line, we consult
1030                  * the parsing module to find the main target(s) to create.
1031                  */
1032                 Lst targs = Lst_Initializer(targs);
1033
1034                 if (Lst_IsEmpty(&create))
1035                         Parse_MainName(&targs);
1036                 else
1037                         Targ_FindList(&targs, &create, TARG_CREATE);
1038
1039                 /* Traverse the graph, checking on all the targets */
1040                 if (compatMake) {
1041                         outOfDate = Compat_Run(&targs, mf.queryFlag);
1042                 } else {
1043                         outOfDate = Make_Run(&targs, mf.queryFlag);
1044                 }
1045                 Lst_Destroy(&targs, NOFREE);
1046
1047         } else {
1048                 Var_Print(&mf.variables, mf.expandVars);
1049         }
1050
1051         Lst_Destroy(&mf.variables, free);
1052         Lst_Destroy(&mf.makefiles, free);
1053         Lst_Destroy(&create, free);
1054
1055         /* print the graph now it's been processed if the user requested it */
1056         if (DEBUG(GRAPH2))
1057                 Targ_PrintGraph(2);
1058
1059         if (mf.queryFlag && outOfDate)
1060                 return (1);
1061         else
1062                 return (0);
1063 }
1064