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