Commit | Line | Data |
---|---|---|
9320ab9e | 1 | /* |
8db0b741 KB |
2 | * Copyright (c) 1988, 1989, 1990, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
9320ab9e KB |
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 | * | |
87198c0c | 10 | * %sccs.include.redist.c% |
9320ab9e KB |
11 | */ |
12 | ||
13 | #ifndef lint | |
8db0b741 KB |
14 | static char copyright[] = |
15 | "@(#) Copyright (c) 1988, 1989, 1990, 1993\n\ | |
16 | The Regents of the University of California. All rights reserved.\n"; | |
9320ab9e KB |
17 | #endif /* not lint */ |
18 | ||
19 | #ifndef lint | |
a6c99206 | 20 | static char sccsid[] = "@(#)main.c 8.2 (Berkeley) %G%"; |
9320ab9e KB |
21 | #endif /* not lint */ |
22 | ||
ab950546 KB |
23 | /*- |
24 | * main.c -- | |
25 | * The main file for this entire program. Exit routines etc | |
26 | * reside here. | |
27 | * | |
ab950546 | 28 | * Utility functions defined in this file: |
45250cd5 KB |
29 | * Main_ParseArgLine Takes a line of arguments, breaks them and |
30 | * treats them as if they were given when first | |
31 | * invoked. Used by the parse module to implement | |
32 | * the .MFLAGS target. | |
ab950546 | 33 | * |
45250cd5 KB |
34 | * Error Print a tagged error message. The global |
35 | * MAKE variable must have been defined. This | |
36 | * takes a format string and two optional | |
37 | * arguments for it. | |
ab950546 | 38 | * |
45250cd5 KB |
39 | * Fatal Print an error message and exit. Also takes |
40 | * a format string and two arguments. | |
ab950546 | 41 | * |
45250cd5 KB |
42 | * Punt Aborts all jobs and exits with a message. Also |
43 | * takes a format string and two arguments. | |
ab950546 | 44 | * |
45250cd5 KB |
45 | * Finish Finish things up by printing the number of |
46 | * errors which occured, as passed to it, and | |
47 | * exiting. | |
ab950546 | 48 | */ |
ab950546 | 49 | |
40a80f0c KB |
50 | #include <sys/types.h> |
51 | #include <sys/time.h> | |
83b53e32 | 52 | #include <sys/param.h> |
40a80f0c | 53 | #include <sys/resource.h> |
45250cd5 KB |
54 | #include <sys/signal.h> |
55 | #include <sys/stat.h> | |
98eb476c | 56 | #include <errno.h> |
45250cd5 | 57 | #include <fcntl.h> |
45250cd5 | 58 | #include <stdio.h> |
40a80f0c KB |
59 | #if __STDC__ |
60 | #include <stdarg.h> | |
61 | #else | |
b6cda174 | 62 | #include <varargs.h> |
40a80f0c | 63 | #endif |
45250cd5 | 64 | #include "make.h" |
40a80f0c KB |
65 | #include "hash.h" |
66 | #include "dir.h" | |
67 | #include "job.h" | |
05a7e5b6 | 68 | #include "pathnames.h" |
ab950546 | 69 | |
45250cd5 KB |
70 | #ifndef DEFMAXLOCAL |
71 | #define DEFMAXLOCAL DEFMAXJOBS | |
72 | #endif DEFMAXLOCAL | |
ab950546 | 73 | |
45250cd5 | 74 | #define MAKEFLAGS ".MAKEFLAGS" |
ab950546 | 75 | |
45250cd5 KB |
76 | Lst create; /* Targets to be made */ |
77 | time_t now; /* Time at start of make */ | |
78 | GNode *DEFAULT; /* .DEFAULT node */ | |
79 | Boolean allPrecious; /* .PRECIOUS given on line by itself */ | |
ab950546 | 80 | |
45250cd5 | 81 | static Boolean noBuiltins; /* -r flag */ |
6c4ac3f1 | 82 | static Lst makefiles; /* ordered list of makefiles to read */ |
45250cd5 KB |
83 | int maxJobs; /* -J argument */ |
84 | static int maxLocal; /* -L argument */ | |
40a80f0c | 85 | Boolean compatMake; /* -B argument */ |
45250cd5 | 86 | Boolean debug; /* -d flag */ |
45250cd5 KB |
87 | Boolean noExecute; /* -n flag */ |
88 | Boolean keepgoing; /* -k flag */ | |
89 | Boolean queryFlag; /* -q flag */ | |
90 | Boolean touchFlag; /* -t flag */ | |
91 | Boolean usePipes; /* !-P flag */ | |
ab950546 | 92 | Boolean ignoreErrors; /* -i flag */ |
45250cd5 | 93 | Boolean beSilent; /* -s flag */ |
45250cd5 KB |
94 | Boolean oldVars; /* variable substitution style */ |
95 | Boolean checkEnvFirst; /* -e flag */ | |
96 | static Boolean jobsRunning; /* TRUE if the jobs might be running */ | |
ab950546 | 97 | |
45250cd5 | 98 | static Boolean ReadMakefile(); |
40a80f0c | 99 | static void usage(); |
ab950546 | 100 | |
05a7e5b6 KB |
101 | static char *curdir; /* if chdir'd for an architecture */ |
102 | ||
ab950546 | 103 | /*- |
ab950546 KB |
104 | * MainParseArgs -- |
105 | * Parse a given argument vector. Called from main() and from | |
106 | * Main_ParseArgLine() when the .MAKEFLAGS target is used. | |
107 | * | |
108 | * XXX: Deal with command line overriding .MAKEFLAGS in makefile | |
109 | * | |
110 | * Results: | |
111 | * None | |
112 | * | |
113 | * Side Effects: | |
114 | * Various global and local flags will be set depending on the flags | |
115 | * given | |
ab950546 KB |
116 | */ |
117 | static void | |
45250cd5 KB |
118 | MainParseArgs(argc, argv) |
119 | int argc; | |
120 | char **argv; | |
ab950546 | 121 | { |
45250cd5 KB |
122 | extern int optind; |
123 | extern char *optarg; | |
b3c4b5a7 | 124 | int c; |
45250cd5 | 125 | |
f0fbb401 | 126 | optind = 1; /* since we're called more than once */ |
40a80f0c KB |
127 | #ifdef notyet |
128 | # define OPTFLAGS "BD:I:L:PSd:ef:ij:knqrst" | |
129 | #else | |
130 | # define OPTFLAGS "D:I:d:ef:ij:knqrst" | |
131 | #endif | |
b3c4b5a7 | 132 | rearg: while ((c = getopt(argc, argv, OPTFLAGS)) != EOF) { |
45250cd5 | 133 | switch(c) { |
45250cd5 KB |
134 | case 'D': |
135 | Var_Set(optarg, "1", VAR_GLOBAL); | |
136 | Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); | |
137 | Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); | |
138 | break; | |
139 | case 'I': | |
140 | Parse_AddIncludeDir(optarg); | |
141 | Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL); | |
142 | Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); | |
143 | break; | |
40a80f0c KB |
144 | #ifdef notyet |
145 | case 'B': | |
146 | compatMake = TRUE; | |
147 | break; | |
45250cd5 KB |
148 | case 'L': |
149 | maxLocal = atoi(optarg); | |
150 | Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL); | |
151 | Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); | |
152 | break; | |
45250cd5 KB |
153 | case 'P': |
154 | usePipes = FALSE; | |
155 | Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL); | |
156 | break; | |
157 | case 'S': | |
158 | keepgoing = FALSE; | |
159 | Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL); | |
160 | break; | |
5f618604 | 161 | #endif |
45250cd5 KB |
162 | case 'd': { |
163 | char *modules = optarg; | |
164 | ||
5f618604 | 165 | for (; *modules; ++modules) |
45250cd5 | 166 | switch (*modules) { |
5f618604 | 167 | case 'A': |
45250cd5 KB |
168 | debug = ~0; |
169 | break; | |
170 | case 'a': | |
171 | debug |= DEBUG_ARCH; | |
172 | break; | |
173 | case 'c': | |
174 | debug |= DEBUG_COND; | |
175 | break; | |
176 | case 'd': | |
177 | debug |= DEBUG_DIR; | |
178 | break; | |
40a80f0c KB |
179 | case 'f': |
180 | debug |= DEBUG_FOR; | |
181 | break; | |
5f618604 KB |
182 | case 'g': |
183 | if (modules[1] == '1') { | |
184 | debug |= DEBUG_GRAPH1; | |
185 | ++modules; | |
186 | } | |
187 | else if (modules[1] == '2') { | |
188 | debug |= DEBUG_GRAPH2; | |
189 | ++modules; | |
190 | } | |
191 | break; | |
45250cd5 KB |
192 | case 'j': |
193 | debug |= DEBUG_JOB; | |
194 | break; | |
195 | case 'm': | |
196 | debug |= DEBUG_MAKE; | |
197 | break; | |
45250cd5 KB |
198 | case 's': |
199 | debug |= DEBUG_SUFF; | |
200 | break; | |
201 | case 't': | |
202 | debug |= DEBUG_TARG; | |
203 | break; | |
204 | case 'v': | |
205 | debug |= DEBUG_VAR; | |
206 | break; | |
f01a5a44 KB |
207 | default: |
208 | (void)fprintf(stderr, | |
209 | "make: illegal argument to d option -- %c\n", | |
210 | *modules); | |
211 | usage(); | |
45250cd5 | 212 | } |
45250cd5 KB |
213 | Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL); |
214 | Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); | |
215 | break; | |
216 | } | |
217 | case 'e': | |
218 | checkEnvFirst = TRUE; | |
219 | Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL); | |
220 | break; | |
221 | case 'f': | |
222 | (void)Lst_AtEnd(makefiles, (ClientData)optarg); | |
223 | break; | |
224 | case 'i': | |
225 | ignoreErrors = TRUE; | |
226 | Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL); | |
227 | break; | |
5f618604 KB |
228 | case 'j': |
229 | maxJobs = atoi(optarg); | |
230 | Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL); | |
231 | Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); | |
232 | break; | |
45250cd5 KB |
233 | case 'k': |
234 | keepgoing = TRUE; | |
235 | Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); | |
236 | break; | |
237 | case 'n': | |
238 | noExecute = TRUE; | |
239 | Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL); | |
240 | break; | |
45250cd5 KB |
241 | case 'q': |
242 | queryFlag = TRUE; | |
243 | /* Kind of nonsensical, wot? */ | |
244 | Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL); | |
245 | break; | |
246 | case 'r': | |
247 | noBuiltins = TRUE; | |
248 | Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL); | |
249 | break; | |
250 | case 's': | |
251 | beSilent = TRUE; | |
252 | Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL); | |
253 | break; | |
254 | case 't': | |
255 | touchFlag = TRUE; | |
256 | Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL); | |
257 | break; | |
b6cda174 KB |
258 | default: |
259 | case '?': | |
260 | usage(); | |
ab950546 | 261 | } |
ab950546 | 262 | } |
45250cd5 | 263 | |
45250cd5 KB |
264 | oldVars = TRUE; |
265 | ||
266 | /* | |
267 | * See if the rest of the arguments are variable assignments and | |
268 | * perform them if so. Else take them to be targets and stuff them | |
269 | * on the end of the "create" list. | |
270 | */ | |
fbd260e1 | 271 | for (argv += optind, argc -= optind; *argv; ++argv, --argc) |
b6cda174 KB |
272 | if (Parse_IsVar(*argv)) |
273 | Parse_DoVar(*argv, VAR_CMD); | |
274 | else { | |
947ddcac | 275 | if (!*argv[0] || *argv[0] == '-' && !(*argv)[1]) |
acf0797a | 276 | Punt("illegal (null) argument."); |
fbd260e1 KB |
277 | if (**argv == '-') { |
278 | optind = 0; | |
279 | goto rearg; | |
280 | } | |
b6cda174 | 281 | (void)Lst_AtEnd(create, (ClientData)*argv); |
45250cd5 | 282 | } |
ab950546 | 283 | } |
aa5839c2 | 284 | |
ab950546 | 285 | /*- |
ab950546 KB |
286 | * Main_ParseArgLine -- |
287 | * Used by the parse module when a .MFLAGS or .MAKEFLAGS target | |
288 | * is encountered and by main() when reading the .MAKEFLAGS envariable. | |
289 | * Takes a line of arguments and breaks it into its | |
290 | * component words and passes those words and the number of them to the | |
291 | * MainParseArgs function. | |
292 | * The line should have all its leading whitespace removed. | |
293 | * | |
294 | * Results: | |
295 | * None | |
296 | * | |
297 | * Side Effects: | |
298 | * Only those that come from the various arguments. | |
ab950546 KB |
299 | */ |
300 | void | |
45250cd5 KB |
301 | Main_ParseArgLine(line) |
302 | char *line; /* Line to fracture */ | |
ab950546 | 303 | { |
45250cd5 KB |
304 | char **argv; /* Manufactured argument vector */ |
305 | int argc; /* Number of arguments in argv */ | |
ab950546 | 306 | |
45250cd5 KB |
307 | if (line == NULL) |
308 | return; | |
40a80f0c KB |
309 | for (; *line == ' '; ++line) |
310 | continue; | |
acf0797a KB |
311 | if (!*line) |
312 | return; | |
ab950546 | 313 | |
05a7e5b6 | 314 | argv = brk_string(line, &argc); |
45250cd5 | 315 | MainParseArgs(argc, argv); |
ab950546 | 316 | } |
aa5839c2 | 317 | |
ab950546 | 318 | /*- |
ab950546 KB |
319 | * main -- |
320 | * The main function, for obvious reasons. Initializes variables | |
321 | * and a few modules, then parses the arguments give it in the | |
322 | * environment and on the command line. Reads the system makefile | |
323 | * followed by either Makefile, makefile or the file given by the | |
324 | * -f argument. Sets the .MAKEFLAGS PMake variable based on all the | |
325 | * flags it has received by then uses either the Make or the Compat | |
326 | * module to create the initial list of targets. | |
327 | * | |
328 | * Results: | |
329 | * If -q was given, exits -1 if anything was out-of-date. Else it exits | |
330 | * 0. | |
331 | * | |
332 | * Side Effects: | |
333 | * The program exits when done. Targets are created. etc. etc. etc. | |
ab950546 | 334 | */ |
40a80f0c | 335 | int |
45250cd5 KB |
336 | main(argc, argv) |
337 | int argc; | |
338 | char **argv; | |
ab950546 | 339 | { |
45250cd5 | 340 | Lst targs; /* target nodes to create -- passed to Make_Init */ |
40a80f0c KB |
341 | Boolean outOfDate = TRUE; /* FALSE if all targets up to date */ |
342 | struct stat sb, sa; | |
343 | char *p, *path, *pwd, *getenv(); | |
344 | ||
345 | /* | |
346 | * Find where we are and take care of PWD for the automounter... | |
347 | */ | |
348 | curdir = emalloc((u_int)MAXPATHLEN + 1); | |
349 | if (!getwd(curdir)) { | |
350 | (void)fprintf(stderr, "make: %s.\n", curdir); | |
351 | exit(2); | |
352 | } | |
353 | ||
354 | if (stat(curdir, &sa) == -1) { | |
355 | (void)fprintf(stderr, "make: %s: %s.\n", | |
356 | curdir, strerror(errno)); | |
357 | exit(2); | |
358 | } | |
359 | ||
360 | if ((pwd = getenv("PWD")) != NULL) { | |
361 | if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino && | |
362 | sa.st_dev == sb.st_dev) | |
363 | (void) strcpy(curdir, pwd); | |
364 | } | |
365 | ||
05a7e5b6 KB |
366 | |
367 | /* | |
368 | * if the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory | |
369 | * exists, change into it and build there. Once things are | |
370 | * initted, have to add the original directory to the search path, | |
371 | * and modify the paths for the Makefiles apropriately. The | |
372 | * current directory is also placed as a variable for make scripts. | |
373 | */ | |
374 | if (!(path = getenv("MAKEOBJDIR"))) | |
375 | path = _PATH_OBJDIR; | |
40a80f0c | 376 | |
8b4899ab KB |
377 | if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode) && |
378 | lstat(path, &sb) == 0) { | |
05a7e5b6 | 379 | if (chdir(path)) { |
05a7e5b6 KB |
380 | (void)fprintf(stderr, "make: %s: %s.\n", |
381 | path, strerror(errno)); | |
382 | exit(2); | |
383 | } | |
40a80f0c KB |
384 | if (path[0] != '/') { |
385 | char cwd[MAXPATHLEN]; | |
386 | (void) sprintf(cwd, "%s/%s", curdir, path); | |
387 | setenv("PWD", cwd, 1); | |
388 | } | |
389 | else | |
390 | setenv("PWD", path, 1); | |
05a7e5b6 | 391 | } |
a6c99206 | 392 | else { |
40a80f0c | 393 | setenv("PWD", curdir, 1); |
a6c99206 KB |
394 | path = "."; |
395 | } | |
45250cd5 | 396 | |
6c4ac3f1 | 397 | create = Lst_Init(FALSE); |
45250cd5 KB |
398 | makefiles = Lst_Init(FALSE); |
399 | beSilent = FALSE; /* Print commands as executed */ | |
400 | ignoreErrors = FALSE; /* Pay attention to non-zero returns */ | |
401 | noExecute = FALSE; /* Execute all commands */ | |
402 | keepgoing = FALSE; /* Stop on error */ | |
403 | allPrecious = FALSE; /* Remove targets when interrupted */ | |
404 | queryFlag = FALSE; /* This is not just a check-run */ | |
405 | noBuiltins = FALSE; /* Read the built-in rules */ | |
406 | touchFlag = FALSE; /* Actually update targets */ | |
407 | usePipes = TRUE; /* Catch child output in pipes */ | |
408 | debug = 0; /* No debug verbosity, please. */ | |
45250cd5 KB |
409 | jobsRunning = FALSE; |
410 | ||
411 | maxJobs = DEFMAXJOBS; /* Set default max concurrency */ | |
412 | maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */ | |
40a80f0c KB |
413 | #ifdef notyet |
414 | compatMake = FALSE; /* No compat mode */ | |
415 | #else | |
416 | compatMake = TRUE; /* No compat mode */ | |
417 | #endif | |
ab950546 | 418 | |
40a80f0c | 419 | |
45250cd5 KB |
420 | /* |
421 | * Initialize the parsing, directory and variable modules to prepare | |
422 | * for the reading of inclusion paths and variable settings on the | |
423 | * command line | |
424 | */ | |
425 | Dir_Init(); /* Initialize directory structures so -I flags | |
ab950546 | 426 | * can be processed correctly */ |
45250cd5 | 427 | Parse_Init(); /* Need to initialize the paths of #include |
ab950546 | 428 | * directories */ |
45250cd5 | 429 | Var_Init(); /* As well as the lists of variables for |
ab950546 | 430 | * parsing arguments */ |
05a7e5b6 KB |
431 | if (curdir) { |
432 | Dir_AddDir(dirSearchPath, curdir); | |
433 | Var_Set(".CURDIR", curdir, VAR_GLOBAL); | |
40a80f0c KB |
434 | } |
435 | Var_Set(".OBJDIR", path, VAR_GLOBAL); | |
05a7e5b6 | 436 | |
45250cd5 KB |
437 | /* |
438 | * Initialize various variables. | |
45250cd5 KB |
439 | * MAKE also gets this name, for compatibility |
440 | * .MAKEFLAGS gets set to the empty string just in case. | |
441 | * MFLAGS also gets initialized empty, for compatibility. | |
442 | */ | |
45250cd5 KB |
443 | Var_Set("MAKE", argv[0], VAR_GLOBAL); |
444 | Var_Set(MAKEFLAGS, "", VAR_GLOBAL); | |
445 | Var_Set("MFLAGS", "", VAR_GLOBAL); | |
05a7e5b6 | 446 | Var_Set("MACHINE", MACHINE, VAR_GLOBAL); |
45250cd5 KB |
447 | |
448 | /* | |
82fe1445 | 449 | * First snag any flags out of the MAKE environment variable. |
45250cd5 KB |
450 | * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's |
451 | * in a different format). | |
452 | */ | |
ab950546 | 453 | #ifdef POSIX |
45250cd5 | 454 | Main_ParseArgLine(getenv("MAKEFLAGS")); |
ab950546 | 455 | #else |
82fe1445 | 456 | Main_ParseArgLine(getenv("MAKE")); |
ab950546 KB |
457 | #endif |
458 | ||
45250cd5 | 459 | MainParseArgs(argc, argv); |
ab950546 | 460 | |
45250cd5 KB |
461 | /* |
462 | * Initialize archive, target and suffix modules in preparation for | |
463 | * parsing the makefile(s) | |
464 | */ | |
465 | Arch_Init(); | |
466 | Targ_Init(); | |
467 | Suff_Init(); | |
ab950546 | 468 | |
45250cd5 KB |
469 | DEFAULT = NILGNODE; |
470 | (void)time(&now); | |
ab950546 | 471 | |
45250cd5 KB |
472 | /* |
473 | * Set up the .TARGETS variable to contain the list of targets to be | |
474 | * created. If none specified, make the variable empty -- the parser | |
475 | * will fill the thing in with the default or .MAIN target. | |
476 | */ | |
477 | if (!Lst_IsEmpty(create)) { | |
478 | LstNode ln; | |
ab950546 | 479 | |
45250cd5 KB |
480 | for (ln = Lst_First(create); ln != NILLNODE; |
481 | ln = Lst_Succ(ln)) { | |
482 | char *name = (char *)Lst_Datum(ln); | |
ab950546 | 483 | |
45250cd5 KB |
484 | Var_Append(".TARGETS", name, VAR_GLOBAL); |
485 | } | |
486 | } else | |
487 | Var_Set(".TARGETS", "", VAR_GLOBAL); | |
ab950546 | 488 | |
45250cd5 KB |
489 | /* |
490 | * Read in the built-in rules first, followed by the specified makefile, | |
491 | * if it was (makefile != (char *) NULL), or the default Makefile and | |
492 | * makefile, in that order, if it wasn't. | |
493 | */ | |
05a7e5b6 KB |
494 | if (!noBuiltins && !ReadMakefile(_PATH_DEFSYSMK)) |
495 | Fatal("make: no system rules (%s).", _PATH_DEFSYSMK); | |
45250cd5 KB |
496 | |
497 | if (!Lst_IsEmpty(makefiles)) { | |
498 | LstNode ln; | |
499 | ||
500 | ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile); | |
501 | if (ln != NILLNODE) | |
6c4ac3f1 | 502 | Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); |
b6cda174 KB |
503 | } else if (!ReadMakefile("makefile")) |
504 | (void)ReadMakefile("Makefile"); | |
ab950546 | 505 | |
aae0c546 KB |
506 | (void)ReadMakefile(".depend"); |
507 | ||
6c4ac3f1 | 508 | Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL), VAR_GLOBAL); |
ab950546 | 509 | |
82fe1445 | 510 | /* Install all the flags into the MAKE envariable. */ |
40a80f0c | 511 | if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL)) != NULL) && *p) |
ab950546 | 512 | #ifdef POSIX |
acf0797a | 513 | setenv("MAKEFLAGS", p, 1); |
ab950546 | 514 | #else |
acf0797a | 515 | setenv("MAKE", p, 1); |
ab950546 KB |
516 | #endif |
517 | ||
ab950546 | 518 | /* |
45250cd5 KB |
519 | * For compatibility, look at the directories in the VPATH variable |
520 | * and add them to the search path, if the variable is defined. The | |
521 | * variable's value is in the same format as the PATH envariable, i.e. | |
522 | * <directory>:<directory>:<directory>... | |
ab950546 | 523 | */ |
6c4ac3f1 | 524 | if (Var_Exists("VPATH", VAR_CMD)) { |
45250cd5 KB |
525 | char *vpath, *path, *cp, savec; |
526 | /* | |
527 | * GCC stores string constants in read-only memory, but | |
528 | * Var_Subst will want to write this thing, so store it | |
529 | * in an array | |
530 | */ | |
531 | static char VPATH[] = "${VPATH}"; | |
532 | ||
40a80f0c | 533 | vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE); |
45250cd5 KB |
534 | path = vpath; |
535 | do { | |
536 | /* skip to end of directory */ | |
40a80f0c KB |
537 | for (cp = path; *cp != ':' && *cp != '\0'; cp++) |
538 | continue; | |
45250cd5 KB |
539 | /* Save terminator character so know when to stop */ |
540 | savec = *cp; | |
541 | *cp = '\0'; | |
542 | /* Add directory to search path */ | |
543 | Dir_AddDir(dirSearchPath, path); | |
544 | *cp = savec; | |
545 | path = cp + 1; | |
546 | } while (savec == ':'); | |
547 | (void)free((Address)vpath); | |
ab950546 | 548 | } |
45250cd5 | 549 | |
ab950546 | 550 | /* |
45250cd5 KB |
551 | * Now that all search paths have been read for suffixes et al, it's |
552 | * time to add the default search path to their lists... | |
ab950546 | 553 | */ |
45250cd5 KB |
554 | Suff_DoPaths(); |
555 | ||
5f618604 KB |
556 | /* print the initial graph, if the user requested it */ |
557 | if (DEBUG(GRAPH1)) | |
45250cd5 KB |
558 | Targ_PrintGraph(1); |
559 | ||
ab950546 | 560 | /* |
45250cd5 KB |
561 | * Have now read the entire graph and need to make a list of targets |
562 | * to create. If none was given on the command line, we consult the | |
563 | * parsing module to find the main target(s) to create. | |
ab950546 | 564 | */ |
45250cd5 KB |
565 | if (Lst_IsEmpty(create)) |
566 | targs = Parse_MainName(); | |
567 | else | |
6c4ac3f1 | 568 | targs = Targ_FindList(create, TARG_CREATE); |
45250cd5 | 569 | |
b6cda174 KB |
570 | /* |
571 | * this was original amMake -- want to allow parallelism, so put this | |
572 | * back in, eventually. | |
573 | */ | |
40a80f0c | 574 | if (!compatMake) { |
45250cd5 KB |
575 | /* |
576 | * Initialize job module before traversing the graph, now that | |
577 | * any .BEGIN and .END targets have been read. This is done | |
578 | * only if the -q flag wasn't given (to prevent the .BEGIN from | |
579 | * being executed should it exist). | |
580 | */ | |
581 | if (!queryFlag) { | |
582 | if (maxLocal == -1) | |
583 | maxLocal = maxJobs; | |
6c4ac3f1 | 584 | Job_Init(maxJobs, maxLocal); |
45250cd5 KB |
585 | jobsRunning = TRUE; |
586 | } | |
587 | ||
588 | /* Traverse the graph, checking on all the targets */ | |
589 | outOfDate = Make_Run(targs); | |
590 | } else | |
591 | /* | |
592 | * Compat_Init will take care of creating all the targets as | |
593 | * well as initializing the module. | |
594 | */ | |
595 | Compat_Run(targs); | |
ab950546 | 596 | |
5f618604 KB |
597 | /* print the graph now it's been processed if the user requested it */ |
598 | if (DEBUG(GRAPH2)) | |
45250cd5 KB |
599 | Targ_PrintGraph(2); |
600 | ||
601 | if (queryFlag && outOfDate) | |
40a80f0c | 602 | return(1); |
45250cd5 | 603 | else |
40a80f0c | 604 | return(0); |
ab950546 | 605 | } |
aa5839c2 | 606 | |
ab950546 | 607 | /*- |
ab950546 KB |
608 | * ReadMakefile -- |
609 | * Open and parse the given makefile. | |
610 | * | |
611 | * Results: | |
612 | * TRUE if ok. FALSE if couldn't open file. | |
613 | * | |
614 | * Side Effects: | |
615 | * lots | |
ab950546 KB |
616 | */ |
617 | static Boolean | |
45250cd5 KB |
618 | ReadMakefile(fname) |
619 | char *fname; /* makefile to read */ | |
ab950546 | 620 | { |
05a7e5b6 KB |
621 | extern Lst parseIncPath, sysIncPath; |
622 | FILE *stream; | |
623 | char *name, path[MAXPATHLEN + 1]; | |
624 | ||
6c4ac3f1 | 625 | if (!strcmp(fname, "-")) { |
45250cd5 KB |
626 | Parse_File("(stdin)", stdin); |
627 | Var_Set("MAKEFILE", "", VAR_GLOBAL); | |
628 | } else { | |
40a80f0c | 629 | if ((stream = fopen(fname, "r")) != NULL) |
aae0c546 | 630 | goto found; |
05a7e5b6 KB |
631 | /* if we've chdir'd, rebuild the path name */ |
632 | if (curdir && *fname != '/') { | |
633 | (void)sprintf(path, "%s/%s", curdir, fname); | |
40a80f0c | 634 | if ((stream = fopen(path, "r")) != NULL) { |
aae0c546 KB |
635 | fname = path; |
636 | goto found; | |
637 | } | |
45250cd5 | 638 | } |
aae0c546 KB |
639 | /* look in -I and system include directories. */ |
640 | name = Dir_FindFile(fname, parseIncPath); | |
641 | if (!name) | |
642 | name = Dir_FindFile(fname, sysIncPath); | |
643 | if (!name || !(stream = fopen(name, "r"))) | |
644 | return(FALSE); | |
645 | fname = name; | |
ab950546 | 646 | /* |
05a7e5b6 KB |
647 | * set the MAKEFILE variable desired by System V fans -- the |
648 | * placement of the setting here means it gets set to the last | |
649 | * makefile specified, as it is set by SysV make. | |
ab950546 | 650 | */ |
aae0c546 | 651 | found: Var_Set("MAKEFILE", fname, VAR_GLOBAL); |
45250cd5 KB |
652 | Parse_File(fname, stream); |
653 | (void)fclose(stream); | |
ab950546 | 654 | } |
45250cd5 | 655 | return(TRUE); |
ab950546 | 656 | } |
aa5839c2 | 657 | |
ab950546 | 658 | /*- |
ab950546 | 659 | * Error -- |
b6cda174 | 660 | * Print an error message given its format. |
ab950546 KB |
661 | * |
662 | * Results: | |
663 | * None. | |
664 | * | |
665 | * Side Effects: | |
666 | * The message is printed. | |
ab950546 | 667 | */ |
b6cda174 | 668 | /* VARARGS */ |
ab950546 | 669 | void |
40a80f0c KB |
670 | #if __STDC__ |
671 | Error(const char *fmt, ...) | |
672 | #else | |
673 | Error(fmt, va_alist) | |
674 | char *fmt; | |
b6cda174 | 675 | va_dcl |
40a80f0c | 676 | #endif |
ab950546 | 677 | { |
b6cda174 | 678 | va_list ap; |
40a80f0c KB |
679 | #if __STDC__ |
680 | va_start(ap, fmt); | |
681 | #else | |
b6cda174 | 682 | va_start(ap); |
40a80f0c | 683 | #endif |
b6cda174 KB |
684 | (void)vfprintf(stderr, fmt, ap); |
685 | va_end(ap); | |
686 | (void)fprintf(stderr, "\n"); | |
45250cd5 | 687 | (void)fflush(stderr); |
ab950546 | 688 | } |
aa5839c2 | 689 | |
ab950546 | 690 | /*- |
ab950546 KB |
691 | * Fatal -- |
692 | * Produce a Fatal error message. If jobs are running, waits for them | |
693 | * to finish. | |
694 | * | |
695 | * Results: | |
696 | * None | |
697 | * | |
698 | * Side Effects: | |
699 | * The program exits | |
ab950546 | 700 | */ |
b6cda174 | 701 | /* VARARGS */ |
ab950546 | 702 | void |
40a80f0c KB |
703 | #if __STDC__ |
704 | Fatal(const char *fmt, ...) | |
705 | #else | |
706 | Fatal(fmt, va_alist) | |
707 | char *fmt; | |
b6cda174 | 708 | va_dcl |
40a80f0c | 709 | #endif |
ab950546 | 710 | { |
6c4ac3f1 | 711 | va_list ap; |
40a80f0c KB |
712 | #if __STDC__ |
713 | va_start(ap, fmt); | |
714 | #else | |
715 | va_start(ap); | |
716 | #endif | |
45250cd5 KB |
717 | if (jobsRunning) |
718 | Job_Wait(); | |
6c4ac3f1 | 719 | |
6c4ac3f1 KB |
720 | (void)vfprintf(stderr, fmt, ap); |
721 | va_end(ap); | |
722 | (void)fprintf(stderr, "\n"); | |
723 | (void)fflush(stderr); | |
ab950546 | 724 | |
5f618604 | 725 | if (DEBUG(GRAPH2)) |
45250cd5 KB |
726 | Targ_PrintGraph(2); |
727 | exit(2); /* Not 1 so -q can distinguish error */ | |
ab950546 | 728 | } |
aa5839c2 | 729 | |
ab950546 | 730 | /* |
ab950546 KB |
731 | * Punt -- |
732 | * Major exception once jobs are being created. Kills all jobs, prints | |
733 | * a message and exits. | |
734 | * | |
735 | * Results: | |
736 | * None | |
737 | * | |
738 | * Side Effects: | |
739 | * All children are killed indiscriminately and the program Lib_Exits | |
ab950546 | 740 | */ |
b6cda174 | 741 | /* VARARGS */ |
ab950546 | 742 | void |
40a80f0c KB |
743 | #if __STDC__ |
744 | Punt(const char *fmt, ...) | |
745 | #else | |
746 | Punt(fmt, va_alist) | |
747 | char *fmt; | |
b6cda174 | 748 | va_dcl |
40a80f0c | 749 | #endif |
ab950546 | 750 | { |
6c4ac3f1 | 751 | va_list ap; |
40a80f0c KB |
752 | #if __STDC__ |
753 | va_start(ap, fmt); | |
754 | #else | |
6c4ac3f1 | 755 | va_start(ap); |
40a80f0c KB |
756 | #endif |
757 | (void)fprintf(stderr, "make: "); | |
6c4ac3f1 KB |
758 | (void)vfprintf(stderr, fmt, ap); |
759 | va_end(ap); | |
760 | (void)fprintf(stderr, "\n"); | |
761 | (void)fflush(stderr); | |
762 | ||
45250cd5 | 763 | DieHorribly(); |
ab950546 | 764 | } |
aa5839c2 | 765 | |
ab950546 | 766 | /*- |
ab950546 KB |
767 | * DieHorribly -- |
768 | * Exit without giving a message. | |
769 | * | |
770 | * Results: | |
771 | * None | |
772 | * | |
773 | * Side Effects: | |
774 | * A big one... | |
ab950546 KB |
775 | */ |
776 | void | |
777 | DieHorribly() | |
778 | { | |
45250cd5 KB |
779 | if (jobsRunning) |
780 | Job_AbortAll(); | |
5f618604 | 781 | if (DEBUG(GRAPH2)) |
45250cd5 KB |
782 | Targ_PrintGraph(2); |
783 | exit(2); /* Not 1, so -q can distinguish error */ | |
ab950546 | 784 | } |
aa5839c2 | 785 | |
ab950546 | 786 | /* |
ab950546 KB |
787 | * Finish -- |
788 | * Called when aborting due to errors in child shell to signal | |
789 | * abnormal exit. | |
790 | * | |
791 | * Results: | |
792 | * None | |
793 | * | |
794 | * Side Effects: | |
795 | * The program exits | |
ab950546 KB |
796 | */ |
797 | void | |
45250cd5 KB |
798 | Finish(errors) |
799 | int errors; /* number of errors encountered in Make_Make */ | |
ab950546 | 800 | { |
45250cd5 | 801 | Fatal("%d error%s", errors, errors == 1 ? "" : "s"); |
ab950546 | 802 | } |
b6cda174 | 803 | |
05a7e5b6 KB |
804 | /* |
805 | * emalloc -- | |
806 | * malloc, but die on error. | |
807 | */ | |
808 | char * | |
809 | emalloc(len) | |
810 | u_int len; | |
811 | { | |
40a80f0c | 812 | char *p; |
05a7e5b6 KB |
813 | |
814 | if (!(p = malloc(len))) | |
815 | enomem(); | |
816 | return(p); | |
817 | } | |
818 | ||
819 | /* | |
820 | * enomem -- | |
821 | * die when out of memory. | |
822 | */ | |
40a80f0c | 823 | void |
05a7e5b6 KB |
824 | enomem() |
825 | { | |
826 | (void)fprintf(stderr, "make: %s.\n", strerror(errno)); | |
827 | exit(2); | |
828 | } | |
829 | ||
830 | /* | |
831 | * usage -- | |
832 | * exit with usage message | |
833 | */ | |
40a80f0c | 834 | static void |
b6cda174 KB |
835 | usage() |
836 | { | |
837 | (void)fprintf(stderr, | |
f01a5a44 KB |
838 | "usage: make [-eiknqrst] [-D variable] [-d flags] [-f makefile ]\n\ |
839 | [-I directory] [-j max_jobs] [variable=value]\n"); | |
b6cda174 KB |
840 | exit(2); |
841 | } |