source: trunk/src/kmk/make.c@ 40

Last change on this file since 40 was 25, checked in by bird, 23 years ago

This commit was generated by cvs2svn to compensate for changes in r24,
which included commits to RCS files with non-trunk default branches.

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