bug 2450: Allow build of RELEASE 3.2 from master's bmake
[dragonfly.git] / usr.bin / make / main.c
CommitLineData
edf6dd37 1/*-
984263bc
MD
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.
1de703da
MD
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
1901cbd2 40 * $FreeBSD: src/usr.bin/make/main.c,v 1.118 2005/02/13 13:33:56 harti Exp $
0955fd91 41 * $DragonFly: src/usr.bin/make/main.c,v 1.146 2007/01/19 07:23:43 dillon Exp $
984263bc
MD
42 */
43
df64c352
MO
44/*
45 * main.c
984263bc
MD
46 * The main file for this entire program. Exit routines etc
47 * reside here.
48 *
49 * Utility functions defined in this file:
df64c352
MO
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.
984263bc
MD
55 */
56
984263bc
MD
57#ifndef MACHINE
58#include <sys/utsname.h>
59#endif
9863ce62 60#include <sys/param.h>
9863ce62 61#include <sys/stat.h>
e2ea6619 62#include <sys/sysctl.h>
edf6dd37 63#include <sys/time.h>
e1ec67f4 64#include <sys/queue.h>
edf6dd37 65#include <sys/resource.h>
984263bc
MD
66#include <sys/wait.h>
67#include <err.h>
984263bc 68#include <errno.h>
79ffa91f 69#include <stdlib.h>
9863ce62 70#include <string.h>
d0f0ba15 71#include <unistd.h>
79ffa91f 72
9863ce62 73#include "arch.h"
6a3d9147 74#include "buf.h"
9863ce62 75#include "config.h"
984263bc 76#include "dir.h"
9863ce62 77#include "globals.h"
984263bc 78#include "job.h"
9863ce62
MO
79#include "make.h"
80#include "parse.h"
984263bc 81#include "pathnames.h"
880b6521 82#include "shell.h"
9863ce62
MO
83#include "str.h"
84#include "suff.h"
85#include "targ.h"
86#include "util.h"
87#include "var.h"
984263bc 88
8ad20cfe
MO
89extern char **environ; /* XXX what header declares this variable? */
90
ca28aa20
MO
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
deb5677d 98typedef struct CLI {
62ecbc73 99 /** ordered list of makefiles to read */
c60a3c87 100 Lst makefiles;
0a7e0b85 101
62ecbc73 102 /** list of variables to print */
c60a3c87 103 Lst variables;
0a7e0b85 104
62ecbc73
MO
105 /** Targets to be made */
106 Lst create;
107
22f60e7a
MO
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
4080e755
MO
114 bool expandVars; /* fully expand printed variables */
115 bool builtins; /* -r flag */
116 bool forceJobs; /* -j argument given */
3137cd87
MO
117
118 /**
119 * -q flag:
4080e755 120 * true if we aren't supposed to really make anything, just
3137cd87
MO
121 * see if the targets are out-of-date
122 */
4080e755 123 bool queryFlag;
deb5677d 124} CLI;
8ad20cfe
MO
125
126/* (-E) vars to override from env */
127Lst envFirstVars = Lst_Initializer(envFirstVars);
128
4080e755
MO
129bool allPrecious; /* .PRECIOUS given on line by itself */
130bool beSilent; /* -s flag */
131bool beVerbose; /* -v flag */
132bool compatMake; /* -B argument */
80962b69 133int debug; /* -d flag */
4080e755 134bool ignoreErrors; /* -i flag */
c5784061 135int jobLimit; /* -j argument */
4080e755
MO
136bool jobsRunning; /* true if the jobs might be running */
137bool keepgoing; /* -k flag */
138bool noExecute; /* -n flag */
139bool touchFlag; /* -t flag */
140bool usePipes; /* !-P flag */
567e5d9a 141uint32_t warn_cmd; /* command line warning flags */
c5784061 142uint32_t warn_flags; /* actual warning flags */
567e5d9a 143uint32_t warn_nocmd; /* command line no-warning flags */
0a7e0b85 144
8ad20cfe
MO
145time_t now; /* Time at start of make */
146struct GNode *DEFAULT; /* .DEFAULT node */
984263bc 147
3137cd87 148
df64c352 149/**
05e2db3d
MO
150 * Exit with usage message.
151 */
152static void
153usage(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/**
df64c352
MO
164 * MFLAGS_append
165 * Append a flag with an optional argument to MAKEFLAGS and MFLAGS
d2e0d34c
JS
166 */
167static void
271e747f 168MFLAGS_append(const char *flag, char *arg)
d2e0d34c 169{
d5bdc48c
MO
170 char *str;
171
8ad20cfe 172 Var_Append(".MAKEFLAGS", flag, VAR_GLOBAL);
9d304036 173 if (arg != NULL) {
d5bdc48c 174 str = MAKEFLAGS_quote(arg);
8ad20cfe 175 Var_Append(".MAKEFLAGS", str, VAR_GLOBAL);
9d304036
JS
176 free(str);
177 }
d2e0d34c
JS
178
179 Var_Append("MFLAGS", flag, VAR_GLOBAL);
9d304036 180 if (arg != NULL) {
d5bdc48c 181 str = MAKEFLAGS_quote(arg);
9d304036
JS
182 Var_Append("MFLAGS", str, VAR_GLOBAL);
183 free(str);
184 }
d2e0d34c
JS
185}
186
df64c352 187/**
05e2db3d
MO
188 * Open and parse the given makefile.
189 *
190 * Results:
4080e755 191 * true if ok. false if couldn't open file.
05e2db3d 192 */
4080e755 193static bool
deb5677d 194ReadMakefile(Parser *parser, CLI *cli, const char file[], const char curdir[], const char objdir[])
05e2db3d 195{
6111d18b
MO
196 char path[MAXPATHLEN];
197 FILE *stream;
198 char *fname;
199 char *name;
05e2db3d 200
6111d18b 201 if (!strcmp(file, "-")) {
deb5677d 202 Parse_File(parser, cli, "(stdin)", stdin);
d911a818 203 Var_SetGlobal("MAKEFILE", "");
4080e755 204 return (true);
6111d18b 205 }
05e2db3d 206
6111d18b
MO
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 }
05e2db3d 215#if THIS_BREAKS_THINGS
6111d18b
MO
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 }
05e2db3d 236#else
6111d18b 237 stream = fopen(path, "r");
05e2db3d 238#endif
6111d18b
MO
239 if (stream != NULL) {
240 if (strcmp(file, ".depend") != 0)
241 Var_SetGlobal("MAKEFILE", file);
deb5677d 242 Parse_File(parser, cli, path, stream);
05e2db3d 243 fclose(stream);
4080e755 244 return (true);
05e2db3d 245 }
6111d18b
MO
246
247 /* look in -I and system include directories. */
248 fname = estrdup(file);
249 name = NULL;
250 if (name == NULL)
deb5677d 251 name = Path_FindFile(fname, &cli->parseIncPath);
6111d18b 252 if (name == NULL)
deb5677d 253 name = Path_FindFile(fname, &cli->sysIncPath);
6111d18b
MO
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);
deb5677d 266 Parse_File(parser, cli, name, stream);
6111d18b 267 fclose(stream);
4080e755 268 return (true);
6111d18b
MO
269 }
270 }
271
4080e755 272 return (false); /* no makefile found */
05e2db3d
MO
273}
274
0fffc5db
MO
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 */
8b779f97 280static void
deb5677d 281ReadInputFiles(Parser *parser, CLI *cli, const char curdir[], const char objdir[])
8b779f97 282{
deb5677d 283 if (cli->builtins) {
2b239c7a 284 char defsysmk[] = PATH_DEFSYSMK; /* Path of sys.mk */
8b779f97
MO
285 Lst sysMkPath = Lst_Initializer(sysMkPath);
286 LstNode *ln;
8b779f97 287
deb5677d 288 Path_Expand(defsysmk, &cli->sysIncPath, &sysMkPath);
8b779f97
MO
289 if (Lst_IsEmpty(&sysMkPath))
290 Fatal("make: no system rules (%s).", PATH_DEFSYSMK);
2b239c7a 291
8b779f97 292 LST_FOREACH(ln, &sysMkPath) {
2b239c7a 293 char *name = Lst_Datum(ln);
deb5677d 294 if (!ReadMakefile(parser, cli, name, curdir, objdir))
2b239c7a 295 Fatal("make: cannot open %s.", name);
8b779f97 296 }
8b779f97
MO
297 Lst_Destroy(&sysMkPath, free);
298 }
299
deb5677d 300 if (!Lst_IsEmpty(&cli->makefiles)) {
8b779f97
MO
301 LstNode *ln;
302
deb5677d 303 LST_FOREACH(ln, &cli->makefiles) {
2b239c7a 304 char *name = Lst_Datum(ln);
deb5677d 305 if (!ReadMakefile(parser, cli, name, curdir, objdir))
2b239c7a 306 Fatal("make: cannot open %s.", name);
8b779f97 307 }
deb5677d 308 } else if (ReadMakefile(parser, cli, "BSDmakefile", curdir, objdir)) {
8b779f97 309 /* read BSDmakefile */
deb5677d 310 } else if (ReadMakefile(parser, cli, "makefile", curdir, objdir)) {
8b779f97 311 /* read makefile */
deb5677d 312 } else if (ReadMakefile(parser, cli, "Makefile", curdir, objdir)) {
8b779f97
MO
313 /* read Makefile */
314 } else {
315 /* No Makefile found */
316 }
317
deb5677d 318 ReadMakefile(parser, cli, ".depend", curdir, objdir);
8b779f97
MO
319}
320
05e2db3d 321/**
567e5d9a
MO
322 * Main_ParseWarn
323 *
324 * Handle argument to warning option.
325 */
326int
327Main_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/**
df64c352 374 * MainParseArgs
984263bc
MD
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 *
984263bc
MD
380 * Side Effects:
381 * Various global and local flags will be set depending on the flags
382 * given
383 */
384static void
deb5677d 385MainParseArgs(CLI *cli, int argc, char **argv)
984263bc 386{
984263bc 387 int c;
4080e755 388 bool found_dd = false;
984263bc 389
ef844d51 390rearg:
984263bc 391 optind = 1; /* since we're called more than once */
6ef095c6 392 optreset = 1;
59620cdf 393#define OPTFLAGS "ABC:D:E:I:J:PSV:Xd:ef:ij:km:nqrstvx:"
bf7f2be4
MO
394 for (;;) {
395 if ((optind < argc) && strcmp(argv[optind], "--") == 0) {
4080e755 396 found_dd = true;
bf7f2be4
MO
397 }
398 if ((c = getopt(argc, argv, OPTFLAGS)) == -1) {
399 break;
400 }
984263bc 401 switch(c) {
dd416385
MO
402
403 case 'A':
4080e755 404 arch_fatal = false;
dd416385
MO
405 MFLAGS_append("-A", NULL);
406 break;
984263bc
MD
407 case 'C':
408 if (chdir(optarg) == -1)
409 err(1, "chdir %s", optarg);
410 break;
411 case 'D':
d911a818 412 Var_SetGlobal(optarg, "1");
d2e0d34c 413 MFLAGS_append("-D", optarg);
984263bc
MD
414 break;
415 case 'I':
deb5677d 416 Path_AddDir(&cli->parseIncPath, optarg);
d2e0d34c 417 MFLAGS_append("-I", optarg);
984263bc 418 break;
59620cdf
JM
419 case 'J':
420 /* Allow make child of bmake parent (No-op) */
421 break;
984263bc 422 case 'V':
deb5677d 423 Lst_AtEnd(&cli->variables, estrdup(optarg));
d2e0d34c 424 MFLAGS_append("-V", optarg);
984263bc
MD
425 break;
426 case 'X':
4080e755 427 cli->expandVars = false;
984263bc
MD
428 break;
429 case 'B':
4080e755 430 compatMake = true;
d2e0d34c 431 MFLAGS_append("-B", NULL);
aa582f64 432 unsetenv("MAKE_JOBS_FIFO");
984263bc 433 break;
984263bc 434 case 'P':
4080e755 435 usePipes = false;
d2e0d34c 436 MFLAGS_append("-P", NULL);
984263bc
MD
437 break;
438 case 'S':
4080e755 439 keepgoing = false;
d2e0d34c 440 MFLAGS_append("-S", NULL);
984263bc
MD
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:
df64c352
MO
491 warnx("illegal argument to d option "
492 "-- %c", *modules);
984263bc
MD
493 usage();
494 }
d2e0d34c 495 MFLAGS_append("-d", optarg);
984263bc
MD
496 break;
497 }
498 case 'E':
913d5730 499 Lst_AtEnd(&envFirstVars, estrdup(optarg));
d2e0d34c 500 MFLAGS_append("-E", optarg);
984263bc
MD
501 break;
502 case 'e':
4080e755 503 checkEnvFirst = true;
d2e0d34c 504 MFLAGS_append("-e", NULL);
984263bc
MD
505 break;
506 case 'f':
deb5677d 507 Lst_AtEnd(&cli->makefiles, estrdup(optarg));
984263bc
MD
508 break;
509 case 'i':
4080e755 510 ignoreErrors = true;
d2e0d34c 511 MFLAGS_append("-i", NULL);
984263bc
MD
512 break;
513 case 'j': {
514 char *endptr;
515
4080e755 516 cli->forceJobs = true;
c5784061
MO
517 jobLimit = strtol(optarg, &endptr, 10);
518 if (jobLimit <= 0 || *endptr != '\0') {
984263bc
MD
519 warnx("illegal number, -j argument -- %s",
520 optarg);
521 usage();
522 }
d2e0d34c 523 MFLAGS_append("-j", optarg);
984263bc
MD
524 break;
525 }
526 case 'k':
4080e755 527 keepgoing = true;
d2e0d34c 528 MFLAGS_append("-k", NULL);
984263bc
MD
529 break;
530 case 'm':
deb5677d 531 Path_AddDir(&cli->sysIncPath, optarg);
d2e0d34c 532 MFLAGS_append("-m", optarg);
984263bc
MD
533 break;
534 case 'n':
4080e755 535 noExecute = true;
d2e0d34c 536 MFLAGS_append("-n", NULL);
984263bc
MD
537 break;
538 case 'q':
4080e755 539 cli->queryFlag = true;
984263bc 540 /* Kind of nonsensical, wot? */
d2e0d34c 541 MFLAGS_append("-q", NULL);
984263bc
MD
542 break;
543 case 'r':
4080e755 544 cli->builtins = false;
d2e0d34c 545 MFLAGS_append("-r", NULL);
984263bc
MD
546 break;
547 case 's':
4080e755 548 beSilent = true;
d2e0d34c 549 MFLAGS_append("-s", NULL);
984263bc
MD
550 break;
551 case 't':
4080e755 552 touchFlag = true;
d2e0d34c 553 MFLAGS_append("-t", NULL);
984263bc
MD
554 break;
555 case 'v':
4080e755 556 beVerbose = true;
d2e0d34c 557 MFLAGS_append("-v", NULL);
984263bc 558 break;
ca790272 559 case 'x':
567e5d9a 560 if (Main_ParseWarn(optarg, 1) != -1)
ca790272 561 MFLAGS_append("-x", optarg);
ca790272 562 break;
984263bc
MD
563 default:
564 case '?':
565 usage();
566 }
567 }
6ef095c6
MO
568 argv += optind;
569 argc -= optind;
984263bc 570
4080e755 571 oldVars = true;
984263bc
MD
572
573 /*
6ef095c6
MO
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.
984263bc 579 */
6ef095c6 580 for (; *argv != NULL; ++argv, --argc) {
c382ef3f 581 if (Parse_IsVar(*argv)) {
9d304036
JS
582 char *ptr = MAKEFLAGS_quote(*argv);
583
8ad20cfe 584 Var_Append(".MAKEFLAGS", ptr, VAR_GLOBAL);
6ef095c6 585 Parse_DoVar(*argv, VAR_CMD);
9d304036
JS
586 free(ptr);
587
6ef095c6
MO
588 } else if ((*argv)[0] == '-') {
589 if ((*argv)[1] == '\0') {
590 /*
591 * (*argv) is a single dash, so we
592 * just ignore it.
593 */
bf7f2be4
MO
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 */
deb5677d 600 Lst_AtEnd(&cli->create, estrdup(*argv));
6ef095c6
MO
601 } else {
602 /*
bf7f2be4
MO
603 * (*argv) is a -flag, so backup argv and
604 * argc. getopt() expects options to start
605 * in the 2nd position.
6ef095c6
MO
606 */
607 argc++;
608 argv--;
984263bc
MD
609 goto rearg;
610 }
6ef095c6
MO
611
612 } else if ((*argv)[0] == '\0') {
6ef095c6
MO
613 Punt("illegal (null) argument.");
614
615 } else {
deb5677d 616 Lst_AtEnd(&cli->create, estrdup(*argv));
984263bc 617 }
6ef095c6 618 }
984263bc
MD
619}
620
df64c352
MO
621/**
622 * Main_ParseArgLine
f86feb9b 623 * Used by the parse module when a .MFLAGS or .MAKEFLAGS target
984263bc
MD
624 * is encountered and by main() when reading the .MAKEFLAGS envariable.
625 * Takes a line of arguments and breaks it into its
f86feb9b 626 * component words and passes those words and the number of them to the
984263bc
MD
627 * MainParseArgs function.
628 * The line should have all its leading whitespace removed.
629 *
984263bc
MD
630 * Side Effects:
631 * Only those that come from the various arguments.
632 */
633void
deb5677d 634Main_ParseArgLine(CLI *cli, const char line[], int mflags)
984263bc 635{
db647c9e 636 ArgArray aa;
984263bc 637
db647c9e
MO
638 if (mflags) {
639 MAKEFLAGS_break(&aa, line);
640 } else {
4080e755 641 brk_string(&aa, line, true);
db647c9e 642 }
deb5677d 643 MainParseArgs(cli, aa.argc, aa.argv);
db647c9e 644 ArgArray_Done(&aa);
984263bc
MD
645}
646
50259f9c 647/**
7f283202
MO
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).
50259f9c 652 */
f21c5d84 653static int
856add86 654CheckDir(const char path[], char newdir[])
984263bc
MD
655{
656 struct stat sb;
657
50259f9c
MO
658 /*
659 * Check if the path is a directory. If not fail without reporting
660 * an error.
661 */
662 if (stat(path, &sb) < 0) {
7f283202 663 return (0);
50259f9c
MO
664 }
665 if (S_ISDIR(sb.st_mode) == 0) {
f21c5d84 666 return (0);
984263bc
MD
667 }
668
50259f9c
MO
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);
f21c5d84 676 return (0);
50259f9c 677 }
f21c5d84 678 if (getcwd(newdir, MAXPATHLEN) == NULL) {
50259f9c 679 warn("warning: %s", path);
f21c5d84 680 return (0);
50259f9c 681 }
856add86
MO
682
683 /*
684 * Directory in path is accessable, newdir should now contain the
685 * path to it.
686 */
f21c5d84 687 return (1);
984263bc
MD
688}
689
856add86
MO
690/**
691 * Determine location of the object directory.
692 */
6111d18b 693static void
856add86 694FindObjDir(const char machine[], char curdir[], char objdir[])
6111d18b
MO
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);
856add86 726 if (CheckDir(mdpath, newdir)) {
6111d18b
MO
727 strcpy(objdir, newdir);
728 return;
729 }
730 strcpy(objdir, curdir);
731 return;
732 }
733
734 if ((env = getenv("MAKEOBJDIR")) != NULL) {
856add86 735 if (CheckDir(env, newdir)) {
6111d18b
MO
736 strcpy(objdir, newdir);
737 return;
738 }
739 strcpy(objdir, curdir);
740 return;
741 }
742
743 snprintf(mdpath, MAXPATHLEN, "%s.%s", PATH_OBJDIR, machine);
856add86 744 if (CheckDir(mdpath, newdir)) {
6111d18b
MO
745 strcpy(objdir, newdir);
746 return;
747 }
748
856add86 749 if (CheckDir(PATH_OBJDIR, newdir)) {
6111d18b
MO
750 strcpy(objdir, newdir);
751 return;
752 }
753
754 snprintf(mdpath, MAXPATHLEN, "%s%s", PATH_OBJDIRPREFIX, curdir);
856add86 755 if (CheckDir(mdpath, newdir)) {
6111d18b
MO
756 strcpy(objdir, newdir);
757 return;
758 }
759
760 strcpy(objdir, curdir);
761}
762
ca8582e4 763/**
22c40a18
MO
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.
984263bc 768 */
22c40a18 769static void
8cfc630d 770InitVariables(const char progname[])
984263bc 771{
0955fd91 772 const char *machine_platform;
22c40a18 773 const char *machine_arch;
0955fd91 774 const char *machine;
e2ea6619
MD
775 char buf[256];
776 size_t bufsiz;
8ad20cfe 777
8cfc630d 778 Var_SetGlobal("MAKE", progname);
22c40a18
MO
779 Var_SetGlobal(".MAKEFLAGS", "");
780 Var_SetGlobal("MFLAGS", "");
89a1b397 781
22c40a18
MO
782 Var_SetGlobal(".DIRECTIVE_MAKEENV", "YES");
783 Var_SetGlobal(".ST_EXPORTVAR", "YES");
784#ifdef MAKE_VERSION
785 Var_SetGlobal("MAKE_VERSION", MAKE_VERSION);
984263bc 786#endif
22c40a18 787
984263bc 788 /*
0955fd91
MD
789 * The make program defines MACHINE_PLATFORM, MACHINE and MACHINE_ARCH.
790 * These parameters are taken from the running system but can be
e2ea6619 791 * overridden by environment variables.
984263bc 792 *
0955fd91
MD
793 * MACHINE_PLATFORM
794 * - This is the platform, e.g. "vkernel", "pc32",
e2ea6619
MD
795 * and so forth.
796 *
0955fd91
MD
797 * MACHINE - This is the machine architecture and in most
798 * cases is the same as the cpu architecture.
799 *
e2ea6619
MD
800 * MACHINE_ARCH - This is the cpu architecture, for example "i386".
801 * Several different platforms may use the same
802 * cpu architecture.
803 *
0955fd91 804 * In most, but not all cases, MACHINE == MACHINE_ARCH.
e2ea6619 805 *
0955fd91
MD
806 * PLATFORM distinguishes differences between, say, a virtual kernel
807 * build and a real kernel build.
984263bc 808 */
0955fd91
MD
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
ca8582e4 817 if ((machine = getenv("MACHINE")) == NULL) {
e2ea6619
MD
818 bufsiz = sizeof(buf);
819 if (sysctlbyname("hw.machine", buf, &bufsiz, NULL, 0) < 0)
820 machine = "unknown";
821 else
822 machine = strdup(buf);
984263bc
MD
823 }
824
ca8582e4 825 if ((machine_arch = getenv("MACHINE_ARCH")) == NULL) {
e2ea6619
MD
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);
984263bc
MD
831 }
832
0955fd91 833 Var_SetGlobal("MACHINE_PLATFORM", machine_platform);
d911a818
MO
834 Var_SetGlobal("MACHINE", machine);
835 Var_SetGlobal("MACHINE_ARCH", machine_arch);
22c40a18
MO
836}
837
be490b49 838/**
856add86
MO
839 * Build targets given in the command line or if none were given
840 * use the main target determined by the parsing module.
be490b49 841 */
24173d32 842static int
856add86 843BuildStuff(CLI *cli)
24173d32 844{
be490b49
MO
845 int status;
846 Lst targs = Lst_Initializer(targs);
24173d32 847
deb5677d 848 if (Lst_IsEmpty(&cli->create))
24173d32
MO
849 Parse_MainName(&targs);
850 else
deb5677d 851 Targ_FindList(&targs, &cli->create, TARG_CREATE);
24173d32
MO
852
853 /* Traverse the graph, checking on all the targets */
854 if (compatMake) {
4080e755 855 Sig_Init(true);
deb5677d 856 status = Compat_Run(&targs, cli->queryFlag);
24173d32 857 } else {
4080e755 858 Sig_Init(false);
003ef929 859 status = Make_Run(&targs, cli->queryFlag);
24173d32 860 }
24173d32 861
003ef929 862 Lst_Destroy(&targs, NOFREE);
be490b49 863 return (status);
24173d32
MO
864}
865
22c40a18
MO
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 */
883int
884main(int argc, char **argv)
885{
8cfc630d 886 CLI cli;
62ecbc73 887 Parser parser;
ba49bfff 888 Shell *shell;
24173d32
MO
889 int status; /* exit status */
890 char curdir[MAXPATHLEN]; /* startup directory */
891 char objdir[MAXPATHLEN]; /* where we chdir'ed to */
8cfc630d 892 const char *make_flags;
22c40a18 893
1e871808 894 /*------------------------------------------------------------*
ccd8b25e 895 * This section initializes stuff that require no input.
1e871808 896 *------------------------------------------------------------*/
22c40a18 897 /*
ccd8b25e 898 * Initialize program globals.
22c40a18 899 */
4080e755
MO
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 */
22c40a18 907 debug = 0; /* No debug verbosity, please. */
4080e755 908 jobsRunning = false;
22c40a18
MO
909
910 jobLimit = DEFMAXJOBS;
4080e755 911 compatMake = false; /* No compat mode */
22c40a18
MO
912
913 /*
ccd8b25e 914 * Initialize program flags.
22c40a18 915 */
deb5677d
MO
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);
22c40a18 921
4080e755
MO
922 cli.expandVars = true;
923 cli.builtins = true; /* Read the built-in rules */
924 cli.queryFlag = false;
925 cli.forceJobs = false;
62ecbc73 926
ba49bfff
MO
927 shell = Shell_Match(DEFSHELLNAME);
928
22c40a18 929 /*
18e2da36 930 * Initialize the various modules.
22c40a18
MO
931 */
932 Proc_Init();
ba49bfff 933 commandShell = shell;
ceac73f4
MO
934 Targ_Init();
935 Suff_Init();
637ccb80 936 Dir_Init();
22c40a18 937
ceac73f4 938 /*------------------------------------------------------------*
ccd8b25e 939 * This section initializes stuff that depend on things
ceac73f4
MO
940 * in the enviornment, command line, or a input file.
941 *------------------------------------------------------------*/
8cfc630d
MO
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
856add86 955 FindObjDir(Var_Value("MACHINE", VAR_GLOBAL), curdir, objdir);
1c0ed2c9
MO
956 Var_SetGlobal(".CURDIR", curdir);
957 Var_SetGlobal(".OBJDIR", objdir);
958
8cfc630d
MO
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
c6362b5b 969 LST_FOREACH(ln, &cli.create) {
8cfc630d
MO
970 char *name = Lst_Datum(ln);
971
972 Var_Append(".TARGETS", name, VAR_GLOBAL);
973 }
974 }
f21c5d84 975
637ccb80 976 Dir_CurObj(curdir, objdir);
984263bc
MD
977
978 /*
984263bc
MD
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 */
deb5677d 983 if (TAILQ_EMPTY(&cli.sysIncPath)) {
ca8582e4 984 char syspath[] = PATH_DEFSYSPATH;
31ae001b
MO
985 char *start = syspath;
986 char *cp;
987
988 while ((cp = strsep(&start, ":")) != NULL) {
deb5677d 989 Path_AddDir(&cli.sysIncPath, cp);
984263bc
MD
990 }
991 }
992
ceac73f4 993 if (getenv("MAKE_JOBS_FIFO") != NULL)
4080e755 994 cli.forceJobs = true;
ceac73f4
MO
995
996 /*
997 * Be compatible if user did not specify -j and did not explicitly
998 * turned compatibility on
999 */
4080e755
MO
1000 if (compatMake == false && cli.forceJobs == false)
1001 compatMake = true;
ceac73f4
MO
1002
1003 DEFAULT = NULL;
1004 time(&now);
1005
deb5677d
MO
1006 parser.create = &cli.create;
1007 parser.parseIncPath = &cli.parseIncPath;
1008 parser.sysIncPath = &cli.sysIncPath;
ceac73f4 1009
deb5677d 1010 ReadInputFiles(&parser, &cli, curdir, objdir);
984263bc 1011
1e871808
MO
1012 /*------------------------------------------------------------*
1013 * We are finished processing inputs.
1014 *------------------------------------------------------------*/
1015
984263bc 1016 /* Install all the flags into the MAKE envariable. */
10d0fb4c
MO
1017 {
1018 const char *p;
1019
a46501be 1020 p = Var_Value(".MAKEFLAGS", VAR_GLOBAL);
b0961026
MO
1021 if (p != NULL && *p != '\0') {
1022 if (setenv("MAKEFLAGS", p, 1) == -1)
1023 Punt("setenv: MAKEFLAGS: can't allocate memory");
1024 }
10d0fb4c 1025 }
984263bc
MD
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 */
038e99f8 1033 if (Var_Value("VPATH", VAR_CMD) != NULL) {
4080e755 1034 Buffer *buf = Var_Subst("${VPATH}", VAR_CMD, false);
a46501be
MO
1035 char *start = Buf_Data(buf);
1036 char *cp;
1037
1038 while ((cp = strsep(&start, ":")) != NULL) {
1039 Path_AddDir(&dirSearchPath, cp);
1040 }
82c2ab03 1041
4080e755 1042 Buf_Destroy(buf, true);
984263bc
MD
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
deb5677d 1055 if (Lst_IsEmpty(&cli.variables)) {
856add86 1056 status = BuildStuff(&cli);
82c2ab03 1057 } else {
24173d32 1058 /* Print the values of variables requested by the user. */
deb5677d 1059 Var_Print(&cli.variables, cli.expandVars);
24173d32 1060
614ddb22 1061 /*
24173d32
MO
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
614ddb22 1069 */
deb5677d 1070 status = cli.queryFlag ? 1 : 0;
984263bc
MD
1071 }
1072
c7c06ff1
MO
1073 /* print the graph now it's been processed if the user requested it */
1074 if (DEBUG(GRAPH2))
1075 Targ_PrintGraph(2);
1076
22f60e7a 1077#if 0
deb5677d
MO
1078 TAILQ_DESTROY(&cli.sysIncPath);
1079 TAILQ_DESTROY(&cli.parseIncPath);
22f60e7a 1080#endif
deb5677d
MO
1081 Lst_Destroy(&cli.create, free);
1082 Lst_Destroy(&cli.variables, free);
1083 Lst_Destroy(&cli.makefiles, free);
984263bc 1084
24173d32 1085 return (status);
984263bc
MD
1086}
1087