source: trunk/src/kmk/main.c@ 36

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

emx is kind of working again...

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