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