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