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 | * | |
87198c0c | 10 | * %sccs.include.redist.c% |
9320ab9e KB |
11 | */ |
12 | ||
13 | #ifndef lint | |
87198c0c | 14 | static char sccsid[] = "@(#)make.c 5.3 (Berkeley) %G%"; |
9320ab9e KB |
15 | #endif /* not lint */ |
16 | ||
ab950546 KB |
17 | /*- |
18 | * make.c -- | |
19 | * The functions which perform the examination of targets and | |
20 | * their suitability for creation | |
21 | * | |
ab950546 KB |
22 | * Interface: |
23 | * Make_Run Initialize things for the module and recreate | |
24 | * whatever needs recreating. Returns TRUE if | |
25 | * work was (or would have been) done and FALSE | |
26 | * otherwise. | |
27 | * | |
28 | * Make_Update Update all parents of a given child. Performs | |
29 | * various bookkeeping chores like the updating | |
30 | * of the cmtime field of the parent, filling | |
31 | * of the IMPSRC context variable, etc. It will | |
32 | * place the parent on the toBeMade queue if it | |
33 | * should be. | |
34 | * | |
35 | * Make_TimeStamp Function to set the parent's cmtime field | |
36 | * based on a child's modification time. | |
37 | * | |
38 | * Make_DoAllVar Set up the various local variables for a | |
39 | * target, including the .ALLSRC variable, making | |
40 | * sure that any variable that needs to exist | |
41 | * at the very least has the empty value. | |
42 | * | |
43 | * Make_OODate Determine if a target is out-of-date. | |
44 | * | |
45 | * Make_HandleUse See if a child is a .USE node for a parent | |
46 | * and perform the .USE actions if so. | |
47 | */ | |
ab950546 KB |
48 | |
49 | #include "make.h" | |
50 | ||
51 | static Lst toBeMade; /* The current fringe of the graph. These | |
52 | * are nodes which await examination by | |
53 | * MakeOODate. It is added to by | |
54 | * Make_Update and subtracted from by | |
55 | * MakeStartJobs */ | |
56 | static int numNodes; /* Number of nodes to be processed. If this | |
57 | * is non-zero when Job_Empty() returns | |
58 | * TRUE, there's a cycle in the graph */ | |
59 | ||
60 | /*- | |
61 | *----------------------------------------------------------------------- | |
62 | * Make_TimeStamp -- | |
63 | * Set the cmtime field of a parent node based on the mtime stamp in its | |
64 | * child. Called from MakeOODate via Lst_ForEach. | |
65 | * | |
66 | * Results: | |
67 | * Always returns 0. | |
68 | * | |
69 | * Side Effects: | |
70 | * The cmtime of the parent node will be changed if the mtime | |
71 | * field of the child is greater than it. | |
72 | *----------------------------------------------------------------------- | |
73 | */ | |
74 | int | |
75 | Make_TimeStamp (pgn, cgn) | |
76 | register GNode *pgn; /* the current parent */ | |
77 | register GNode *cgn; /* the child we've just examined */ | |
78 | { | |
79 | if (cgn->mtime > pgn->cmtime) { | |
80 | pgn->cmtime = cgn->mtime; | |
81 | } | |
82 | return (0); | |
83 | } | |
84 | \f | |
85 | /*- | |
86 | *----------------------------------------------------------------------- | |
87 | * Make_OODate -- | |
88 | * See if a given node is out of date with respect to its sources. | |
89 | * Used by Make_Run when deciding which nodes to place on the | |
90 | * toBeMade queue initially and by Make_Update to screen out USE and | |
91 | * EXEC nodes. In the latter case, however, any other sort of node | |
92 | * must be considered out-of-date since at least one of its children | |
93 | * will have been recreated. | |
94 | * | |
95 | * Results: | |
96 | * TRUE if the node is out of date. FALSE otherwise. | |
97 | * | |
98 | * Side Effects: | |
99 | * The mtime field of the node and the cmtime field of its parents | |
100 | * will/may be changed. | |
101 | *----------------------------------------------------------------------- | |
102 | */ | |
103 | Boolean | |
104 | Make_OODate (gn) | |
105 | register GNode *gn; /* the node to check */ | |
106 | { | |
107 | Boolean oodate; | |
108 | ||
109 | /* | |
110 | * Certain types of targets needn't even be sought as their datedness | |
111 | * doesn't depend on their modification time... | |
112 | */ | |
113 | if ((gn->type & (OP_JOIN|OP_USE|OP_EXEC)) == 0) { | |
114 | (void) Dir_MTime (gn); | |
115 | if (DEBUG(MAKE)) { | |
116 | if (gn->mtime != 0) { | |
117 | printf ("modified %s...", Targ_FmtTime(gn->mtime)); | |
118 | } else { | |
119 | printf ("non-existent..."); | |
120 | } | |
121 | } | |
122 | } | |
123 | ||
124 | /* | |
125 | * A target is remade in one of the following circumstances: | |
126 | * its modification time is smaller than that of its youngest child | |
127 | * and it would actually be run (has commands or type OP_NOP) | |
128 | * it's the object of a force operator | |
129 | * it has no children, was on the lhs of an operator and doesn't exist | |
130 | * already. | |
131 | * | |
132 | * Libraries are only considered out-of-date if the archive module says | |
133 | * they are. | |
134 | * | |
135 | * These weird rules are brought to you by Backward-Compatability and | |
136 | * the strange people who wrote 'Make'. | |
137 | */ | |
138 | if (gn->type & OP_USE) { | |
139 | /* | |
140 | * If the node is a USE node it is *never* out of date | |
141 | * no matter *what*. | |
142 | */ | |
143 | if (DEBUG(MAKE)) { | |
144 | printf(".USE node..."); | |
145 | } | |
146 | oodate = FALSE; | |
147 | } else if (gn->type & OP_LIB) { | |
148 | if (DEBUG(MAKE)) { | |
149 | printf("library..."); | |
150 | } | |
151 | oodate = Arch_LibOODate (gn); | |
152 | } else if (gn->type & OP_JOIN) { | |
153 | /* | |
154 | * A target with the .JOIN attribute is only considered | |
155 | * out-of-date if any of its children was out-of-date. | |
156 | */ | |
157 | if (DEBUG(MAKE)) { | |
158 | printf(".JOIN node..."); | |
159 | } | |
160 | oodate = gn->childMade; | |
161 | } else if (gn->type & (OP_FORCE|OP_EXEC)) { | |
162 | /* | |
163 | * A node which is the object of the force (!) operator or which has | |
164 | * the .EXEC attribute is always considered out-of-date. | |
165 | */ | |
166 | if (DEBUG(MAKE)) { | |
167 | if (gn->type & OP_FORCE) { | |
168 | printf("! operator..."); | |
169 | } else { | |
170 | printf(".EXEC node..."); | |
171 | } | |
172 | } | |
173 | oodate = TRUE; | |
174 | } else if ((gn->mtime < gn->cmtime) || | |
175 | ((gn->cmtime == 0) && | |
176 | ((gn->mtime==0) || (gn->type & OP_DOUBLEDEP)))) | |
177 | { | |
178 | /* | |
179 | * A node whose modification time is less than that of its | |
180 | * youngest child or that has no children (cmtime == 0) and | |
181 | * either doesn't exist (mtime == 0) or was the object of a | |
182 | * :: operator is out-of-date. Why? Because that's the way Make does | |
183 | * it. | |
184 | */ | |
185 | if (DEBUG(MAKE)) { | |
186 | if (gn->mtime < gn->cmtime) { | |
187 | printf("modified before source..."); | |
188 | } else if (gn->mtime == 0) { | |
189 | printf("non-existent and no sources..."); | |
190 | } else { | |
191 | printf(":: operator and no sources..."); | |
192 | } | |
193 | } | |
194 | oodate = TRUE; | |
195 | } else { | |
196 | #if 0 | |
197 | /* WHY? */ | |
198 | if (DEBUG(MAKE)) { | |
199 | printf("source %smade...", gn->childMade ? "" : "not "); | |
200 | } | |
201 | oodate = gn->childMade; | |
202 | #else | |
203 | oodate = FALSE; | |
204 | #endif /* 0 */ | |
205 | } | |
206 | ||
207 | /* | |
208 | * If the target isn't out-of-date, the parents need to know its | |
209 | * modification time. Note that targets that appear to be out-of-date | |
210 | * but aren't, because they have no commands and aren't of type OP_NOP, | |
211 | * have their mtime stay below their children's mtime to keep parents from | |
212 | * thinking they're out-of-date. | |
213 | */ | |
214 | if (!oodate) { | |
215 | Lst_ForEach (gn->parents, Make_TimeStamp, (ClientData)gn); | |
216 | } | |
217 | ||
218 | return (oodate); | |
219 | } | |
220 | \f | |
221 | /*- | |
222 | *----------------------------------------------------------------------- | |
223 | * MakeAddChild -- | |
224 | * Function used by Make_Run to add a child to the list l. | |
225 | * It will only add the child if its make field is FALSE. | |
226 | * | |
227 | * Results: | |
228 | * Always returns 0 | |
229 | * | |
230 | * Side Effects: | |
231 | * The given list is extended | |
232 | *----------------------------------------------------------------------- | |
233 | */ | |
234 | static int | |
235 | MakeAddChild (gn, l) | |
236 | GNode *gn; /* the node to add */ | |
237 | Lst l; /* the list to which to add it */ | |
238 | { | |
239 | if (!gn->make && !(gn->type & OP_USE)) { | |
240 | (void)Lst_EnQueue (l, (ClientData)gn); | |
241 | } | |
242 | return (0); | |
243 | } | |
244 | ||
245 | /*- | |
246 | *----------------------------------------------------------------------- | |
247 | * Make_HandleUse -- | |
248 | * Function called by Make_Run and SuffApplyTransform on the downward | |
249 | * pass to handle .USE and transformation nodes. A callback function | |
250 | * for Lst_ForEach, it implements the .USE and transformation | |
251 | * functionality by copying the node's commands, type flags | |
252 | * and children to the parent node. Should be called before the | |
253 | * children are enqueued to be looked at by MakeAddChild. | |
254 | * | |
255 | * A .USE node is much like an explicit transformation rule, except | |
256 | * its commands are always added to the target node, even if the | |
257 | * target already has commands. | |
258 | * | |
259 | * Results: | |
260 | * returns 0. | |
261 | * | |
262 | * Side Effects: | |
263 | * Children and commands may be added to the parent and the parent's | |
264 | * type may be changed. | |
265 | * | |
266 | *----------------------------------------------------------------------- | |
267 | */ | |
268 | int | |
269 | Make_HandleUse (cgn, pgn) | |
270 | register GNode *cgn; /* The .USE node */ | |
271 | register GNode *pgn; /* The target of the .USE node */ | |
272 | { | |
273 | register GNode *gn; /* A child of the .USE node */ | |
274 | register LstNode ln; /* An element in the children list */ | |
275 | ||
276 | if (cgn->type & (OP_USE|OP_TRANSFORM)) { | |
277 | if ((cgn->type & OP_USE) || Lst_IsEmpty(pgn->commands)) { | |
278 | /* | |
279 | * .USE or transformation and target has no commands -- append | |
280 | * the child's commands to the parent. | |
281 | */ | |
282 | (void) Lst_Concat (pgn->commands, cgn->commands, LST_CONCNEW); | |
283 | } | |
284 | ||
285 | if (Lst_Open (cgn->children) == SUCCESS) { | |
286 | while ((ln = Lst_Next (cgn->children)) != NILLNODE) { | |
287 | gn = (GNode *)Lst_Datum (ln); | |
288 | ||
289 | if (Lst_Member (pgn->children, gn) == NILLNODE) { | |
290 | (void) Lst_AtEnd (pgn->children, gn); | |
291 | (void) Lst_AtEnd (gn->parents, pgn); | |
292 | pgn->unmade += 1; | |
293 | } | |
294 | } | |
295 | Lst_Close (cgn->children); | |
296 | } | |
297 | ||
298 | pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_TRANSFORM); | |
299 | ||
300 | /* | |
301 | * This child node is now "made", so we decrement the count of | |
302 | * unmade children in the parent... We also remove the child | |
303 | * from the parent's list to accurately reflect the number of decent | |
304 | * children the parent has. This is used by Make_Run to decide | |
305 | * whether to queue the parent or examine its children... | |
306 | */ | |
307 | if (cgn->type & OP_USE) { | |
308 | pgn->unmade -= 1; | |
309 | } | |
310 | } | |
311 | return (0); | |
312 | } | |
313 | \f | |
314 | /*- | |
315 | *----------------------------------------------------------------------- | |
316 | * Make_Update -- | |
317 | * Perform update on the parents of a node. Used by JobFinish once | |
318 | * a node has been dealt with and by MakeStartJobs if it finds an | |
319 | * up-to-date node. | |
320 | * | |
321 | * Results: | |
322 | * Always returns 0 | |
323 | * | |
324 | * Side Effects: | |
325 | * The unmade field of pgn is decremented and pgn may be placed on | |
326 | * the toBeMade queue if this field becomes 0. | |
327 | * | |
328 | * If the child was made, the parent's childMade field will be set true | |
329 | * and its cmtime set to now. | |
330 | * | |
331 | * If the child wasn't made, the cmtime field of the parent will be | |
332 | * altered if the child's mtime is big enough. | |
333 | * | |
334 | * Finally, if the child is the implied source for the parent, the | |
335 | * parent's IMPSRC variable is set appropriately. | |
336 | * | |
337 | *----------------------------------------------------------------------- | |
338 | */ | |
339 | void | |
340 | Make_Update (cgn) | |
341 | register GNode *cgn; /* the child node */ | |
342 | { | |
343 | register GNode *pgn; /* the parent node */ | |
344 | register char *cname; /* the child's name */ | |
345 | register LstNode ln; /* Element in parents and iParents lists */ | |
346 | ||
347 | cname = Var_Value (TARGET, cgn); | |
348 | ||
349 | /* | |
350 | * If the child was actually made, see what its modification time is | |
351 | * now -- some rules won't actually update the file. If the file still | |
352 | * doesn't exist, make its mtime now. | |
353 | */ | |
354 | if (cgn->made != UPTODATE) { | |
355 | #ifndef RECHECK | |
356 | /* | |
357 | * We can't re-stat the thing, but we can at least take care of rules | |
358 | * where a target depends on a source that actually creates the | |
359 | * target, but only if it has changed, e.g. | |
360 | * | |
361 | * parse.h : parse.o | |
362 | * | |
363 | * parse.o : parse.y | |
364 | * yacc -d parse.y | |
365 | * cc -c y.tab.c | |
366 | * mv y.tab.o parse.o | |
367 | * cmp -s y.tab.h parse.h || mv y.tab.h parse.h | |
368 | * | |
369 | * In this case, if the definitions produced by yacc haven't changed | |
370 | * from before, parse.h won't have been updated and cgn->mtime will | |
371 | * reflect the current modification time for parse.h. This is | |
372 | * something of a kludge, I admit, but it's a useful one.. | |
373 | * XXX: People like to use a rule like | |
374 | * | |
375 | * FRC: | |
376 | * | |
377 | * To force things that depend on FRC to be made, so we have to | |
378 | * check for gn->children being empty as well... | |
379 | */ | |
380 | if (!Lst_IsEmpty(cgn->commands) || Lst_IsEmpty(cgn->children)) { | |
381 | cgn->mtime = now; | |
382 | } | |
383 | #else | |
384 | /* | |
385 | * This is what Make does and it's actually a good thing, as it | |
386 | * allows rules like | |
387 | * | |
388 | * cmp -s y.tab.h parse.h || cp y.tab.h parse.h | |
389 | * | |
390 | * to function as intended. Unfortunately, thanks to the stateless | |
391 | * nature of NFS (by which I mean the loose coupling of two clients | |
392 | * using the same file from a common server), there are times | |
393 | * when the modification time of a file created on a remote | |
394 | * machine will not be modified before the local stat() implied by | |
395 | * the Dir_MTime occurs, thus leading us to believe that the file | |
396 | * is unchanged, wreaking havoc with files that depend on this one. | |
397 | * | |
398 | * I have decided it is better to make too much than to make too | |
399 | * little, so this stuff is commented out unless you're sure it's ok. | |
400 | * -- ardeb 1/12/88 | |
401 | */ | |
402 | if (noExecute || Dir_MTime(cgn) == 0) { | |
403 | cgn->mtime = now; | |
404 | } | |
405 | if (DEBUG(MAKE)) { | |
406 | printf("update time: %s\n", Targ_FmtTime(cgn->mtime)); | |
407 | } | |
408 | #endif | |
409 | } | |
410 | ||
411 | if (Lst_Open (cgn->parents) == SUCCESS) { | |
412 | while ((ln = Lst_Next (cgn->parents)) != NILLNODE) { | |
413 | pgn = (GNode *)Lst_Datum (ln); | |
414 | if (pgn->make) { | |
415 | pgn->unmade -= 1; | |
416 | ||
417 | if ( ! (cgn->type & (OP_EXEC|OP_USE))) { | |
418 | if (cgn->made == MADE) { | |
419 | pgn->childMade = TRUE; | |
420 | if (pgn->cmtime < cgn->mtime) { | |
421 | pgn->cmtime = cgn->mtime; | |
422 | } | |
423 | } else { | |
424 | (void)Make_TimeStamp (pgn, cgn); | |
425 | } | |
426 | } | |
427 | if (pgn->unmade == 0) { | |
428 | /* | |
429 | * Queue the node up -- any unmade predecessors will | |
430 | * be dealt with in MakeStartJobs. | |
431 | */ | |
432 | (void)Lst_EnQueue (toBeMade, (ClientData)pgn); | |
433 | } else if (pgn->unmade < 0) { | |
434 | Error ("Graph cycles through %s", pgn->name); | |
435 | } | |
436 | } | |
437 | } | |
438 | Lst_Close (cgn->parents); | |
439 | } | |
440 | /* | |
441 | * Deal with successor nodes. If any is marked for making and has an unmade | |
442 | * count of 0, has not been made and isn't in the examination queue, | |
443 | * it means we need to place it in the queue as it restrained itself | |
444 | * before. | |
445 | */ | |
446 | for (ln = Lst_First(cgn->successors); ln != NILLNODE; ln = Lst_Succ(ln)) { | |
447 | GNode *succ = (GNode *)Lst_Datum(ln); | |
448 | ||
449 | if (succ->make && succ->unmade == 0 && succ->made == UNMADE && | |
450 | Lst_Member(toBeMade, (ClientData)succ) == NILLNODE) | |
451 | { | |
452 | (void)Lst_EnQueue(toBeMade, (ClientData)succ); | |
453 | } | |
454 | } | |
455 | ||
456 | /* | |
457 | * Set the .PREFIX and .IMPSRC variables for all the implied parents | |
458 | * of this node. | |
459 | */ | |
460 | if (Lst_Open (cgn->iParents) == SUCCESS) { | |
461 | char *cpref = Var_Value(PREFIX, cgn); | |
462 | ||
463 | while ((ln = Lst_Next (cgn->iParents)) != NILLNODE) { | |
464 | pgn = (GNode *)Lst_Datum (ln); | |
465 | if (pgn->make) { | |
466 | Var_Set (IMPSRC, cname, pgn); | |
467 | Var_Set (PREFIX, cpref, pgn); | |
468 | } | |
469 | } | |
470 | Lst_Close (cgn->iParents); | |
471 | } | |
472 | } | |
473 | \f | |
474 | /*- | |
475 | *----------------------------------------------------------------------- | |
476 | * MakeAddAllSrc -- | |
477 | * Add a child's name to the ALLSRC and OODATE variables of the given | |
478 | * node. Called from Make_DoAllVar via Lst_ForEach. A child is added only | |
479 | * if it has not been given the .EXEC, .USE or .INVISIBLE attributes. | |
480 | * .EXEC and .USE children are very rarely going to be files, so... | |
481 | * A child is added to the OODATE variable if its modification time is | |
482 | * later than that of its parent, as defined by Make, except if the | |
483 | * parent is a .JOIN node. In that case, it is only added to the OODATE | |
484 | * variable if it was actually made (since .JOIN nodes don't have | |
485 | * modification times, the comparison is rather unfair...).. | |
486 | * | |
487 | * Results: | |
488 | * Always returns 0 | |
489 | * | |
490 | * Side Effects: | |
491 | * The ALLSRC variable for the given node is extended. | |
492 | *----------------------------------------------------------------------- | |
493 | */ | |
494 | static int | |
495 | MakeAddAllSrc (cgn, pgn) | |
496 | GNode *cgn; /* The child to add */ | |
497 | GNode *pgn; /* The parent to whose ALLSRC variable it should be */ | |
498 | /* added */ | |
499 | { | |
500 | if ((cgn->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) == 0) { | |
501 | register char *child; | |
502 | ||
503 | child = Var_Value(TARGET, cgn); | |
504 | Var_Append (ALLSRC, child, pgn); | |
505 | if (pgn->type & OP_JOIN) { | |
506 | if (cgn->made == MADE) { | |
507 | Var_Append(OODATE, child, pgn); | |
508 | } | |
509 | } else if ((pgn->mtime < cgn->mtime) || | |
510 | (cgn->mtime >= now && cgn->made == MADE)) | |
511 | { | |
512 | /* | |
513 | * It goes in the OODATE variable if the parent is younger than the | |
514 | * child or if the child has been modified more recently than | |
515 | * the start of the make. This is to keep pmake from getting | |
516 | * confused if something else updates the parent after the | |
517 | * make starts (shouldn't happen, I know, but sometimes it | |
518 | * does). In such a case, if we've updated the kid, the parent | |
519 | * is likely to have a modification time later than that of | |
520 | * the kid and anything that relies on the OODATE variable will | |
521 | * be hosed. | |
522 | * | |
523 | * XXX: This will cause all made children to go in the OODATE | |
524 | * variable, even if they're not touched, if RECHECK isn't defined, | |
525 | * since cgn->mtime is set to now in Make_Update. According to | |
526 | * some people, this is good... | |
527 | */ | |
528 | Var_Append(OODATE, child, pgn); | |
529 | } | |
530 | } | |
531 | return (0); | |
532 | } | |
533 | \f | |
534 | /*- | |
535 | *----------------------------------------------------------------------- | |
536 | * Make_DoAllVar -- | |
537 | * Set up the ALLSRC and OODATE variables. Sad to say, it must be | |
538 | * done separately, rather than while traversing the graph. This is | |
539 | * because Make defined OODATE to contain all sources whose modification | |
540 | * times were later than that of the target, *not* those sources that | |
541 | * were out-of-date. Since in both compatibility and native modes, | |
542 | * the modification time of the parent isn't found until the child | |
543 | * has been dealt with, we have to wait until now to fill in the | |
544 | * variable. As for ALLSRC, the ordering is important and not | |
545 | * guaranteed when in native mode, so it must be set here, too. | |
546 | * | |
547 | * Results: | |
548 | * None | |
549 | * | |
550 | * Side Effects: | |
551 | * The ALLSRC and OODATE variables of the given node is filled in. | |
552 | * If the node is a .JOIN node, its TARGET variable will be set to | |
553 | * match its ALLSRC variable. | |
554 | *----------------------------------------------------------------------- | |
555 | */ | |
556 | void | |
557 | Make_DoAllVar (gn) | |
558 | GNode *gn; | |
559 | { | |
560 | Lst_ForEach (gn->children, MakeAddAllSrc, gn); | |
561 | ||
562 | if (!Var_Exists (OODATE, gn)) { | |
563 | Var_Set (OODATE, "", gn); | |
564 | } | |
565 | if (!Var_Exists (ALLSRC, gn)) { | |
566 | Var_Set (ALLSRC, "", gn); | |
567 | } | |
568 | ||
569 | if (gn->type & OP_JOIN) { | |
570 | Var_Set (TARGET, Var_Value (ALLSRC, gn), gn); | |
571 | } | |
572 | } | |
573 | \f | |
574 | /*- | |
575 | *----------------------------------------------------------------------- | |
576 | * MakeStartJobs -- | |
577 | * Start as many jobs as possible. | |
578 | * | |
579 | * Results: | |
580 | * If the query flag was given to pmake, no job will be started, | |
581 | * but as soon as an out-of-date target is found, this function | |
582 | * returns TRUE. At all other times, this function returns FALSE. | |
583 | * | |
584 | * Side Effects: | |
585 | * Nodes are removed from the toBeMade queue and job table slots | |
586 | * are filled. | |
587 | * | |
588 | *----------------------------------------------------------------------- | |
589 | */ | |
590 | static Boolean | |
591 | MakeStartJobs () | |
592 | { | |
593 | register GNode *gn; | |
594 | ||
595 | while (!Job_Full() && !Lst_IsEmpty (toBeMade)) { | |
596 | gn = (GNode *) Lst_DeQueue (toBeMade); | |
597 | if (DEBUG(MAKE)) { | |
598 | printf ("Examining %s...", gn->name); | |
599 | } | |
600 | /* | |
601 | * Make sure any and all predecessors that are going to be made, | |
602 | * have been. | |
603 | */ | |
604 | if (!Lst_IsEmpty(gn->preds)) { | |
605 | LstNode ln; | |
606 | ||
607 | for (ln = Lst_First(gn->preds); ln != NILLNODE; ln = Lst_Succ(ln)){ | |
608 | GNode *pgn = (GNode *)Lst_Datum(ln); | |
609 | ||
610 | if (pgn->make && pgn->made == UNMADE) { | |
611 | if (DEBUG(MAKE)) { | |
612 | printf("predecessor %s not made yet.\n", pgn->name); | |
613 | } | |
614 | break; | |
615 | } | |
616 | } | |
617 | /* | |
618 | * If ln isn't nil, there's a predecessor as yet unmade, so we | |
619 | * just drop this node on the floor. When the node in question | |
620 | * has been made, it will notice this node as being ready to | |
621 | * make but as yet unmade and will place the node on the queue. | |
622 | */ | |
623 | if (ln != NILLNODE) { | |
624 | continue; | |
625 | } | |
626 | } | |
627 | ||
628 | numNodes--; | |
629 | if (Make_OODate (gn)) { | |
630 | if (DEBUG(MAKE)) { | |
631 | printf ("out-of-date\n"); | |
632 | } | |
633 | if (queryFlag) { | |
634 | return (TRUE); | |
635 | } | |
636 | Make_DoAllVar (gn); | |
637 | Job_Make (gn); | |
638 | } else { | |
639 | if (DEBUG(MAKE)) { | |
640 | printf ("up-to-date\n"); | |
641 | } | |
642 | gn->made = UPTODATE; | |
643 | if (gn->type & OP_JOIN) { | |
644 | /* | |
645 | * Even for an up-to-date .JOIN node, we need it to have its | |
646 | * context variables so references to it get the correct | |
647 | * value for .TARGET when building up the context variables | |
648 | * of its parent(s)... | |
649 | */ | |
650 | Make_DoAllVar (gn); | |
651 | } | |
652 | ||
653 | Make_Update (gn); | |
654 | } | |
655 | } | |
656 | return (FALSE); | |
657 | } | |
658 | \f | |
659 | /*- | |
660 | *----------------------------------------------------------------------- | |
661 | * MakePrintStatus -- | |
662 | * Print the status of a top-level node, viz. it being up-to-date | |
663 | * already or not created due to an error in a lower level. | |
664 | * Callback function for Make_Run via Lst_ForEach. | |
665 | * | |
666 | * Results: | |
667 | * Always returns 0. | |
668 | * | |
669 | * Side Effects: | |
670 | * A message may be printed. | |
671 | * | |
672 | *----------------------------------------------------------------------- | |
673 | */ | |
674 | static int | |
675 | MakePrintStatus(gn, cycle) | |
676 | GNode *gn; /* Node to examine */ | |
677 | Boolean cycle; /* True if gn->unmade being non-zero implies | |
678 | * a cycle in the graph, not an error in an | |
679 | * inferior */ | |
680 | { | |
681 | if (gn->made == UPTODATE) { | |
682 | printf ("`%s' is up to date.\n", gn->name); | |
683 | } else if (gn->unmade != 0) { | |
684 | if (cycle) { | |
685 | /* | |
686 | * If printing cycles and came to one that has unmade children, | |
687 | * print out the cycle by recursing on its children. Note a | |
688 | * cycle like: | |
689 | * a : b | |
690 | * b : c | |
691 | * c : b | |
692 | * will cause this to erroneously complain about a being in | |
693 | * the cycle, but this is a good approximation. | |
694 | */ | |
695 | if (gn->made == CYCLE) { | |
696 | Error("Graph cycles through `%s'", gn->name); | |
697 | gn->made = ENDCYCLE; | |
698 | Lst_ForEach(gn->children, MakePrintStatus, (ClientData)TRUE); | |
699 | gn->made = UNMADE; | |
700 | } else if (gn->made != ENDCYCLE) { | |
701 | gn->made = CYCLE; | |
702 | Lst_ForEach(gn->children, MakePrintStatus, (ClientData)TRUE); | |
703 | } | |
704 | } else { | |
705 | printf ("`%s' not remade because of errors.\n", gn->name); | |
706 | } | |
707 | } | |
708 | return (0); | |
709 | } | |
710 | \f | |
711 | /*- | |
712 | *----------------------------------------------------------------------- | |
713 | * Make_Run -- | |
714 | * Initialize the nodes to remake and the list of nodes which are | |
715 | * ready to be made by doing a breadth-first traversal of the graph | |
716 | * starting from the nodes in the given list. Once this traversal | |
717 | * is finished, all the 'leaves' of the graph are in the toBeMade | |
718 | * queue. | |
719 | * Using this queue and the Job module, work back up the graph, | |
720 | * calling on MakeStartJobs to keep the job table as full as | |
721 | * possible. | |
722 | * | |
723 | * Results: | |
724 | * TRUE if work was done. FALSE otherwise. | |
725 | * | |
726 | * Side Effects: | |
727 | * The make field of all nodes involved in the creation of the given | |
728 | * targets is set to 1. The toBeMade list is set to contain all the | |
729 | * 'leaves' of these subgraphs. | |
730 | *----------------------------------------------------------------------- | |
731 | */ | |
732 | Boolean | |
733 | Make_Run (targs) | |
734 | Lst targs; /* the initial list of targets */ | |
735 | { | |
736 | register GNode *gn; /* a temporary pointer */ | |
737 | register Lst examine; /* List of targets to examine */ | |
738 | int errors; /* Number of errors the Job module reports */ | |
739 | ||
740 | toBeMade = Lst_Init (FALSE); | |
741 | ||
742 | examine = Lst_Duplicate(targs, NOCOPY); | |
743 | numNodes = 0; | |
744 | ||
745 | /* | |
746 | * Make an initial downward pass over the graph, marking nodes to be made | |
747 | * as we go down. We call Suff_FindDeps to find where a node is and | |
748 | * to get some children for it if it has none and also has no commands. | |
749 | * If the node is a leaf, we stick it on the toBeMade queue to | |
750 | * be looked at in a minute, otherwise we add its children to our queue | |
751 | * and go on about our business. | |
752 | */ | |
753 | while (!Lst_IsEmpty (examine)) { | |
754 | gn = (GNode *) Lst_DeQueue (examine); | |
755 | ||
756 | if (!gn->make) { | |
757 | gn->make = TRUE; | |
758 | numNodes++; | |
759 | ||
760 | /* | |
761 | * Apply any .USE rules before looking for implicit dependencies | |
762 | * to make sure everything has commands that should... | |
763 | */ | |
764 | Lst_ForEach (gn->children, Make_HandleUse, (ClientData)gn); | |
765 | Suff_FindDeps (gn); | |
766 | ||
767 | if (gn->unmade != 0) { | |
768 | Lst_ForEach (gn->children, MakeAddChild, (ClientData)examine); | |
769 | } else { | |
770 | (void)Lst_EnQueue (toBeMade, (ClientData)gn); | |
771 | } | |
772 | } | |
773 | } | |
774 | ||
775 | Lst_Destroy (examine, NOFREE); | |
776 | ||
777 | if (queryFlag) { | |
778 | /* | |
779 | * We wouldn't do any work unless we could start some jobs in the | |
780 | * next loop... (we won't actually start any, of course, this is just | |
781 | * to see if any of the targets was out of date) | |
782 | */ | |
783 | return (MakeStartJobs()); | |
784 | } else { | |
785 | /* | |
786 | * Initialization. At the moment, no jobs are running and until some | |
787 | * get started, nothing will happen since the remaining upward | |
788 | * traversal of the graph is performed by the routines in job.c upon | |
789 | * the finishing of a job. So we fill the Job table as much as we can | |
790 | * before going into our loop. | |
791 | */ | |
792 | (void) MakeStartJobs(); | |
793 | } | |
794 | ||
795 | /* | |
796 | * Main Loop: The idea here is that the ending of jobs will take | |
797 | * care of the maintenance of data structures and the waiting for output | |
798 | * will cause us to be idle most of the time while our children run as | |
799 | * much as possible. Because the job table is kept as full as possible, | |
800 | * the only time when it will be empty is when all the jobs which need | |
801 | * running have been run, so that is the end condition of this loop. | |
802 | * Note that the Job module will exit if there were any errors unless the | |
803 | * keepgoing flag was given. | |
804 | */ | |
805 | while (!Job_Empty ()) { | |
806 | Job_CatchOutput (); | |
807 | Job_CatchChildren (!usePipes); | |
808 | (void)MakeStartJobs(); | |
809 | } | |
810 | ||
811 | errors = Job_End(); | |
812 | ||
813 | /* | |
814 | * Print the final status of each target. E.g. if it wasn't made | |
815 | * because some inferior reported an error. | |
816 | */ | |
817 | Lst_ForEach(targs, MakePrintStatus, | |
818 | (ClientData)((errors == 0) && (numNodes != 0))); | |
819 | ||
820 | return (TRUE); | |
821 | } |