VirtualBox

source: kBuild/trunk/src/kmk/main.c@ 25

Last change on this file since 25 was 25, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r24,
which included commits to RCS files with non-trunk default branches.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.7 KB
Line 
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
39#ifndef lint
40static const char copyright[] =
41"@(#) Copyright (c) 1988, 1989, 1990, 1993\n\
42 The Regents of the University of California. All rights reserved.\n";
43#endif /* not lint */
44
45#ifndef lint
46#if 0
47static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
48#else
49static const char rcsid[] =
50 "$FreeBSD: src/usr.bin/make/main.c,v 1.35.2.6 2002/07/24 16:50:18 ru Exp $";
51#endif
52#endif /* not lint */
53
54/*-
55 * main.c --
56 * The main file for this entire program. Exit routines etc
57 * reside here.
58 *
59 * Utility functions defined in this file:
60 * Main_ParseArgLine Takes a line of arguments, breaks them and
61 * treats them as if they were given when first
62 * invoked. Used by the parse module to implement
63 * the .MFLAGS target.
64 *
65 * Error Print a tagged error message. The global
66 * MAKE variable must have been defined. This
67 * takes a format string and two optional
68 * arguments for it.
69 *
70 * Fatal Print an error message and exit. Also takes
71 * a format string and two arguments.
72 *
73 * Punt Aborts all jobs and exits with a message. Also
74 * takes a format string and two arguments.
75 *
76 * Finish Finish things up by printing the number of
77 * errors which occured, as passed to it, and
78 * exiting.
79 */
80
81#include <sys/types.h>
82#include <sys/time.h>
83#include <sys/param.h>
84#include <sys/resource.h>
85#include <sys/signal.h>
86#include <sys/stat.h>
87#if defined(__i386__)
88#include <sys/sysctl.h>
89#endif
90#ifndef MACHINE
91#include <sys/utsname.h>
92#endif
93#include <sys/wait.h>
94#include <err.h>
95#include <stdlib.h>
96#include <errno.h>
97#include <fcntl.h>
98#include <stdio.h>
99#include <sysexits.h>
100#ifdef __STDC__
101#include <stdarg.h>
102#else
103#include <varargs.h>
104#endif
105#include "make.h"
106#include "hash.h"
107#include "dir.h"
108#include "job.h"
109#include "pathnames.h"
110
111#ifndef DEFMAXLOCAL
112#define DEFMAXLOCAL DEFMAXJOBS
113#endif /* DEFMAXLOCAL */
114
115#define MAKEFLAGS ".MAKEFLAGS"
116
117Lst create; /* Targets to be made */
118time_t now; /* Time at start of make */
119GNode *DEFAULT; /* .DEFAULT node */
120Boolean allPrecious; /* .PRECIOUS given on line by itself */
121
122static Boolean noBuiltins; /* -r flag */
123static Lst makefiles; /* ordered list of makefiles to read */
124static Boolean printVars; /* print value of one or more vars */
125static Boolean expandVars; /* fully expand printed variables */
126static Lst variables; /* list of variables to print */
127int maxJobs; /* -j argument */
128static Boolean forceJobs; /* -j argument given */
129static int maxLocal; /* -L argument */
130Boolean compatMake; /* -B argument */
131Boolean debug; /* -d flag */
132Boolean noExecute; /* -n flag */
133Boolean keepgoing; /* -k flag */
134Boolean queryFlag; /* -q flag */
135Boolean touchFlag; /* -t flag */
136Boolean usePipes; /* !-P flag */
137Boolean ignoreErrors; /* -i flag */
138Boolean beSilent; /* -s flag */
139Boolean beVerbose; /* -v flag */
140Boolean oldVars; /* variable substitution style */
141Boolean checkEnvFirst; /* -e flag */
142Lst envFirstVars; /* (-E) vars to override from env */
143static Boolean jobsRunning; /* TRUE if the jobs might be running */
144
145static void MainParseArgs __P((int, char **));
146char * chdir_verify_path __P((char *, char *));
147static int ReadMakefile __P((ClientData, ClientData));
148static void usage __P((void));
149
150static char *curdir; /* startup directory */
151static char *objdir; /* where we chdir'ed to */
152
153/*-
154 * MainParseArgs --
155 * Parse a given argument vector. Called from main() and from
156 * Main_ParseArgLine() when the .MAKEFLAGS target is used.
157 *
158 * XXX: Deal with command line overriding .MAKEFLAGS in makefile
159 *
160 * Results:
161 * None
162 *
163 * Side Effects:
164 * Various global and local flags will be set depending on the flags
165 * given
166 */
167static void
168MainParseArgs(argc, argv)
169 int argc;
170 char **argv;
171{
172 extern int optind;
173 extern char *optarg;
174 char *p;
175 int c;
176
177 optind = 1; /* since we're called more than once */
178#ifdef REMOTE
179# define OPTFLAGS "BD:E:I:L:PSV:Xd:ef:ij:km:nqrstv"
180#else
181# define OPTFLAGS "BD:E:I:PSV:Xd:ef:ij:km:nqrstv"
182#endif
183rearg: while((c = getopt(argc, argv, OPTFLAGS)) != -1) {
184 switch(c) {
185 case 'D':
186 Var_Set(optarg, "1", VAR_GLOBAL);
187 Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
188 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
189 break;
190 case 'I':
191 Parse_AddIncludeDir(optarg);
192 Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
193 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
194 break;
195 case 'V':
196 printVars = TRUE;
197 (void)Lst_AtEnd(variables, (ClientData)optarg);
198 Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
199 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
200 break;
201 case 'X':
202 expandVars = FALSE;
203 break;
204 case 'B':
205 compatMake = TRUE;
206 Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
207 break;
208#ifdef REMOTE
209 case 'L': {
210 char *endptr;
211
212 maxLocal = strtol(optarg, &endptr, 10);
213 if (maxLocal < 0 || *endptr != '\0') {
214 warnx("illegal number, -L argument -- %s",
215 optarg);
216 usage();
217 }
218 Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
219 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
220 break;
221 }
222#endif
223 case 'P':
224 usePipes = FALSE;
225 Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
226 break;
227 case 'S':
228 keepgoing = FALSE;
229 Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
230 break;
231 case 'd': {
232 char *modules = optarg;
233
234 for (; *modules; ++modules)
235 switch (*modules) {
236 case 'A':
237 debug = ~0;
238 break;
239 case 'a':
240 debug |= DEBUG_ARCH;
241 break;
242 case 'c':
243 debug |= DEBUG_COND;
244 break;
245 case 'd':
246 debug |= DEBUG_DIR;
247 break;
248 case 'f':
249 debug |= DEBUG_FOR;
250 break;
251 case 'g':
252 if (modules[1] == '1') {
253 debug |= DEBUG_GRAPH1;
254 ++modules;
255 }
256 else if (modules[1] == '2') {
257 debug |= DEBUG_GRAPH2;
258 ++modules;
259 }
260 break;
261 case 'j':
262 debug |= DEBUG_JOB;
263 break;
264 case 'l':
265 debug |= DEBUG_LOUD;
266 break;
267 case 'm':
268 debug |= DEBUG_MAKE;
269 break;
270 case 's':
271 debug |= DEBUG_SUFF;
272 break;
273 case 't':
274 debug |= DEBUG_TARG;
275 break;
276 case 'v':
277 debug |= DEBUG_VAR;
278 break;
279 default:
280 warnx("illegal argument to d option -- %c", *modules);
281 usage();
282 }
283 Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
284 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
285 break;
286 }
287 case 'E':
288 p = malloc(strlen(optarg) + 1);
289 if (!p)
290 Punt("make: cannot allocate memory.");
291 (void)strcpy(p, optarg);
292 (void)Lst_AtEnd(envFirstVars, (ClientData)p);
293 Var_Append(MAKEFLAGS, "-E", VAR_GLOBAL);
294 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
295 break;
296 case 'e':
297 checkEnvFirst = TRUE;
298 Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
299 break;
300 case 'f':
301 (void)Lst_AtEnd(makefiles, (ClientData)optarg);
302 break;
303 case 'i':
304 ignoreErrors = TRUE;
305 Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
306 break;
307 case 'j': {
308 char *endptr;
309
310 forceJobs = TRUE;
311 maxJobs = strtol(optarg, &endptr, 10);
312 if (maxJobs <= 0 || *endptr != '\0') {
313 warnx("illegal number, -j argument -- %s",
314 optarg);
315 usage();
316 }
317#ifndef REMOTE
318 maxLocal = maxJobs;
319#endif
320 Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
321 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
322 break;
323 }
324 case 'k':
325 keepgoing = TRUE;
326 Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
327 break;
328 case 'm':
329 Dir_AddDir(sysIncPath, optarg);
330 Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
331 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
332 break;
333 case 'n':
334 noExecute = TRUE;
335 Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
336 break;
337 case 'q':
338 queryFlag = TRUE;
339 /* Kind of nonsensical, wot? */
340 Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
341 break;
342 case 'r':
343 noBuiltins = TRUE;
344 Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
345 break;
346 case 's':
347 beSilent = TRUE;
348 Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
349 break;
350 case 't':
351 touchFlag = TRUE;
352 Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
353 break;
354 case 'v':
355 beVerbose = TRUE;
356 Var_Append(MAKEFLAGS, "-v", VAR_GLOBAL);
357 break;
358 default:
359 case '?':
360 usage();
361 }
362 }
363
364 oldVars = TRUE;
365
366 /*
367 * See if the rest of the arguments are variable assignments and
368 * perform them if so. Else take them to be targets and stuff them
369 * on the end of the "create" list.
370 */
371 for (argv += optind, argc -= optind; *argv; ++argv, --argc)
372 if (Parse_IsVar(*argv))
373 Parse_DoVar(*argv, VAR_CMD);
374 else {
375 if (!**argv)
376 Punt("illegal (null) argument.");
377 if (**argv == '-') {
378 if ((*argv)[1])
379 optind = 0; /* -flag... */
380 else
381 optind = 1; /* - */
382 goto rearg;
383 }
384 (void)Lst_AtEnd(create, (ClientData)estrdup(*argv));
385 }
386}
387
388/*-
389 * Main_ParseArgLine --
390 * Used by the parse module when a .MFLAGS or .MAKEFLAGS target
391 * is encountered and by main() when reading the .MAKEFLAGS envariable.
392 * Takes a line of arguments and breaks it into its
393 * component words and passes those words and the number of them to the
394 * MainParseArgs function.
395 * The line should have all its leading whitespace removed.
396 *
397 * Results:
398 * None
399 *
400 * Side Effects:
401 * Only those that come from the various arguments.
402 */
403void
404Main_ParseArgLine(line)
405 char *line; /* Line to fracture */
406{
407 char **argv; /* Manufactured argument vector */
408 int argc; /* Number of arguments in argv */
409
410 if (line == NULL)
411 return;
412 for (; *line == ' '; ++line)
413 continue;
414 if (!*line)
415 return;
416
417 argv = brk_string(line, &argc, TRUE);
418 MainParseArgs(argc, argv);
419}
420
421char *
422chdir_verify_path(path, obpath)
423 char *path;
424 char *obpath;
425{
426 struct stat sb;
427
428 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
429 if (chdir(path)) {
430 warn("warning: %s", path);
431 return 0;
432 }
433 else {
434 if (path[0] != '/') {
435 (void) snprintf(obpath, MAXPATHLEN, "%s/%s",
436 curdir, path);
437 return obpath;
438 }
439 else
440 return path;
441 }
442 }
443
444 return 0;
445}
446
447
448/*-
449 * main --
450 * The main function, for obvious reasons. Initializes variables
451 * and a few modules, then parses the arguments give it in the
452 * environment and on the command line. Reads the system makefile
453 * followed by either Makefile, makefile or the file given by the
454 * -f argument. Sets the .MAKEFLAGS PMake variable based on all the
455 * flags it has received by then uses either the Make or the Compat
456 * module to create the initial list of targets.
457 *
458 * Results:
459 * If -q was given, exits -1 if anything was out-of-date. Else it exits
460 * 0.
461 *
462 * Side Effects:
463 * The program exits when done. Targets are created. etc. etc. etc.
464 */
465int
466main(argc, argv)
467 int argc;
468 char **argv;
469{
470 Lst targs; /* target nodes to create -- passed to Make_Init */
471 Boolean outOfDate = TRUE; /* FALSE if all targets up to date */
472 struct stat sa;
473 char *p, *p1, *path, *pathp;
474#ifdef WANT_ENV_PWD
475 struct stat sb;
476 char *pwd;
477#endif
478 char mdpath[MAXPATHLEN + 1];
479 char obpath[MAXPATHLEN + 1];
480 char cdpath[MAXPATHLEN + 1];
481 char *machine = getenv("MACHINE");
482 char *machine_arch = getenv("MACHINE_ARCH");
483 char *machine_cpu = getenv("MACHINE_CPU");
484 Lst sysMkPath; /* Path of sys.mk */
485 char *cp = NULL, *start;
486 /* avoid faults on read-only strings */
487 static char syspath[] = _PATH_DEFSYSPATH;
488
489#ifdef RLIMIT_NOFILE
490 /*
491 * get rid of resource limit on file descriptors
492 */
493 {
494 struct rlimit rl;
495 if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
496 rl.rlim_cur != rl.rlim_max) {
497 rl.rlim_cur = rl.rlim_max;
498 (void) setrlimit(RLIMIT_NOFILE, &rl);
499 }
500 }
501#endif
502 /*
503 * Find where we are and take care of PWD for the automounter...
504 * All this code is so that we know where we are when we start up
505 * on a different machine with pmake.
506 */
507 curdir = cdpath;
508 if (getcwd(curdir, MAXPATHLEN) == NULL)
509 err(2, NULL);
510
511 if (stat(curdir, &sa) == -1)
512 err(2, "%s", curdir);
513
514#ifdef WANT_ENV_PWD
515 if ((pwd = getenv("PWD")) != NULL) {
516 if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
517 sa.st_dev == sb.st_dev)
518 (void) strcpy(curdir, pwd);
519 }
520#endif
521
522#if defined(__i386__) && defined(__FreeBSD_version) && \
523 __FreeBSD_version > 300003
524 /*
525 * PC-98 kernel sets the `i386' string to the utsname.machine and
526 * it cannot be distinguished from IBM-PC by uname(3). Therefore,
527 * we check machine.ispc98 and adjust the machine variable before
528 * using usname(3) below.
529 * NOTE: machdep.ispc98 was defined on 1998/8/31. At that time,
530 * __FreeBSD_version was defined as 300003. So, this check can
531 * safely be done with any kernel with version > 300003.
532 */
533 if (!machine) {
534 int ispc98;
535 size_t len;
536
537 len = sizeof(ispc98);
538 if (!sysctlbyname("machdep.ispc98", &ispc98, &len, NULL, 0)) {
539 if (ispc98)
540 machine = "pc98";
541 }
542 }
543#endif
544
545 /*
546 * Get the name of this type of MACHINE from utsname
547 * so we can share an executable for similar machines.
548 * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
549 *
550 * Note that while MACHINE is decided at run-time,
551 * MACHINE_ARCH is always known at compile time.
552 */
553 if (!machine) {
554#ifndef MACHINE
555 struct utsname utsname;
556
557 if (uname(&utsname) == -1) {
558 perror("make: uname");
559 exit(2);
560 }
561 machine = utsname.machine;
562#else
563 machine = MACHINE;
564#endif
565 }
566
567 if (!machine_arch) {
568#ifndef MACHINE_ARCH
569 machine_arch = "unknown";
570#else
571 machine_arch = MACHINE_ARCH;
572#endif
573 }
574
575 /*
576 * Set machine_cpu to the minumum supported CPU revision based
577 * on the target architecture, if not already set.
578 */
579 if (!machine_cpu) {
580 if (!strcmp(machine_arch, "i386"))
581 machine_cpu = "i386";
582 else if (!strcmp(machine_arch, "alpha"))
583 machine_cpu = "ev4";
584 else
585 machine_cpu = "unknown";
586 }
587
588 /*
589 * The object directory location is determined using the
590 * following order of preference:
591 *
592 * 1. MAKEOBJDIRPREFIX`cwd`
593 * 2. MAKEOBJDIR
594 * 3. _PATH_OBJDIR.${MACHINE}
595 * 4. _PATH_OBJDIR
596 * 5. _PATH_OBJDIRPREFIX`cwd`
597 *
598 * If one of the first two fails, use the current directory.
599 * If the remaining three all fail, use the current directory.
600 *
601 * Once things are initted,
602 * have to add the original directory to the search path,
603 * and modify the paths for the Makefiles apropriately. The
604 * current directory is also placed as a variable for make scripts.
605 */
606 if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) {
607 if (!(path = getenv("MAKEOBJDIR"))) {
608 path = _PATH_OBJDIR;
609 pathp = _PATH_OBJDIRPREFIX;
610 (void) snprintf(mdpath, MAXPATHLEN, "%s.%s",
611 path, machine);
612 if (!(objdir = chdir_verify_path(mdpath, obpath)))
613 if (!(objdir=chdir_verify_path(path, obpath))) {
614 (void) snprintf(mdpath, MAXPATHLEN,
615 "%s%s", pathp, curdir);
616 if (!(objdir=chdir_verify_path(mdpath,
617 obpath)))
618 objdir = curdir;
619 }
620 }
621 else if (!(objdir = chdir_verify_path(path, obpath)))
622 objdir = curdir;
623 }
624 else {
625 (void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir);
626 if (!(objdir = chdir_verify_path(mdpath, obpath)))
627 objdir = curdir;
628 }
629
630#ifdef WANT_ENV_PWD
631 setenv("PWD", objdir, 1);
632#endif
633
634 create = Lst_Init(FALSE);
635 makefiles = Lst_Init(FALSE);
636 envFirstVars = Lst_Init(FALSE);
637 printVars = FALSE;
638 expandVars = TRUE;
639 variables = Lst_Init(FALSE);
640 beSilent = FALSE; /* Print commands as executed */
641 ignoreErrors = FALSE; /* Pay attention to non-zero returns */
642 noExecute = FALSE; /* Execute all commands */
643 keepgoing = FALSE; /* Stop on error */
644 allPrecious = FALSE; /* Remove targets when interrupted */
645 queryFlag = FALSE; /* This is not just a check-run */
646 noBuiltins = FALSE; /* Read the built-in rules */
647 touchFlag = FALSE; /* Actually update targets */
648 usePipes = TRUE; /* Catch child output in pipes */
649 debug = 0; /* No debug verbosity, please. */
650 jobsRunning = FALSE;
651
652 maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */
653#ifdef REMOTE
654 maxJobs = DEFMAXJOBS; /* Set default max concurrency */
655#else
656 maxJobs = maxLocal;
657#endif
658 forceJobs = FALSE; /* No -j flag */
659 compatMake = FALSE; /* No compat mode */
660
661
662 /*
663 * Initialize the parsing, directory and variable modules to prepare
664 * for the reading of inclusion paths and variable settings on the
665 * command line
666 */
667 Dir_Init(); /* Initialize directory structures so -I flags
668 * can be processed correctly */
669 Parse_Init(); /* Need to initialize the paths of #include
670 * directories */
671 Var_Init(); /* As well as the lists of variables for
672 * parsing arguments */
673 str_init();
674 if (objdir != curdir)
675 Dir_AddDir(dirSearchPath, curdir);
676 Var_Set(".CURDIR", curdir, VAR_GLOBAL);
677 Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
678
679 /*
680 * Initialize various variables.
681 * MAKE also gets this name, for compatibility
682 * .MAKEFLAGS gets set to the empty string just in case.
683 * MFLAGS also gets initialized empty, for compatibility.
684 */
685 Var_Set("MAKE", argv[0], VAR_GLOBAL);
686 Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
687 Var_Set("MFLAGS", "", VAR_GLOBAL);
688 Var_Set("MACHINE", machine, VAR_GLOBAL);
689 Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL);
690 Var_Set("MACHINE_CPU", machine_cpu, VAR_GLOBAL);
691
692 /*
693 * First snag any flags out of the MAKE environment variable.
694 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
695 * in a different format).
696 */
697#ifdef POSIX
698 Main_ParseArgLine(getenv("MAKEFLAGS"));
699#else
700 Main_ParseArgLine(getenv("MAKE"));
701#endif
702
703 MainParseArgs(argc, argv);
704
705 /*
706 * Be compatible if user did not specify -j and did not explicitly
707 * turned compatibility on
708 */
709 if (!compatMake && !forceJobs)
710 compatMake = TRUE;
711
712 /*
713 * Initialize archive, target and suffix modules in preparation for
714 * parsing the makefile(s)
715 */
716 Arch_Init();
717 Targ_Init();
718 Suff_Init();
719
720 DEFAULT = NILGNODE;
721 (void)time(&now);
722
723 /*
724 * Set up the .TARGETS variable to contain the list of targets to be
725 * created. If none specified, make the variable empty -- the parser
726 * will fill the thing in with the default or .MAIN target.
727 */
728 if (!Lst_IsEmpty(create)) {
729 LstNode ln;
730
731 for (ln = Lst_First(create); ln != NILLNODE;
732 ln = Lst_Succ(ln)) {
733 char *name = (char *)Lst_Datum(ln);
734
735 Var_Append(".TARGETS", name, VAR_GLOBAL);
736 }
737 } else
738 Var_Set(".TARGETS", "", VAR_GLOBAL);
739
740
741 /*
742 * If no user-supplied system path was given (through the -m option)
743 * add the directories from the DEFSYSPATH (more than one may be given
744 * as dir1:...:dirn) to the system include path.
745 */
746 if (Lst_IsEmpty(sysIncPath)) {
747 for (start = syspath; *start != '\0'; start = cp) {
748 for (cp = start; *cp != '\0' && *cp != ':'; cp++)
749 continue;
750 if (*cp == '\0') {
751 Dir_AddDir(sysIncPath, start);
752 } else {
753 *cp++ = '\0';
754 Dir_AddDir(sysIncPath, start);
755 }
756 }
757 }
758
759 /*
760 * Read in the built-in rules first, followed by the specified
761 * makefile, if it was (makefile != (char *) NULL), or the default
762 * Makefile and makefile, in that order, if it wasn't.
763 */
764 if (!noBuiltins) {
765 LstNode ln;
766
767 sysMkPath = Lst_Init (FALSE);
768 Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath);
769 if (Lst_IsEmpty(sysMkPath))
770 Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
771 ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
772 if (ln != NILLNODE)
773 Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
774 }
775
776 if (!Lst_IsEmpty(makefiles)) {
777 LstNode ln;
778
779 ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile);
780 if (ln != NILLNODE)
781 Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
782 } else if (!ReadMakefile("makefile", NULL))
783 (void)ReadMakefile("Makefile", NULL);
784
785 (void)ReadMakefile(".depend", NULL);
786
787 Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
788 efree(p1);
789
790 /* Install all the flags into the MAKE envariable. */
791 if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p)
792#ifdef POSIX
793 setenv("MAKEFLAGS", p, 1);
794#else
795 setenv("MAKE", p, 1);
796#endif
797 efree(p1);
798
799 /*
800 * For compatibility, look at the directories in the VPATH variable
801 * and add them to the search path, if the variable is defined. The
802 * variable's value is in the same format as the PATH envariable, i.e.
803 * <directory>:<directory>:<directory>...
804 */
805 if (Var_Exists("VPATH", VAR_CMD)) {
806 char *vpath, *path, *cp, savec;
807 /*
808 * GCC stores string constants in read-only memory, but
809 * Var_Subst will want to write this thing, so store it
810 * in an array
811 */
812 static char VPATH[] = "${VPATH}";
813
814 vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
815 path = vpath;
816 do {
817 /* skip to end of directory */
818 for (cp = path; *cp != ':' && *cp != '\0'; cp++)
819 continue;
820 /* Save terminator character so know when to stop */
821 savec = *cp;
822 *cp = '\0';
823 /* Add directory to search path */
824 Dir_AddDir(dirSearchPath, path);
825 *cp = savec;
826 path = cp + 1;
827 } while (savec == ':');
828 (void)free((Address)vpath);
829 }
830
831 /*
832 * Now that all search paths have been read for suffixes et al, it's
833 * time to add the default search path to their lists...
834 */
835 Suff_DoPaths();
836
837 /* print the initial graph, if the user requested it */
838 if (DEBUG(GRAPH1))
839 Targ_PrintGraph(1);
840
841 /* print the values of any variables requested by the user */
842 if (printVars) {
843 LstNode ln;
844
845 for (ln = Lst_First(variables); ln != NILLNODE;
846 ln = Lst_Succ(ln)) {
847 char *value;
848 if (expandVars) {
849 p1 = malloc(strlen((char *)Lst_Datum(ln)) + 1 + 3);
850 if (!p1)
851 Punt("make: cannot allocate memory.");
852 /* This sprintf is safe, because of the malloc above */
853 (void)sprintf(p1, "${%s}", (char *)Lst_Datum(ln));
854 value = Var_Subst(NULL, p1, VAR_GLOBAL, FALSE);
855 } else {
856 value = Var_Value((char *)Lst_Datum(ln),
857 VAR_GLOBAL, &p1);
858 }
859 printf("%s\n", value ? value : "");
860 if (p1)
861 free(p1);
862 }
863 }
864
865 /*
866 * Have now read the entire graph and need to make a list of targets
867 * to create. If none was given on the command line, we consult the
868 * parsing module to find the main target(s) to create.
869 */
870 if (Lst_IsEmpty(create))
871 targs = Parse_MainName();
872 else
873 targs = Targ_FindList(create, TARG_CREATE);
874
875 if (!compatMake && !printVars) {
876 /*
877 * Initialize job module before traversing the graph, now that
878 * any .BEGIN and .END targets have been read. This is done
879 * only if the -q flag wasn't given (to prevent the .BEGIN from
880 * being executed should it exist).
881 */
882 if (!queryFlag) {
883 if (maxLocal == -1)
884 maxLocal = maxJobs;
885 Job_Init(maxJobs, maxLocal);
886 jobsRunning = TRUE;
887 }
888
889 /* Traverse the graph, checking on all the targets */
890 outOfDate = Make_Run(targs);
891 } else if (!printVars) {
892 /*
893 * Compat_Init will take care of creating all the targets as
894 * well as initializing the module.
895 */
896 Compat_Run(targs);
897 }
898
899 Lst_Destroy(targs, NOFREE);
900 Lst_Destroy(variables, NOFREE);
901 Lst_Destroy(makefiles, NOFREE);
902 Lst_Destroy(create, (void (*) __P((ClientData))) free);
903
904 /* print the graph now it's been processed if the user requested it */
905 if (DEBUG(GRAPH2))
906 Targ_PrintGraph(2);
907
908 Suff_End();
909 Targ_End();
910 Arch_End();
911 str_end();
912 Var_End();
913 Parse_End();
914 Dir_End();
915
916 if (queryFlag && outOfDate)
917 return(1);
918 else
919 return(0);
920}
921
922/*-
923 * ReadMakefile --
924 * Open and parse the given makefile.
925 *
926 * Results:
927 * TRUE if ok. FALSE if couldn't open file.
928 *
929 * Side Effects:
930 * lots
931 */
932static Boolean
933ReadMakefile(p, q)
934 ClientData p, q;
935{
936 char *fname = p; /* makefile to read */
937 extern Lst parseIncPath;
938 FILE *stream;
939 char *name, path[MAXPATHLEN + 1];
940 char *MAKEFILE;
941 int setMAKEFILE;
942
943 if (!strcmp(fname, "-")) {
944 Parse_File("(stdin)", stdin);
945 Var_Set("MAKEFILE", "", VAR_GLOBAL);
946 } else {
947 setMAKEFILE = strcmp(fname, ".depend");
948
949 /* if we've chdir'd, rebuild the path name */
950 if (curdir != objdir && *fname != '/') {
951 (void)snprintf(path, MAXPATHLEN, "%s/%s", curdir, fname);
952 if (realpath(path, path) != NULL &&
953 (stream = fopen(path, "r")) != NULL) {
954 MAKEFILE = fname;
955 fname = path;
956 goto found;
957 }
958 } else if (realpath(fname, path) != NULL) {
959 MAKEFILE = fname;
960 fname = path;
961 if ((stream = fopen(fname, "r")) != NULL)
962 goto found;
963 }
964 /* look in -I and system include directories. */
965 name = Dir_FindFile(fname, parseIncPath);
966 if (!name)
967 name = Dir_FindFile(fname, sysIncPath);
968 if (!name || !(stream = fopen(name, "r")))
969 return(FALSE);
970 MAKEFILE = fname = name;
971 /*
972 * set the MAKEFILE variable desired by System V fans -- the
973 * placement of the setting here means it gets set to the last
974 * makefile specified, as it is set by SysV make.
975 */
976found:
977 if (setMAKEFILE)
978 Var_Set("MAKEFILE", MAKEFILE, VAR_GLOBAL);
979 Parse_File(fname, stream);
980 (void)fclose(stream);
981 }
982 return(TRUE);
983}
984
985/*-
986 * Cmd_Exec --
987 * Execute the command in cmd, and return the output of that command
988 * in a string.
989 *
990 * Results:
991 * A string containing the output of the command, or the empty string
992 * If err is not NULL, it contains the reason for the command failure
993 *
994 * Side Effects:
995 * The string must be freed by the caller.
996 */
997char *
998Cmd_Exec(cmd, err)
999 char *cmd;
1000 char **err;
1001{
1002 char *args[4]; /* Args for invoking the shell */
1003 int fds[2]; /* Pipe streams */
1004 int cpid; /* Child PID */
1005 int pid; /* PID from wait() */
1006 char *res; /* result */
1007 int status; /* command exit status */
1008 Buffer buf; /* buffer to store the result */
1009 char *cp;
1010 int cc;
1011
1012
1013 *err = NULL;
1014
1015 /*
1016 * Set up arguments for shell
1017 */
1018 args[0] = "sh";
1019 args[1] = "-c";
1020 args[2] = cmd;
1021 args[3] = NULL;
1022
1023 /*
1024 * Open a pipe for fetching its output
1025 */
1026 if (pipe(fds) == -1) {
1027 *err = "Couldn't create pipe for \"%s\"";
1028 goto bad;
1029 }
1030
1031 /*
1032 * Fork
1033 */
1034 switch (cpid = vfork()) {
1035 case 0:
1036 /*
1037 * Close input side of pipe
1038 */
1039 (void) close(fds[0]);
1040
1041 /*
1042 * Duplicate the output stream to the shell's output, then
1043 * shut the extra thing down. Note we don't fetch the error
1044 * stream...why not? Why?
1045 */
1046 (void) dup2(fds[1], 1);
1047 (void) close(fds[1]);
1048
1049 (void) execv("/bin/sh", args);
1050 _exit(1);
1051 /*NOTREACHED*/
1052
1053 case -1:
1054 *err = "Couldn't exec \"%s\"";
1055 goto bad;
1056
1057 default:
1058 /*
1059 * No need for the writing half
1060 */
1061 (void) close(fds[1]);
1062
1063 buf = Buf_Init (MAKE_BSIZE);
1064
1065 do {
1066 char result[BUFSIZ];
1067 cc = read(fds[0], result, sizeof(result));
1068 if (cc > 0)
1069 Buf_AddBytes(buf, cc, (Byte *) result);
1070 }
1071 while (cc > 0 || (cc == -1 && errno == EINTR));
1072
1073 /*
1074 * Close the input side of the pipe.
1075 */
1076 (void) close(fds[0]);
1077
1078 /*
1079 * Wait for the process to exit.
1080 */
1081 while(((pid = wait(&status)) != cpid) && (pid >= 0))
1082 continue;
1083
1084 if (cc == -1)
1085 *err = "Error reading shell's output for \"%s\"";
1086
1087 res = (char *)Buf_GetAll (buf, &cc);
1088 Buf_Destroy (buf, FALSE);
1089
1090 if (status)
1091 *err = "\"%s\" returned non-zero status";
1092
1093 /*
1094 * Null-terminate the result, convert newlines to spaces and
1095 * install it in the variable.
1096 */
1097 res[cc] = '\0';
1098 cp = &res[cc] - 1;
1099
1100 if (*cp == '\n') {
1101 /*
1102 * A final newline is just stripped
1103 */
1104 *cp-- = '\0';
1105 }
1106 while (cp >= res) {
1107 if (*cp == '\n') {
1108 *cp = ' ';
1109 }
1110 cp--;
1111 }
1112 break;
1113 }
1114 return res;
1115bad:
1116 res = emalloc(1);
1117 *res = '\0';
1118 return res;
1119}
1120
1121/*-
1122 * Error --
1123 * Print an error message given its format.
1124 *
1125 * Results:
1126 * None.
1127 *
1128 * Side Effects:
1129 * The message is printed.
1130 */
1131/* VARARGS */
1132void
1133#ifdef __STDC__
1134Error(char *fmt, ...)
1135#else
1136Error(va_alist)
1137 va_dcl
1138#endif
1139{
1140 va_list ap;
1141#ifdef __STDC__
1142 va_start(ap, fmt);
1143#else
1144 char *fmt;
1145
1146 va_start(ap);
1147 fmt = va_arg(ap, char *);
1148#endif
1149 (void)vfprintf(stderr, fmt, ap);
1150 va_end(ap);
1151 (void)fprintf(stderr, "\n");
1152 (void)fflush(stderr);
1153}
1154
1155/*-
1156 * Fatal --
1157 * Produce a Fatal error message. If jobs are running, waits for them
1158 * to finish.
1159 *
1160 * Results:
1161 * None
1162 *
1163 * Side Effects:
1164 * The program exits
1165 */
1166/* VARARGS */
1167void
1168#ifdef __STDC__
1169Fatal(char *fmt, ...)
1170#else
1171Fatal(va_alist)
1172 va_dcl
1173#endif
1174{
1175 va_list ap;
1176#ifdef __STDC__
1177 va_start(ap, fmt);
1178#else
1179 char *fmt;
1180
1181 va_start(ap);
1182 fmt = va_arg(ap, char *);
1183#endif
1184 if (jobsRunning)
1185 Job_Wait();
1186
1187 (void)vfprintf(stderr, fmt, ap);
1188 va_end(ap);
1189 (void)fprintf(stderr, "\n");
1190 (void)fflush(stderr);
1191
1192 if (DEBUG(GRAPH2))
1193 Targ_PrintGraph(2);
1194 exit(2); /* Not 1 so -q can distinguish error */
1195}
1196
1197/*
1198 * Punt --
1199 * Major exception once jobs are being created. Kills all jobs, prints
1200 * a message and exits.
1201 *
1202 * Results:
1203 * None
1204 *
1205 * Side Effects:
1206 * All children are killed indiscriminately and the program Lib_Exits
1207 */
1208/* VARARGS */
1209void
1210#ifdef __STDC__
1211Punt(char *fmt, ...)
1212#else
1213Punt(va_alist)
1214 va_dcl
1215#endif
1216{
1217 va_list ap;
1218#if __STDC__
1219 va_start(ap, fmt);
1220#else
1221 char *fmt;
1222
1223 va_start(ap);
1224 fmt = va_arg(ap, char *);
1225#endif
1226
1227 (void)fprintf(stderr, "make: ");
1228 (void)vfprintf(stderr, fmt, ap);
1229 va_end(ap);
1230 (void)fprintf(stderr, "\n");
1231 (void)fflush(stderr);
1232
1233 DieHorribly();
1234}
1235
1236/*-
1237 * DieHorribly --
1238 * Exit without giving a message.
1239 *
1240 * Results:
1241 * None
1242 *
1243 * Side Effects:
1244 * A big one...
1245 */
1246void
1247DieHorribly()
1248{
1249 if (jobsRunning)
1250 Job_AbortAll();
1251 if (DEBUG(GRAPH2))
1252 Targ_PrintGraph(2);
1253 exit(2); /* Not 1, so -q can distinguish error */
1254}
1255
1256/*
1257 * Finish --
1258 * Called when aborting due to errors in child shell to signal
1259 * abnormal exit.
1260 *
1261 * Results:
1262 * None
1263 *
1264 * Side Effects:
1265 * The program exits
1266 */
1267void
1268Finish(errors)
1269 int errors; /* number of errors encountered in Make_Make */
1270{
1271 Fatal("%d error%s", errors, errors == 1 ? "" : "s");
1272}
1273
1274/*
1275 * emalloc --
1276 * malloc, but die on error.
1277 */
1278void *
1279emalloc(len)
1280 size_t len;
1281{
1282 void *p;
1283
1284 if ((p = malloc(len)) == NULL)
1285 enomem();
1286 return(p);
1287}
1288
1289/*
1290 * estrdup --
1291 * strdup, but die on error.
1292 */
1293char *
1294estrdup(str)
1295 const char *str;
1296{
1297 char *p;
1298
1299 if ((p = strdup(str)) == NULL)
1300 enomem();
1301 return(p);
1302}
1303
1304/*
1305 * erealloc --
1306 * realloc, but die on error.
1307 */
1308void *
1309erealloc(ptr, size)
1310 void *ptr;
1311 size_t size;
1312{
1313 if ((ptr = realloc(ptr, size)) == NULL)
1314 enomem();
1315 return(ptr);
1316}
1317
1318/*
1319 * enomem --
1320 * die when out of memory.
1321 */
1322void
1323enomem()
1324{
1325 err(2, NULL);
1326}
1327
1328/*
1329 * enunlink --
1330 * Remove a file carefully, avoiding directories.
1331 */
1332int
1333eunlink(file)
1334 const char *file;
1335{
1336 struct stat st;
1337
1338 if (lstat(file, &st) == -1)
1339 return -1;
1340
1341 if (S_ISDIR(st.st_mode)) {
1342 errno = EISDIR;
1343 return -1;
1344 }
1345 return unlink(file);
1346}
1347
1348/*
1349 * usage --
1350 * exit with usage message
1351 */
1352static void
1353usage()
1354{
1355 (void)fprintf(stderr, "%s\n%s\n%s\n",
1356"usage: make [-Beiknqrstv] [-D variable] [-d flags] [-E variable] [-f makefile]",
1357" [-I directory] [-j max_jobs] [-m directory] [-V variable]",
1358" [variable=value] [target ...]");
1359 exit(2);
1360}
1361
1362
1363int
1364PrintAddr(a, b)
1365 ClientData a;
1366 ClientData b;
1367{
1368 printf("%lx ", (unsigned long) a);
1369 return b ? 0 : 0;
1370}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette