Commit | Line | Data |
---|---|---|
9320ab9e KB |
1 | /* |
2 | * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. | |
3 | * Copyright (c) 1988, 1989 by Adam de Boor | |
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 are permitted | |
11 | * provided that the above copyright notice and this paragraph are | |
12 | * duplicated in all such forms and that any documentation, | |
13 | * advertising materials, and other materials related to such | |
14 | * distribution and use acknowledge that the software was developed | |
15 | * by the University of California, Berkeley. The name of the | |
16 | * University may not be used to endorse or promote products derived | |
17 | * from this software without specific prior written permission. | |
18 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
19 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
21 | */ | |
22 | ||
23 | #ifndef lint | |
24 | char copyright[] = | |
25 | "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ | |
26 | All rights reserved.\n"; | |
27 | #endif /* not lint */ | |
28 | ||
29 | #ifndef lint | |
43563d42 | 30 | static char sccsid[] = "@(#)main.c 5.7 (Berkeley) %G%"; |
9320ab9e KB |
31 | #endif /* not lint */ |
32 | ||
ab950546 KB |
33 | /*- |
34 | * main.c -- | |
35 | * The main file for this entire program. Exit routines etc | |
36 | * reside here. | |
37 | * | |
ab950546 KB |
38 | * Utility functions defined in this file: |
39 | * Main_ParseArgLine Takes a line of arguments, breaks them and | |
40 | * treats them as if they were given when first | |
41 | * invoked. Used by the parse module to implement | |
42 | * the .MFLAGS target. | |
43 | * | |
44 | * Error Print a tagged error message. The global | |
45 | * MAKE variable must have been defined. This | |
46 | * takes a format string and two optional | |
47 | * arguments for it. | |
48 | * | |
49 | * Fatal Print an error message and exit. Also takes | |
50 | * a format string and two arguments. | |
51 | * | |
52 | * Punt Aborts all jobs and exits with a message. Also | |
53 | * takes a format string and two arguments. | |
54 | * | |
55 | * Finish Finish things up by printing the number of | |
56 | * errors which occured, as passed to it, and | |
57 | * exiting. | |
58 | */ | |
ab950546 | 59 | |
ab950546 KB |
60 | #include <sys/types.h> |
61 | #include <sys/signal.h> | |
62 | #include <sys/stat.h> | |
ab950546 | 63 | #include <sys/errno.h> |
fb622282 | 64 | #include <fcntl.h> |
ab950546 | 65 | #include <ctype.h> |
fb622282 | 66 | #include <stdio.h> |
ab950546 KB |
67 | #include "make.h" |
68 | ||
69 | extern int errno; | |
70 | ||
71 | ||
72 | #ifndef DEFMAXLOCAL | |
73 | #define DEFMAXLOCAL DEFMAXJOBS | |
74 | #endif DEFMAXLOCAL | |
75 | ||
76 | #define MAKEFLAGS ".MAKEFLAGS" | |
77 | ||
78 | static char *progName; /* Our invocation name */ | |
ab950546 KB |
79 | Lst create; /* Targets to be made */ |
80 | time_t now; /* Time at start of make */ | |
81 | GNode *DEFAULT; /* .DEFAULT node */ | |
82 | Boolean allPrecious; /* .PRECIOUS given on line by itself */ | |
83 | ||
84 | static int printGraph; /* -p flag */ | |
85 | static Boolean noBuiltins; /* -r flag */ | |
ab950546 KB |
86 | static Lst makefiles; /* List of makefiles to read (in |
87 | * order) */ | |
88 | int maxJobs; /* -J argument */ | |
89 | static int maxLocal; /* -L argument */ | |
90 | Boolean debug; /* -d flag */ | |
91 | Boolean amMake; /* -M flag */ | |
92 | Boolean noWarnings; /* -W flag */ | |
93 | Boolean noExecute; /* -n flag */ | |
94 | Boolean keepgoing; /* -k flag */ | |
95 | Boolean queryFlag; /* -q flag */ | |
96 | Boolean touchFlag; /* -t flag */ | |
97 | Boolean usePipes; /* !-P flag */ | |
98 | Boolean backwards; /* -B flag */ | |
99 | Boolean ignoreErrors; /* -i flag */ | |
100 | Boolean beSilent; /* -s flag */ | |
101 | Boolean sysVmake; /* -v flag */ | |
102 | Boolean oldVars; /* -V flag */ | |
103 | Boolean checkEnvFirst; /* -e flag */ | |
104 | static Boolean XFlag=FALSE; /* -X flag given */ | |
105 | static Boolean xFlag=FALSE; /* -x flag given */ | |
106 | Boolean noExport; /* Set TRUE if shouldn't export */ | |
107 | static Boolean jobsRunning; /* TRUE if the jobs might be running */ | |
108 | ||
109 | static Boolean ReadMakefile(); | |
110 | ||
111 | /* | |
112 | * Initial value for optind when parsing args. Different getopts start it | |
113 | * differently... | |
114 | */ | |
115 | static int initOptInd; | |
116 | ||
117 | #ifdef CAN_EXPORT | |
aa5839c2 | 118 | #define OPTSTR "BCD:I:J:L:MPSVWXd:ef:iknp:qrstvxh" |
ab950546 | 119 | #else |
aa5839c2 | 120 | #define OPTSTR "BCD:I:J:L:MPSVWd:ef:iknp:qrstvh" |
ab950546 KB |
121 | #endif |
122 | ||
123 | static char *help[] = { | |
124 | "-B Be as backwards-compatible with make as possible without\n\ | |
125 | being make.", | |
126 | "-C Cancel any current indications of compatibility.", | |
127 | "-D<var> Define the variable <var> with value 1.", | |
128 | "-I<dir> Specify another directory in which to search for included\n\ | |
129 | makefiles.", | |
130 | "-J<num> Specify maximum overall concurrency.", | |
131 | "-L<num> Specify maximum local concurrency.", | |
132 | "-M Be Make as closely as possible.", | |
133 | "-P Don't use pipes to catch the output of jobs, use files.", | |
134 | "-S Turn off the -k flag (see below).", | |
135 | #ifndef POSIX | |
136 | "-V Use old-style variable substitution.", | |
137 | #endif | |
138 | "-W Don't print warning messages.", | |
139 | #ifdef CAN_EXPORT | |
140 | "-X Turn off exporting of commands.", | |
141 | #endif | |
142 | "-d<flags> Turn on debugging output.", | |
143 | "-e Give environment variables precedence over those in the\n\ | |
144 | makefile(s).", | |
145 | "-f<file> Specify a(nother) makefile to read", | |
146 | "-i Ignore errors from executed commands.", | |
147 | "-k On error, continue working on targets that do not depend on\n\ | |
148 | the one for which an error was detected.", | |
ab950546 KB |
149 | "-n Don't execute commands, just print them.", |
150 | "-p<num> Tell when to print the input graph: 1 (before processing),\n\ | |
151 | 2 (after processing), or 3 (both).", | |
152 | "-q See if anything needs to be done. Exits 1 if so.", | |
153 | "-r Do not read the system makefile for pre-defined rules.", | |
154 | "-s Don't print commands as they are executed.", | |
155 | "-t Update targets by \"touching\" them (see touch(1)).", | |
aa5839c2 | 156 | "-v Be compatible with System V make. Implies -B, -V.", |
ab950546 KB |
157 | #ifdef CAN_EXPORT |
158 | "-x Allow exportation of commands.", | |
159 | #endif | |
ab950546 KB |
160 | }; |
161 | ||
162 | ||
163 | /*- | |
164 | *---------------------------------------------------------------------- | |
165 | * MainParseArgs -- | |
166 | * Parse a given argument vector. Called from main() and from | |
167 | * Main_ParseArgLine() when the .MAKEFLAGS target is used. | |
168 | * | |
169 | * XXX: Deal with command line overriding .MAKEFLAGS in makefile | |
170 | * | |
171 | * Results: | |
172 | * None | |
173 | * | |
174 | * Side Effects: | |
175 | * Various global and local flags will be set depending on the flags | |
176 | * given | |
177 | *---------------------------------------------------------------------- | |
178 | */ | |
179 | static void | |
180 | MainParseArgs (argc, argv) | |
181 | int argc; /* Number of arguments in argv */ | |
182 | char **argv; /* The arguments themselves */ | |
183 | { | |
184 | register int i; | |
185 | register char *cp; | |
186 | extern int optind; | |
187 | extern char *optarg; | |
188 | char c; | |
189 | ||
190 | optind = initOptInd; | |
191 | ||
192 | while((c = getopt(argc, argv, OPTSTR)) != -1) { | |
193 | switch(c) { | |
194 | case 'B': | |
195 | backwards = oldVars = TRUE; | |
196 | Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL); | |
197 | break; | |
198 | case 'C': | |
199 | oldVars = backwards = sysVmake = amMake = FALSE; | |
200 | Var_Append(MAKEFLAGS, "-C", VAR_GLOBAL); | |
201 | break; | |
202 | case 'D': | |
203 | Var_Set(optarg, "1", VAR_GLOBAL); | |
204 | Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); | |
205 | Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); | |
206 | break; | |
207 | case 'I': | |
208 | Parse_AddIncludeDir(optarg); | |
209 | Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL); | |
210 | Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); | |
211 | break; | |
212 | case 'J': | |
213 | maxJobs = atoi(optarg); | |
214 | Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL); | |
215 | Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); | |
216 | break; | |
217 | case 'L': | |
218 | maxLocal = atoi(optarg); | |
219 | Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL); | |
220 | Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); | |
221 | break; | |
222 | case 'M': | |
223 | amMake = TRUE; | |
224 | Var_Append(MAKEFLAGS, "-M", VAR_GLOBAL); | |
225 | break; | |
226 | case 'P': | |
227 | usePipes = FALSE; | |
228 | Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL); | |
229 | break; | |
230 | case 'S': | |
231 | keepgoing = FALSE; | |
232 | Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL); | |
233 | break; | |
234 | case 'V': | |
235 | oldVars = TRUE; | |
236 | Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL); | |
237 | break; | |
238 | case 'W': | |
239 | noWarnings = TRUE; | |
240 | Var_Append(MAKEFLAGS, "-W", VAR_GLOBAL); | |
241 | break; | |
242 | case 'X': | |
243 | XFlag = TRUE; | |
244 | Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL); | |
245 | break; | |
246 | case 'd': | |
247 | { | |
248 | char *modules = optarg; | |
249 | ||
250 | while (*modules) { | |
251 | switch (*modules) { | |
252 | case 's': | |
253 | debug |= DEBUG_SUFF; | |
254 | break; | |
255 | case 'm': | |
256 | debug |= DEBUG_MAKE; | |
257 | break; | |
258 | case 'j': | |
259 | debug |= DEBUG_JOB; | |
260 | break; | |
261 | case 't': | |
262 | debug |= DEBUG_TARG; | |
263 | break; | |
264 | case 'd': | |
265 | debug |= DEBUG_DIR; | |
266 | break; | |
267 | case 'v': | |
268 | debug |= DEBUG_VAR; | |
269 | break; | |
270 | case 'c': | |
271 | debug |= DEBUG_COND; | |
272 | break; | |
273 | case 'p': | |
274 | debug |= DEBUG_PARSE; | |
275 | break; | |
276 | case 'r': | |
277 | debug |= DEBUG_RMT; | |
278 | break; | |
279 | case 'a': | |
280 | debug |= DEBUG_ARCH; | |
281 | break; | |
282 | case '*': | |
283 | debug = ~0; | |
284 | break; | |
285 | } | |
286 | modules++; | |
287 | } | |
288 | Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL); | |
289 | Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); | |
290 | break; | |
291 | } | |
292 | case 'e': | |
293 | checkEnvFirst = TRUE; | |
294 | Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL); | |
295 | break; | |
296 | case 'f': | |
297 | (void)Lst_AtEnd(makefiles, (ClientData)optarg); | |
298 | break; | |
299 | case 'i': | |
300 | ignoreErrors = TRUE; | |
301 | Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL); | |
302 | break; | |
303 | case 'k': | |
304 | keepgoing = TRUE; | |
305 | Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); | |
306 | break; | |
ab950546 KB |
307 | case 'n': |
308 | noExecute = TRUE; | |
309 | Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL); | |
310 | break; | |
311 | case 'p': | |
312 | printGraph = atoi(optarg); | |
313 | break; | |
314 | case 'q': | |
315 | queryFlag = TRUE; | |
316 | Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL); /* Kind of | |
317 | * nonsensical, wot? | |
318 | */ | |
319 | break; | |
320 | case 'r': | |
321 | noBuiltins = TRUE; | |
322 | Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL); | |
323 | break; | |
324 | case 's': | |
325 | beSilent = TRUE; | |
326 | Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL); | |
327 | break; | |
328 | case 't': | |
329 | touchFlag = TRUE; | |
330 | Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL); | |
331 | break; | |
332 | case 'v': | |
aa5839c2 | 333 | sysVmake = oldVars = backwards = TRUE; |
ab950546 KB |
334 | Var_Append(MAKEFLAGS, "-v", VAR_GLOBAL); |
335 | break; | |
336 | case 'h': | |
337 | case '?': | |
338 | { | |
339 | int i; | |
340 | ||
341 | for (i = 0; i < sizeof(help)/sizeof(help[0]); i++) { | |
342 | printf("%s\n", help[i]); | |
343 | } | |
344 | exit(c == '?' ? -1 : 0); | |
345 | } | |
346 | } | |
347 | } | |
348 | ||
349 | /* | |
350 | * Take care of encompassing compatibility levels... | |
351 | */ | |
352 | if (amMake) { | |
353 | backwards = TRUE; | |
354 | } | |
355 | if (backwards) { | |
356 | oldVars = TRUE; | |
357 | } | |
358 | ||
359 | /* | |
360 | * See if the rest of the arguments are variable assignments and perform | |
361 | * them if so. Else take them to be targets and stuff them on the end | |
362 | * of the "create" list. | |
363 | */ | |
364 | for (i = optind; i < argc; i++) { | |
365 | if (Parse_IsVar (argv[i])) { | |
366 | Parse_DoVar(argv[i], VAR_CMD); | |
367 | } else { | |
368 | if (argv[i][0] == 0) { | |
369 | Punt("Bogus argument in MainParseArgs"); | |
370 | } | |
371 | (void)Lst_AtEnd (create, (ClientData)argv[i]); | |
372 | } | |
373 | } | |
374 | } | |
aa5839c2 | 375 | |
ab950546 KB |
376 | /*- |
377 | *---------------------------------------------------------------------- | |
378 | * Main_ParseArgLine -- | |
379 | * Used by the parse module when a .MFLAGS or .MAKEFLAGS target | |
380 | * is encountered and by main() when reading the .MAKEFLAGS envariable. | |
381 | * Takes a line of arguments and breaks it into its | |
382 | * component words and passes those words and the number of them to the | |
383 | * MainParseArgs function. | |
384 | * The line should have all its leading whitespace removed. | |
385 | * | |
386 | * Results: | |
387 | * None | |
388 | * | |
389 | * Side Effects: | |
390 | * Only those that come from the various arguments. | |
391 | *----------------------------------------------------------------------- | |
392 | */ | |
393 | void | |
394 | Main_ParseArgLine (line) | |
395 | char *line; /* Line to fracture */ | |
396 | { | |
397 | char **argv; /* Manufactured argument vector */ | |
398 | int argc; /* Number of arguments in argv */ | |
399 | ||
400 | if (line == NULL) return; | |
401 | while (*line == ' ') line++; | |
402 | ||
403 | argv = Str_BreakString (line, " \t", "\n", &argc); | |
404 | ||
405 | MainParseArgs(argc, argv); | |
406 | ||
407 | Str_FreeVec(argc, argv); | |
408 | } | |
aa5839c2 | 409 | |
ab950546 KB |
410 | /*- |
411 | *---------------------------------------------------------------------- | |
412 | * main -- | |
413 | * The main function, for obvious reasons. Initializes variables | |
414 | * and a few modules, then parses the arguments give it in the | |
415 | * environment and on the command line. Reads the system makefile | |
416 | * followed by either Makefile, makefile or the file given by the | |
417 | * -f argument. Sets the .MAKEFLAGS PMake variable based on all the | |
418 | * flags it has received by then uses either the Make or the Compat | |
419 | * module to create the initial list of targets. | |
420 | * | |
421 | * Results: | |
422 | * If -q was given, exits -1 if anything was out-of-date. Else it exits | |
423 | * 0. | |
424 | * | |
425 | * Side Effects: | |
426 | * The program exits when done. Targets are created. etc. etc. etc. | |
427 | * | |
428 | *---------------------------------------------------------------------- | |
429 | */ | |
430 | main (argc, argv) | |
431 | int argc; | |
432 | char **argv; | |
433 | { | |
434 | Lst targs; /* list of target nodes to create. Passed to | |
435 | * Make_Init */ | |
436 | Boolean outOfDate; /* FALSE if all targets up to date */ | |
437 | char *cp; | |
438 | extern int optind; | |
439 | ||
440 | ||
441 | create = Lst_Init (FALSE); | |
442 | makefiles = Lst_Init(FALSE); | |
443 | ||
444 | beSilent = FALSE; /* Print commands as executed */ | |
445 | ignoreErrors = FALSE; /* Pay attention to non-zero returns */ | |
446 | noExecute = FALSE; /* Execute all commands */ | |
447 | keepgoing = FALSE; /* Stop on error */ | |
448 | allPrecious = FALSE; /* Remove targets when interrupted */ | |
449 | queryFlag = FALSE; /* This is not just a check-run */ | |
450 | noBuiltins = FALSE; /* Read the built-in rules */ | |
451 | touchFlag = FALSE; /* Actually update targets */ | |
452 | usePipes = TRUE; /* Catch child output in pipes */ | |
ab950546 KB |
453 | debug = 0; /* No debug verbosity, please. */ |
454 | noWarnings = FALSE; /* Print warning messages */ | |
455 | sysVmake = FALSE; /* Don't be System V compatible */ | |
456 | ||
457 | jobsRunning = FALSE; | |
458 | ||
459 | maxJobs = DEFMAXJOBS; /* Set the default maximum concurrency */ | |
460 | maxLocal = DEFMAXLOCAL; /* Set the default local max concurrency */ | |
461 | ||
462 | /* | |
463 | * Deal with disagreement between different getopt's as to what | |
464 | * the initial value of optind should be by simply saving the | |
465 | * damn thing. | |
466 | */ | |
467 | initOptInd = optind; | |
468 | ||
469 | /* | |
470 | * See what the user calls us. If s/he calls us (yuck) "make", then | |
471 | * act like it. Otherwise act like our normal, cheerful self. | |
472 | */ | |
473 | cp = rindex (argv[0], '/'); | |
474 | if (cp != (char *)NULL) { | |
475 | cp += 1; | |
476 | } else { | |
477 | cp = argv[0]; | |
478 | } | |
479 | progName = cp; | |
480 | ||
481 | if (strcmp (cp, "make") == 0) { | |
482 | amMake = TRUE; /* Be like make */ | |
483 | backwards = TRUE; /* Do things the old-fashioned way */ | |
484 | oldVars = TRUE; /* Same with variables */ | |
485 | } else if (strcmp(cp, "smake") == 0 || strcmp(cp, "vmake") == 0) { | |
aa5839c2 | 486 | sysVmake = oldVars = backwards = TRUE; |
ab950546 KB |
487 | } else { |
488 | amMake = FALSE; | |
489 | backwards = FALSE; /* Do things MY way, not MAKE's */ | |
ab950546 | 490 | oldVars = TRUE; |
ab950546 KB |
491 | } |
492 | ||
493 | /* | |
494 | * Initialize the parsing, directory and variable modules to prepare | |
495 | * for the reading of inclusion paths and variable settings on the | |
496 | * command line | |
497 | */ | |
498 | Dir_Init (); /* Initialize directory structures so -I flags | |
499 | * can be processed correctly */ | |
500 | Parse_Init (); /* Need to initialize the paths of #include | |
501 | * directories */ | |
502 | Var_Init (); /* As well as the lists of variables for | |
503 | * parsing arguments */ | |
504 | ||
505 | /* | |
506 | * Initialize various variables. | |
507 | * .PMAKE gets how we were executed. | |
508 | * MAKE also gets this name, for compatibility | |
509 | * .MAKEFLAGS gets set to the empty string just in case. | |
510 | * MFLAGS also gets initialized empty, for compatibility. | |
511 | */ | |
512 | Var_Set (".PMAKE", argv[0], VAR_GLOBAL); | |
513 | Var_Set ("MAKE", argv[0], VAR_GLOBAL); | |
514 | Var_Set (MAKEFLAGS, "", VAR_GLOBAL); | |
515 | Var_Set ("MFLAGS", "", VAR_GLOBAL); | |
516 | ||
517 | /* | |
518 | * First snag any flags out of the PMAKE environment variable. | |
519 | * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's in | |
520 | * a different format). | |
521 | */ | |
522 | #ifdef POSIX | |
523 | Main_ParseArgLine(getenv("MAKEFLAGS")); | |
524 | #else | |
525 | Main_ParseArgLine (getenv("PMAKE")); | |
526 | #endif | |
527 | ||
528 | MainParseArgs (argc, argv); | |
529 | ||
ab950546 KB |
530 | /* |
531 | * Initialize archive, target and suffix modules in preparation for | |
532 | * parsing the makefile(s) | |
533 | */ | |
534 | Arch_Init (); | |
535 | Targ_Init (); | |
536 | Suff_Init (); | |
537 | ||
538 | DEFAULT = NILGNODE; | |
539 | ||
540 | now = time(0); | |
541 | ||
542 | /* | |
543 | * Set up the .TARGETS variable to contain the list of targets to be | |
544 | * created. If none specified, make the variable empty -- the parser | |
545 | * will fill the thing in with the default or .MAIN target. | |
546 | */ | |
547 | if (!Lst_IsEmpty(create)) { | |
548 | LstNode ln; | |
549 | ||
550 | for (ln = Lst_First(create); ln != NILLNODE; ln = Lst_Succ(ln)) { | |
551 | char *name = (char *)Lst_Datum(ln); | |
552 | ||
553 | Var_Append(".TARGETS", name, VAR_GLOBAL); | |
554 | } | |
555 | } else { | |
556 | Var_Set(".TARGETS", "", VAR_GLOBAL); | |
557 | } | |
558 | ||
559 | /* | |
560 | * Read in the built-in rules first, followed by the specified makefile, | |
561 | * if it was (makefile != (char *) NULL), or the default Makefile and | |
562 | * makefile, in that order, if it wasn't. | |
563 | */ | |
564 | if (!noBuiltins && !ReadMakefile (DEFSYSMK)) { | |
565 | Fatal ("Could not open system rules (%s)", DEFSYSMK); | |
566 | } | |
567 | ||
568 | if (!Lst_IsEmpty(makefiles)) { | |
569 | LstNode ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile); | |
570 | ||
571 | if (ln != NILLNODE) { | |
572 | Fatal ("Cannot open %s", (char *)Lst_Datum(ln)); | |
573 | } | |
574 | } else { | |
575 | #ifdef POSIX | |
576 | if (!ReadMakefile("makefile")) { | |
577 | (void)ReadMakefile("Makefile"); | |
578 | } | |
579 | #else | |
580 | if (!ReadMakefile ((amMake || sysVmake) ? "makefile" : "Makefile")) { | |
581 | (void) ReadMakefile ((amMake||sysVmake) ? "Makefile" : "makefile"); | |
582 | } | |
583 | #endif | |
584 | } | |
585 | ||
586 | /* | |
587 | * Figure "noExport" out based on the current mode. Since exporting each | |
588 | * command in make mode is rather inefficient, we only export if the -x | |
589 | * flag was given. In regular mode though, we only refuse to export if | |
590 | * -X was given. In case the operative flag was given in the environment, | |
591 | * however, the opposite one may be given on the command line and cancel | |
592 | * the action. | |
593 | */ | |
594 | if (amMake) { | |
595 | noExport = !xFlag || XFlag; | |
596 | } else { | |
597 | noExport = XFlag && !xFlag; | |
598 | } | |
599 | ||
600 | Var_Append ("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL), VAR_GLOBAL); | |
601 | ||
602 | /* | |
603 | * Install all the flags into the PMAKE envariable. | |
604 | */ | |
605 | #ifdef POSIX | |
606 | setenv("MAKEFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL)); | |
607 | #else | |
608 | setenv("PMAKE", Var_Value(MAKEFLAGS, VAR_GLOBAL)); | |
609 | #endif | |
610 | ||
611 | /* | |
612 | * For compatibility, look at the directories in the VPATH variable | |
613 | * and add them to the search path, if the variable is defined. The | |
614 | * variable's value is in the same format as the PATH envariable, i.e. | |
615 | * <directory>:<directory>:<directory>... | |
616 | */ | |
617 | if (Var_Exists ("VPATH", VAR_CMD)) { | |
618 | char *vpath; | |
619 | char *path; | |
620 | char *cp; | |
621 | char savec; | |
622 | static char VPATH[] = "${VPATH}"; /* GCC stores string constants in | |
623 | * read-only memory, but Var_Subst | |
624 | * will want to write this thing, | |
625 | * so store it in an array */ | |
626 | ||
627 | vpath = Var_Subst (VPATH, VAR_CMD, FALSE); | |
628 | ||
629 | path = vpath; | |
630 | do { | |
631 | /* | |
632 | * Skip to end of directory | |
633 | */ | |
634 | for (cp = path; *cp != ':' && *cp != '\0'; cp++) { | |
635 | continue; | |
636 | } | |
637 | /* | |
638 | * Save terminator character to figure out when to stop | |
639 | */ | |
640 | savec = *cp; | |
641 | *cp = '\0'; | |
642 | /* | |
643 | * Add directory to search path | |
644 | */ | |
645 | Dir_AddDir (dirSearchPath, path); | |
646 | *cp = savec; | |
647 | path = cp + 1; | |
648 | } while (savec == ':'); | |
649 | free((Address)vpath); | |
650 | } | |
651 | ||
652 | /* | |
653 | * Now that all search paths have been read for suffixes et al, it's | |
654 | * time to add the default search path to their lists... | |
655 | */ | |
656 | Suff_DoPaths(); | |
657 | ||
658 | /* | |
659 | * Print the initial graph, if the user requested it | |
660 | */ | |
661 | if (printGraph & 1) { | |
662 | Targ_PrintGraph (1); | |
663 | } | |
664 | ||
665 | Rmt_Init(); | |
666 | ||
667 | /* | |
668 | * Have now read the entire graph and need to make a list of targets to | |
669 | * create. If none was given on the command line, we consult the parsing | |
670 | * module to find the main target(s) to create. | |
671 | */ | |
672 | if (Lst_IsEmpty (create)) { | |
673 | targs = Parse_MainName (); | |
674 | } else { | |
675 | targs = Targ_FindList (create, TARG_CREATE); | |
676 | } | |
677 | ||
678 | if (!amMake) { | |
679 | /* | |
680 | * Initialize job module before traversing the graph, now that any | |
681 | * .BEGIN and .END targets have been read. This is done only if the | |
682 | * -q flag wasn't given (to prevent the .BEGIN from being executed | |
683 | * should it exist). | |
684 | */ | |
685 | if (!queryFlag) { | |
686 | if (maxLocal == -1) { | |
687 | maxLocal = maxJobs; | |
688 | } | |
689 | Job_Init (maxJobs, maxLocal); | |
690 | jobsRunning = TRUE; | |
691 | } | |
692 | ||
693 | /* | |
694 | * Traverse the graph, checking on all the targets | |
695 | */ | |
696 | outOfDate = Make_Run (targs); | |
697 | } else { | |
698 | /* | |
699 | * Compat_Init will take care of creating all the targets as well | |
700 | * as initializing the module. | |
701 | */ | |
702 | Compat_Run(targs); | |
703 | } | |
704 | ||
705 | /* | |
706 | * Print the graph now it's been processed if the user requested it | |
707 | */ | |
708 | if (printGraph & 2) { | |
709 | Targ_PrintGraph (2); | |
710 | } | |
711 | ||
712 | if (queryFlag && outOfDate) { | |
713 | exit (1); | |
714 | } else { | |
715 | exit (0); | |
716 | } | |
717 | } | |
aa5839c2 | 718 | |
ab950546 KB |
719 | /*- |
720 | *----------------------------------------------------------------------- | |
721 | * ReadMakefile -- | |
722 | * Open and parse the given makefile. | |
723 | * | |
724 | * Results: | |
725 | * TRUE if ok. FALSE if couldn't open file. | |
726 | * | |
727 | * Side Effects: | |
728 | * lots | |
729 | *----------------------------------------------------------------------- | |
730 | */ | |
731 | static Boolean | |
732 | ReadMakefile (fname) | |
733 | char *fname; /* makefile to read */ | |
734 | { | |
735 | if (strcmp (fname, "-") == 0) { | |
736 | Parse_File ("(stdin)", stdin); | |
737 | Var_Set("MAKEFILE", "", VAR_GLOBAL); | |
738 | return (TRUE); | |
739 | } else { | |
740 | FILE * stream; | |
741 | extern Lst parseIncPath, sysIncPath; | |
742 | ||
743 | stream = fopen (fname, "r"); | |
744 | ||
745 | if (stream == (FILE *) NULL) { | |
746 | /* | |
747 | * Look in -I directories... | |
748 | */ | |
749 | char *name = Dir_FindFile(fname, parseIncPath); | |
750 | ||
751 | if (name == NULL) { | |
752 | /* | |
753 | * Last-ditch: look in system include directories. | |
754 | */ | |
755 | name = Dir_FindFile(fname, sysIncPath); | |
756 | if (name == NULL) { | |
757 | return (FALSE); | |
758 | } | |
759 | } | |
760 | stream = fopen(name, "r"); | |
761 | if (stream == (FILE *)NULL) { | |
762 | /* Better safe than sorry... */ | |
763 | return(FALSE); | |
764 | } | |
765 | fname = name; | |
766 | } | |
767 | /* | |
768 | * Set the MAKEFILE variable desired by System V fans -- the placement | |
769 | * of the setting here means it gets set to the last makefile | |
770 | * specified, as it is set by SysV make... | |
771 | */ | |
772 | Var_Set("MAKEFILE", fname, VAR_GLOBAL); | |
773 | Parse_File (fname, stream); | |
774 | fclose (stream); | |
775 | return (TRUE); | |
776 | } | |
777 | } | |
aa5839c2 | 778 | |
ab950546 KB |
779 | /*- |
780 | *----------------------------------------------------------------------- | |
781 | * Error -- | |
782 | * Print an error message given its format and 0, 1, 2 or 3 arguments. | |
783 | * | |
784 | * Results: | |
785 | * None. | |
786 | * | |
787 | * Side Effects: | |
788 | * The message is printed. | |
789 | * | |
790 | *----------------------------------------------------------------------- | |
791 | */ | |
792 | /*VARARGS1*/ | |
793 | void | |
794 | Error (fmt, arg1, arg2, arg3) | |
795 | char *fmt; /* Format string */ | |
796 | int arg1, /* First optional argument */ | |
797 | arg2, /* Second optional argument */ | |
798 | arg3; /* Third optional argument */ | |
799 | { | |
800 | static char estr[BSIZE]; /* output string */ | |
801 | ||
802 | sprintf (estr, "%s: ", Var_Value(".PMAKE", VAR_GLOBAL)); | |
803 | sprintf (&estr[strlen (estr)], fmt, arg1, arg2, arg3); | |
804 | (void) strcat (estr, "\n"); | |
805 | ||
806 | fputs (estr, stderr); | |
807 | fflush (stderr); | |
808 | } | |
aa5839c2 | 809 | |
ab950546 KB |
810 | /*- |
811 | *----------------------------------------------------------------------- | |
812 | * Fatal -- | |
813 | * Produce a Fatal error message. If jobs are running, waits for them | |
814 | * to finish. | |
815 | * | |
816 | * Results: | |
817 | * None | |
818 | * | |
819 | * Side Effects: | |
820 | * The program exits | |
821 | *----------------------------------------------------------------------- | |
822 | */ | |
823 | /* VARARGS1 */ | |
824 | void | |
825 | Fatal (fmt, arg1, arg2) | |
826 | char *fmt; /* format string */ | |
827 | int arg1; /* first optional argument */ | |
828 | int arg2; /* second optional argument */ | |
829 | { | |
830 | if (jobsRunning) { | |
831 | Job_Wait(); | |
832 | } | |
833 | ||
834 | Error (fmt, arg1, arg2); | |
835 | ||
836 | if (printGraph & 2) { | |
837 | Targ_PrintGraph(2); | |
838 | } | |
839 | exit (2); /* Not 1 so -q can distinguish error */ | |
840 | } | |
aa5839c2 | 841 | |
ab950546 KB |
842 | /* |
843 | *----------------------------------------------------------------------- | |
844 | * Punt -- | |
845 | * Major exception once jobs are being created. Kills all jobs, prints | |
846 | * a message and exits. | |
847 | * | |
848 | * Results: | |
849 | * None | |
850 | * | |
851 | * Side Effects: | |
852 | * All children are killed indiscriminately and the program Lib_Exits | |
853 | *----------------------------------------------------------------------- | |
854 | */ | |
855 | /* VARARGS1 */ | |
856 | void | |
857 | Punt (fmt, arg1, arg2) | |
858 | char *fmt; /* format string */ | |
859 | int arg1; /* optional argument */ | |
860 | int arg2; /* optional second argument */ | |
861 | { | |
862 | Error (fmt, arg1, arg2); | |
863 | ||
864 | DieHorribly(); | |
865 | } | |
aa5839c2 | 866 | |
ab950546 KB |
867 | /*- |
868 | *----------------------------------------------------------------------- | |
869 | * DieHorribly -- | |
870 | * Exit without giving a message. | |
871 | * | |
872 | * Results: | |
873 | * None | |
874 | * | |
875 | * Side Effects: | |
876 | * A big one... | |
877 | *----------------------------------------------------------------------- | |
878 | */ | |
879 | void | |
880 | DieHorribly() | |
881 | { | |
882 | if (jobsRunning) { | |
883 | Job_AbortAll (); | |
884 | } | |
885 | if (printGraph & 2) { | |
886 | Targ_PrintGraph(2); | |
887 | } | |
888 | ||
889 | exit (2); /* Not 1, so -q can distinguish error */ | |
890 | } | |
aa5839c2 | 891 | |
ab950546 KB |
892 | /* |
893 | *----------------------------------------------------------------------- | |
894 | * Finish -- | |
895 | * Called when aborting due to errors in child shell to signal | |
896 | * abnormal exit. | |
897 | * | |
898 | * Results: | |
899 | * None | |
900 | * | |
901 | * Side Effects: | |
902 | * The program exits | |
903 | * ----------------------------------------------------------------------- | |
904 | */ | |
905 | void | |
906 | Finish (errors) | |
907 | int errors; /* number of errors encountered in Make_Make */ | |
908 | { | |
909 | Fatal ("%d error%s", errors, errors == 1 ? "" : "s"); | |
910 | } |