1 | /* |
---|
2 | * Copyright 1993, 1995 Christopher Seiwald. |
---|
3 | * |
---|
4 | * This file is part of Jam - see jam.c for Copyright information. |
---|
5 | */ |
---|
6 | |
---|
7 | /* This file is ALSO: |
---|
8 | * Copyright 2001-2004 David Abrahams. |
---|
9 | * Distributed under the Boost Software License, Version 1.0. |
---|
10 | * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) |
---|
11 | */ |
---|
12 | |
---|
13 | /* |
---|
14 | * make.c - bring a target up to date, once rules are in place |
---|
15 | * |
---|
16 | * This modules controls the execution of rules to bring a target and |
---|
17 | * its dependencies up to date. It is invoked after the targets, rules, |
---|
18 | * et. al. described in rules.h are created by the interpreting of the |
---|
19 | * jam files. |
---|
20 | * |
---|
21 | * This file contains the main make() entry point and the first pass |
---|
22 | * make0(). The second pass, make1(), which actually does the command |
---|
23 | * execution, is in make1.c. |
---|
24 | * |
---|
25 | * External routines: |
---|
26 | * make() - make a target, given its name |
---|
27 | * |
---|
28 | * Internal routines: |
---|
29 | * make0() - bind and scan everything to make a TARGET |
---|
30 | * make0sort() - reorder TARGETS chain by their time (newest to oldest) |
---|
31 | * |
---|
32 | * 12/26/93 (seiwald) - allow NOTIME targets to be expanded via $(<), $(>) |
---|
33 | * 01/04/94 (seiwald) - print all targets, bounded, when tracing commands |
---|
34 | * 04/08/94 (seiwald) - progress report now reflects only targets with actions |
---|
35 | * 04/11/94 (seiwald) - Combined deps & headers into deps[2] in TARGET. |
---|
36 | * 12/20/94 (seiwald) - NOTIME renamed NOTFILE. |
---|
37 | * 12/20/94 (seiwald) - make0() headers after determining fate of target, so |
---|
38 | * that headers aren't seen as dependents on themselves. |
---|
39 | * 01/19/95 (seiwald) - distinguish between CANTFIND/CANTMAKE targets. |
---|
40 | * 02/02/95 (seiwald) - propagate leaf source time for new LEAVES rule. |
---|
41 | * 02/14/95 (seiwald) - NOUPDATE rule means don't update existing target. |
---|
42 | * 08/22/95 (seiwald) - NOUPDATE targets immune to anyhow (-a) flag. |
---|
43 | * 09/06/00 (seiwald) - NOCARE affects targets with sources/actions. |
---|
44 | * 03/02/01 (seiwald) - reverse NOCARE change. |
---|
45 | * 03/14/02 (seiwald) - TEMPORARY targets no longer take on parents age |
---|
46 | * 03/16/02 (seiwald) - support for -g (reorder builds by source time) |
---|
47 | */ |
---|
48 | |
---|
49 | # include "jam.h" |
---|
50 | |
---|
51 | # include "lists.h" |
---|
52 | # include "parse.h" |
---|
53 | # include "variable.h" |
---|
54 | # include "rules.h" |
---|
55 | |
---|
56 | #ifdef OPT_HEADER_CACHE_EXT |
---|
57 | # include "hcache.h" |
---|
58 | #endif |
---|
59 | |
---|
60 | # include "search.h" |
---|
61 | # include "newstr.h" |
---|
62 | # include "make.h" |
---|
63 | # include "headers.h" |
---|
64 | # include "command.h" |
---|
65 | # include <assert.h> |
---|
66 | |
---|
67 | # ifndef max |
---|
68 | # define max( a,b ) ((a)>(b)?(a):(b)) |
---|
69 | # endif |
---|
70 | |
---|
71 | static TARGETS *make0sort( TARGETS *c ); |
---|
72 | |
---|
73 | #ifdef OPT_GRAPH_DEBUG_EXT |
---|
74 | static void dependGraphOutput( TARGET *t, int depth ); |
---|
75 | #endif |
---|
76 | |
---|
77 | static const char *target_fate[] = |
---|
78 | { |
---|
79 | "init", /* T_FATE_INIT */ |
---|
80 | "making", /* T_FATE_MAKING */ |
---|
81 | "stable", /* T_FATE_STABLE */ |
---|
82 | "newer", /* T_FATE_NEWER */ |
---|
83 | "temp", /* T_FATE_ISTMP */ |
---|
84 | "touched", /* T_FATE_TOUCHED */ |
---|
85 | "rebuild", /* T_FATE_REBUILD */ |
---|
86 | "missing", /* T_FATE_MISSING */ |
---|
87 | "needtmp", /* T_FATE_NEEDTMP */ |
---|
88 | "old", /* T_FATE_OUTDATED */ |
---|
89 | "update", /* T_FATE_UPDATE */ |
---|
90 | "nofind", /* T_FATE_CANTFIND */ |
---|
91 | "nomake" /* T_FATE_CANTMAKE */ |
---|
92 | } ; |
---|
93 | |
---|
94 | static const char *target_bind[] = |
---|
95 | { |
---|
96 | "unbound", |
---|
97 | "missing", |
---|
98 | "parents", |
---|
99 | "exists", |
---|
100 | } ; |
---|
101 | |
---|
102 | # define spaces(x) ( " " + ( x > 20 ? 0 : 20-x ) ) |
---|
103 | |
---|
104 | /* |
---|
105 | * make() - make a target, given its name |
---|
106 | */ |
---|
107 | |
---|
108 | int |
---|
109 | make( |
---|
110 | int n_targets, |
---|
111 | const char **targets, |
---|
112 | int anyhow ) |
---|
113 | { |
---|
114 | int i; |
---|
115 | COUNTS counts[1]; |
---|
116 | int status = 0; /* 1 if anything fails */ |
---|
117 | |
---|
118 | #ifdef OPT_HEADER_CACHE_EXT |
---|
119 | hcache_init(); |
---|
120 | #endif |
---|
121 | |
---|
122 | memset( (char *)counts, 0, sizeof( *counts ) ); |
---|
123 | |
---|
124 | /* First bind all targets with LOCATE_TARGET setting. This is |
---|
125 | needed to correctly handle dependencies to generated headers. |
---|
126 | */ |
---|
127 | bind_explicitly_located_targets(); |
---|
128 | |
---|
129 | for( i = 0; i < n_targets; i++ ) |
---|
130 | { |
---|
131 | TARGET *t = bindtarget( targets[i] ); |
---|
132 | |
---|
133 | make0( t, 0, 0, counts, anyhow ); |
---|
134 | } |
---|
135 | |
---|
136 | #ifdef OPT_GRAPH_DEBUG_EXT |
---|
137 | if( DEBUG_GRAPH ) |
---|
138 | { |
---|
139 | for( i = 0; i < n_targets; i++ ) |
---|
140 | { |
---|
141 | TARGET *t = bindtarget( targets[i] ); |
---|
142 | dependGraphOutput( t, 0 ); |
---|
143 | } |
---|
144 | } |
---|
145 | #endif |
---|
146 | |
---|
147 | if( DEBUG_MAKE ) |
---|
148 | { |
---|
149 | if( counts->targets ) |
---|
150 | printf( "...found %d target%s...\n", counts->targets, |
---|
151 | counts->targets > 1 ? "s" : "" ); |
---|
152 | if( counts->temp ) |
---|
153 | printf( "...using %d temp target%s...\n", counts->temp, |
---|
154 | counts->temp > 1 ? "s" : "" ); |
---|
155 | if( counts->updating ) |
---|
156 | printf( "...updating %d target%s...\n", counts->updating, |
---|
157 | counts->updating > 1 ? "s" : "" ); |
---|
158 | if( counts->cantfind ) |
---|
159 | printf( "...can't find %d target%s...\n", counts->cantfind, |
---|
160 | counts->cantfind > 1 ? "s" : "" ); |
---|
161 | if( counts->cantmake ) |
---|
162 | printf( "...can't make %d target%s...\n", counts->cantmake, |
---|
163 | counts->cantmake > 1 ? "s" : "" ); |
---|
164 | } |
---|
165 | |
---|
166 | #ifdef OPT_HEADER_CACHE_EXT |
---|
167 | hcache_done(); |
---|
168 | #endif |
---|
169 | |
---|
170 | status = counts->cantfind || counts->cantmake; |
---|
171 | |
---|
172 | for( i = 0; i < n_targets; i++ ) |
---|
173 | status |= make1( bindtarget( targets[i] ) ); |
---|
174 | |
---|
175 | return status; |
---|
176 | } |
---|
177 | |
---|
178 | /* Force any dependents of t that have already at least begun being |
---|
179 | * visited by make0 to be updated. |
---|
180 | */ |
---|
181 | static void update_dependents(TARGET* t) |
---|
182 | { |
---|
183 | TARGETS *q; |
---|
184 | |
---|
185 | for (q = t->dependents; q; q = q->next) |
---|
186 | { |
---|
187 | TARGET* p = q->target; |
---|
188 | char fate0 = p->fate; |
---|
189 | |
---|
190 | /* If we've already at least begun visiting it and |
---|
191 | * we're not already rebuilding it for other reasons |
---|
192 | */ |
---|
193 | if (fate0 != T_FATE_INIT && fate0 < T_FATE_BUILD) |
---|
194 | { |
---|
195 | p->fate = T_FATE_UPDATE; |
---|
196 | |
---|
197 | if (DEBUG_FATE) |
---|
198 | { |
---|
199 | printf( "fate change %s from %s to %s (as dependent of %s)\n", |
---|
200 | p->name, target_fate[fate0], target_fate[p->fate], t->name); |
---|
201 | } |
---|
202 | |
---|
203 | /* If we're done visiting it, go back and make sure its |
---|
204 | * dependents get rebuilt. |
---|
205 | */ |
---|
206 | if (fate0 > T_FATE_MAKING) |
---|
207 | update_dependents(p); |
---|
208 | } |
---|
209 | } |
---|
210 | } |
---|
211 | |
---|
212 | /* Make sure that all of t's rebuilds get rebuilt */ |
---|
213 | static void force_rebuilds(TARGET* t) |
---|
214 | { |
---|
215 | TARGETS* d; |
---|
216 | for (d = t->rebuilds; d; d = d->next) |
---|
217 | { |
---|
218 | TARGET* r = d->target; |
---|
219 | |
---|
220 | /* If it's not already being rebuilt for other reasons */ |
---|
221 | if (r->fate < T_FATE_BUILD) |
---|
222 | { |
---|
223 | if (DEBUG_FATE) |
---|
224 | printf( "fate change %s from %s to %s (by rebuild)\n", |
---|
225 | r->name, target_fate[r->fate], target_fate[T_FATE_REBUILD]); |
---|
226 | |
---|
227 | /* Force rebuild it */ |
---|
228 | r->fate = T_FATE_REBUILD; |
---|
229 | |
---|
230 | /* And make sure its dependents are updated too */ |
---|
231 | update_dependents(r); |
---|
232 | } |
---|
233 | } |
---|
234 | } |
---|
235 | /* |
---|
236 | * make0() - bind and scan everything to make a TARGET |
---|
237 | * |
---|
238 | * Make0() recursively binds a target, searches for #included headers, |
---|
239 | * calls itself on those headers, and calls itself on any dependents. |
---|
240 | */ |
---|
241 | |
---|
242 | void |
---|
243 | make0( |
---|
244 | TARGET *t, |
---|
245 | TARGET *p, /* parent */ |
---|
246 | int depth, /* for display purposes */ |
---|
247 | COUNTS *counts, /* for reporting */ |
---|
248 | int anyhow ) /* forcibly touch all (real) targets */ |
---|
249 | { |
---|
250 | TARGETS *c, *d, *incs; |
---|
251 | TARGET *ptime = t; |
---|
252 | time_t last, leaf, hlast; |
---|
253 | int fate; |
---|
254 | const char *flag = ""; |
---|
255 | SETTINGS *s; |
---|
256 | |
---|
257 | #ifdef OPT_GRAPH_DEBUG_EXT |
---|
258 | int savedFate, oldTimeStamp; |
---|
259 | #endif |
---|
260 | |
---|
261 | if( DEBUG_MAKEPROG ) |
---|
262 | printf( "make\t--\t%s%s\n", spaces( depth ), t->name ); |
---|
263 | |
---|
264 | /* |
---|
265 | * Step 1: initialize |
---|
266 | */ |
---|
267 | |
---|
268 | if( DEBUG_MAKEPROG ) |
---|
269 | printf( "make\t--\t%s%s\n", spaces( depth ), t->name ); |
---|
270 | |
---|
271 | t->fate = T_FATE_MAKING; |
---|
272 | |
---|
273 | /* |
---|
274 | * Step 2: under the influence of "on target" variables, |
---|
275 | * bind the target and search for headers. |
---|
276 | */ |
---|
277 | |
---|
278 | /* Step 2a: set "on target" variables. */ |
---|
279 | |
---|
280 | s = copysettings( t->settings ); |
---|
281 | pushsettings( s ); |
---|
282 | |
---|
283 | /* Step 2b: find and timestamp the target file (if it's a file). */ |
---|
284 | |
---|
285 | if( t->binding == T_BIND_UNBOUND && !( t->flags & T_FLAG_NOTFILE ) ) |
---|
286 | { |
---|
287 | char* another_target; |
---|
288 | t->boundname = search( t->name, &t->time, &another_target ); |
---|
289 | /* If it was detected that this target refers to an already |
---|
290 | existing and bound one, we add include dependency, so that |
---|
291 | every target which depends on us will depend on that other |
---|
292 | target. */ |
---|
293 | if( another_target ) |
---|
294 | { |
---|
295 | TARGET* includes; |
---|
296 | if (!t->includes) { |
---|
297 | t->includes = copytarget(t); |
---|
298 | t->includes->original_target = t; |
---|
299 | } |
---|
300 | includes = t->includes; |
---|
301 | includes->depends = targetlist( includes->depends, |
---|
302 | list_new( L0, another_target ) ); |
---|
303 | } |
---|
304 | |
---|
305 | t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING; |
---|
306 | } |
---|
307 | |
---|
308 | /* INTERNAL, NOTFILE header nodes have the time of their parents */ |
---|
309 | |
---|
310 | if( p && t->flags & T_FLAG_INTERNAL ) |
---|
311 | ptime = p; |
---|
312 | |
---|
313 | /* If temp file doesn't exist but parent does, use parent */ |
---|
314 | if( p && t->flags & T_FLAG_TEMP && |
---|
315 | t->binding == T_BIND_MISSING && |
---|
316 | p->binding != T_BIND_MISSING ) |
---|
317 | { |
---|
318 | t->binding = T_BIND_PARENTS; |
---|
319 | ptime = p; |
---|
320 | } |
---|
321 | |
---|
322 | #ifdef OPT_SEMAPHORE |
---|
323 | { |
---|
324 | LIST *var = var_get( "JAM_SEMAPHORE" ); |
---|
325 | if( var ) |
---|
326 | { |
---|
327 | TARGET *semaphore = bindtarget( var->string ); |
---|
328 | |
---|
329 | semaphore->progress = T_MAKE_SEMAPHORE; |
---|
330 | t->semaphore = semaphore; |
---|
331 | } |
---|
332 | } |
---|
333 | #endif |
---|
334 | |
---|
335 | /* Step 2c: If its a file, search for headers. */ |
---|
336 | |
---|
337 | if( t->binding == T_BIND_EXISTS ) |
---|
338 | headers( t ); |
---|
339 | |
---|
340 | /* Step 2d: reset "on target" variables */ |
---|
341 | |
---|
342 | popsettings( s ); |
---|
343 | freesettings( s ); |
---|
344 | |
---|
345 | /* |
---|
346 | * Pause for a little progress reporting |
---|
347 | */ |
---|
348 | |
---|
349 | if( DEBUG_BIND ) |
---|
350 | |
---|
351 | { |
---|
352 | if( strcmp( t->name, t->boundname ) ) |
---|
353 | { |
---|
354 | printf( "bind\t--\t%s%s: %s\n", |
---|
355 | spaces( depth ), t->name, t->boundname ); |
---|
356 | } |
---|
357 | |
---|
358 | switch( t->binding ) |
---|
359 | { |
---|
360 | case T_BIND_UNBOUND: |
---|
361 | case T_BIND_MISSING: |
---|
362 | case T_BIND_PARENTS: |
---|
363 | printf( "time\t--\t%s%s: %s\n", |
---|
364 | spaces( depth ), t->name, target_bind[ t->binding ] ); |
---|
365 | break; |
---|
366 | |
---|
367 | case T_BIND_EXISTS: |
---|
368 | printf( "time\t--\t%s%s: %s", |
---|
369 | spaces( depth ), t->name, ctime( &t->time ) ); |
---|
370 | break; |
---|
371 | } |
---|
372 | } |
---|
373 | |
---|
374 | /* |
---|
375 | * Step 3: recursively make0() dependents & headers |
---|
376 | */ |
---|
377 | |
---|
378 | /* Step 3a: recursively make0() dependents */ |
---|
379 | |
---|
380 | for( c = t->depends; c; c = c->next ) |
---|
381 | { |
---|
382 | int internal = t->flags & T_FLAG_INTERNAL; |
---|
383 | /* Seems like it's not relevant for us.... |
---|
384 | if( DEBUG_DEPENDS ) |
---|
385 | printf( "%s \"%s\" : \"%s\" ;\n", |
---|
386 | internal ? "Includes" : "Depends", |
---|
387 | t->name, c->target->name ); |
---|
388 | */ |
---|
389 | |
---|
390 | /* Warn about circular deps, except for includes, */ |
---|
391 | /* which include each other alot. */ |
---|
392 | |
---|
393 | if( c->target->fate == T_FATE_INIT ) |
---|
394 | make0( c->target, ptime, depth + 1, counts, anyhow ); |
---|
395 | else if( c->target->fate == T_FATE_MAKING && !internal ) |
---|
396 | printf( "warning: %s depends on itself\n", c->target->name ); |
---|
397 | } |
---|
398 | |
---|
399 | /* Step 3b: recursively make0() internal includes node */ |
---|
400 | |
---|
401 | if( t->includes ) |
---|
402 | make0( t->includes, p, depth + 1, counts, anyhow ); |
---|
403 | |
---|
404 | /* Step 3c: add dependents' includes to our direct dependencies */ |
---|
405 | |
---|
406 | incs = 0; |
---|
407 | |
---|
408 | for( c = t->depends; c; c = c->next ) |
---|
409 | if( c->target->includes ) |
---|
410 | incs = targetentry( incs, c->target->includes ); |
---|
411 | |
---|
412 | t->depends = targetchain( t->depends, incs ); |
---|
413 | |
---|
414 | /* |
---|
415 | * Step 4: compute time & fate |
---|
416 | */ |
---|
417 | |
---|
418 | /* Step 4a: pick up dependents' time and fate */ |
---|
419 | |
---|
420 | |
---|
421 | last = 0; |
---|
422 | leaf = 0; |
---|
423 | fate = T_FATE_STABLE; |
---|
424 | |
---|
425 | for( c = t->depends; c; c = c->next ) |
---|
426 | { |
---|
427 | /* If LEAVES has been applied, we only heed the timestamps of */ |
---|
428 | /* the leaf source nodes. */ |
---|
429 | |
---|
430 | leaf = max( leaf, c->target->leaf ); |
---|
431 | |
---|
432 | if( t->flags & T_FLAG_LEAVES ) |
---|
433 | { |
---|
434 | last = leaf; |
---|
435 | continue; |
---|
436 | } |
---|
437 | |
---|
438 | last = max( last, c->target->time ); |
---|
439 | fate = max( fate, c->target->fate ); |
---|
440 | |
---|
441 | #ifdef OPT_GRAPH_DEBUG_EXT |
---|
442 | if( DEBUG_FATE ) |
---|
443 | if( fate < c->target->fate ) |
---|
444 | printf( "fate change %s from %s to %s by dependency %s\n", |
---|
445 | t->name, |
---|
446 | target_fate[fate], target_fate[c->target->fate], |
---|
447 | c->target->name); |
---|
448 | #endif |
---|
449 | |
---|
450 | } |
---|
451 | |
---|
452 | /* Step 4b: pick up included headers time */ |
---|
453 | |
---|
454 | /* |
---|
455 | * If a header is newer than a temp source that includes it, |
---|
456 | * the temp source will need building. |
---|
457 | */ |
---|
458 | |
---|
459 | hlast = t->includes ? t->includes->time : 0; |
---|
460 | |
---|
461 | /* Step 4c: handle NOUPDATE oddity */ |
---|
462 | |
---|
463 | /* |
---|
464 | * If a NOUPDATE file exists, make dependents eternally old. |
---|
465 | * Don't inherit our fate from our dependents. Decide fate |
---|
466 | * based only upon other flags and our binding (done later). |
---|
467 | */ |
---|
468 | |
---|
469 | if( t->flags & T_FLAG_NOUPDATE ) |
---|
470 | { |
---|
471 | #ifdef OPT_GRAPH_DEBUG_EXT |
---|
472 | if( DEBUG_FATE ) |
---|
473 | if( fate != T_FATE_STABLE ) |
---|
474 | printf( "fate change %s back to stable, NOUPDATE.\n", |
---|
475 | t->name); |
---|
476 | #endif |
---|
477 | |
---|
478 | last = 0; |
---|
479 | t->time = 0; |
---|
480 | |
---|
481 | |
---|
482 | /* |
---|
483 | * Don't inherit our fate from our dependents. Decide fate |
---|
484 | * based only upon other flags and our binding (done later). |
---|
485 | */ |
---|
486 | |
---|
487 | fate = T_FATE_STABLE; |
---|
488 | } |
---|
489 | |
---|
490 | /* Step 4d: determine fate: rebuild target or what? */ |
---|
491 | |
---|
492 | /* |
---|
493 | In English: |
---|
494 | If can't find or make child, can't make target. |
---|
495 | If children changed, make target. |
---|
496 | If target missing, make it. |
---|
497 | If children newer, make target. |
---|
498 | If temp's children newer than parent, make temp. |
---|
499 | If temp's headers newer than parent, make temp. |
---|
500 | If deliberately touched, make it. |
---|
501 | If up-to-date temp file present, use it. |
---|
502 | If target newer than non-notfile parent, mark target newer. |
---|
503 | Otherwise, stable! |
---|
504 | |
---|
505 | Note this block runs from least to most stable: |
---|
506 | as we make it further down the list, the target's |
---|
507 | fate is getting stabler. |
---|
508 | */ |
---|
509 | |
---|
510 | #ifdef OPT_GRAPH_DEBUG_EXT |
---|
511 | savedFate = fate; |
---|
512 | oldTimeStamp = 0; |
---|
513 | #endif |
---|
514 | |
---|
515 | if( fate >= T_FATE_BROKEN ) |
---|
516 | { |
---|
517 | fate = T_FATE_CANTMAKE; |
---|
518 | } |
---|
519 | else if( fate >= T_FATE_SPOIL ) |
---|
520 | { |
---|
521 | fate = T_FATE_UPDATE; |
---|
522 | } |
---|
523 | else if( t->binding == T_BIND_MISSING ) |
---|
524 | { |
---|
525 | fate = T_FATE_MISSING; |
---|
526 | } |
---|
527 | else if( t->binding == T_BIND_EXISTS && last > t->time ) |
---|
528 | { |
---|
529 | #ifdef OPT_GRAPH_DEBUG_EXT |
---|
530 | oldTimeStamp = 1; |
---|
531 | #endif |
---|
532 | fate = T_FATE_OUTDATED; |
---|
533 | } |
---|
534 | else if( t->binding == T_BIND_PARENTS && last > p->time ) |
---|
535 | { |
---|
536 | #ifdef OPT_GRAPH_DEBUG_EXT |
---|
537 | oldTimeStamp = 1; |
---|
538 | #endif |
---|
539 | fate = T_FATE_NEEDTMP; |
---|
540 | } |
---|
541 | else if( t->binding == T_BIND_PARENTS && hlast > p->time ) |
---|
542 | { |
---|
543 | fate = T_FATE_NEEDTMP; |
---|
544 | } |
---|
545 | else if( t->flags & T_FLAG_TOUCHED ) |
---|
546 | { |
---|
547 | fate = T_FATE_TOUCHED; |
---|
548 | } |
---|
549 | else if( anyhow && !( t->flags & T_FLAG_NOUPDATE ) ) |
---|
550 | { |
---|
551 | fate = T_FATE_TOUCHED; |
---|
552 | } |
---|
553 | else if( t->binding == T_BIND_EXISTS && t->flags & T_FLAG_TEMP ) |
---|
554 | { |
---|
555 | fate = T_FATE_ISTMP; |
---|
556 | } |
---|
557 | else if( t->binding == T_BIND_EXISTS && p && |
---|
558 | p->binding != T_BIND_UNBOUND && t->time > p->time ) |
---|
559 | { |
---|
560 | #ifdef OPT_GRAPH_DEBUG_EXT |
---|
561 | oldTimeStamp = 1; |
---|
562 | #endif |
---|
563 | fate = T_FATE_NEWER; |
---|
564 | } |
---|
565 | else |
---|
566 | { |
---|
567 | fate = T_FATE_STABLE; |
---|
568 | } |
---|
569 | #ifdef OPT_GRAPH_DEBUG_EXT |
---|
570 | if( DEBUG_FATE && fate != savedFate ) |
---|
571 | if( savedFate == T_FATE_STABLE ) |
---|
572 | printf( "fate change %s set to %s%s\n", |
---|
573 | t->name, target_fate[fate], |
---|
574 | oldTimeStamp ? " (by timestamp)" : "" ); |
---|
575 | else |
---|
576 | printf( "fate change %s from %s to %s%s\n", |
---|
577 | t->name, target_fate[savedFate], target_fate[fate], |
---|
578 | oldTimeStamp ? " (by timestamp)" : "" ); |
---|
579 | #endif |
---|
580 | |
---|
581 | /* Step 4e: handle missing files */ |
---|
582 | /* If it's missing and there are no actions to create it, boom. */ |
---|
583 | /* If we can't make a target we don't care about, 'sokay */ |
---|
584 | /* We could insist that there are updating actions for all missing */ |
---|
585 | /* files, but if they have dependents we just pretend it's NOTFILE. */ |
---|
586 | |
---|
587 | if( fate == T_FATE_MISSING && !t->actions && !t->depends ) |
---|
588 | { |
---|
589 | if( t->flags & T_FLAG_NOCARE ) |
---|
590 | { |
---|
591 | #ifdef OPT_GRAPH_DEBUG_EXT |
---|
592 | if( DEBUG_FATE ) |
---|
593 | printf( "fate change %s to STABLE from %s, " |
---|
594 | "no actions, no dependents and don't care\n", |
---|
595 | t->name, target_fate[fate]); |
---|
596 | #endif |
---|
597 | fate = T_FATE_STABLE; |
---|
598 | } |
---|
599 | else |
---|
600 | { |
---|
601 | printf( "don't know how to make %s\n", t->name ); |
---|
602 | |
---|
603 | fate = T_FATE_CANTFIND; |
---|
604 | } |
---|
605 | } |
---|
606 | |
---|
607 | /* Step 4f: propagate dependents' time & fate. */ |
---|
608 | /* Set leaf time to be our time only if this is a leaf. */ |
---|
609 | |
---|
610 | t->time = max( t->time, last ); |
---|
611 | t->leaf = leaf ? leaf : t->time ; |
---|
612 | /* This target's fate may have been updated by virtue of following |
---|
613 | * some target's rebuilds list, so only allow it to be increased |
---|
614 | * to the fate we've calculated. Otherwise, grab its new fate. |
---|
615 | */ |
---|
616 | if (fate > t->fate) |
---|
617 | t->fate = fate; |
---|
618 | else |
---|
619 | fate = t->fate; |
---|
620 | |
---|
621 | /* Step 4g: if this target needs to be built, force rebuild |
---|
622 | * everything in this target's rebuilds list */ |
---|
623 | if (fate >= T_FATE_BUILD && fate < T_FATE_BROKEN) |
---|
624 | force_rebuilds(t); |
---|
625 | /* |
---|
626 | * Step 5: sort dependents by their update time. |
---|
627 | */ |
---|
628 | |
---|
629 | if( globs.newestfirst ) |
---|
630 | t->depends = make0sort( t->depends ); |
---|
631 | |
---|
632 | /* |
---|
633 | * Step 6: a little harmless tabulating for tracing purposes |
---|
634 | */ |
---|
635 | |
---|
636 | /* Don't count or report interal includes nodes. */ |
---|
637 | |
---|
638 | if( t->flags & T_FLAG_INTERNAL ) |
---|
639 | return; |
---|
640 | |
---|
641 | if (counts) { |
---|
642 | #ifdef OPT_IMPROVED_PATIENCE_EXT |
---|
643 | ++counts->targets; |
---|
644 | #else |
---|
645 | if( !( ++counts->targets % 1000 ) && DEBUG_MAKE ) |
---|
646 | printf( "...patience...\n" ); |
---|
647 | #endif |
---|
648 | |
---|
649 | if( fate == T_FATE_ISTMP ) |
---|
650 | counts->temp++; |
---|
651 | else if( fate == T_FATE_CANTFIND ) |
---|
652 | counts->cantfind++; |
---|
653 | else if( fate == T_FATE_CANTMAKE && t->actions ) |
---|
654 | counts->cantmake++; |
---|
655 | else if( fate >= T_FATE_BUILD && fate < T_FATE_BROKEN && t->actions ) |
---|
656 | counts->updating++; |
---|
657 | } |
---|
658 | |
---|
659 | if( !( t->flags & T_FLAG_NOTFILE ) && fate >= T_FATE_SPOIL ) |
---|
660 | flag = "+"; |
---|
661 | else if( t->binding == T_BIND_EXISTS && p && t->time > p->time ) |
---|
662 | flag = "*"; |
---|
663 | |
---|
664 | if( DEBUG_MAKEPROG ) |
---|
665 | printf( "made%s\t%s\t%s%s\n", |
---|
666 | flag, target_fate[ t->fate ], |
---|
667 | spaces( depth ), t->name ); |
---|
668 | |
---|
669 | /* We don't have DEBUG_CAUSES. |
---|
670 | if( DEBUG_CAUSES && |
---|
671 | t->fate >= T_FATE_NEWER && |
---|
672 | t->fate <= T_FATE_MISSING ) |
---|
673 | printf( "%s %s\n", target_fate[ t->fate ], t->name ); |
---|
674 | */ |
---|
675 | } |
---|
676 | |
---|
677 | #ifdef OPT_GRAPH_DEBUG_EXT |
---|
678 | |
---|
679 | static const char* target_name( TARGET* t ) |
---|
680 | { |
---|
681 | static char buf[1000]; |
---|
682 | if (t->flags & T_FLAG_INTERNAL) { |
---|
683 | sprintf(buf, "%s (internal node)", t->name); |
---|
684 | return buf; |
---|
685 | } else { |
---|
686 | return t->name; |
---|
687 | } |
---|
688 | } |
---|
689 | |
---|
690 | /* |
---|
691 | * dependGraphOutput() - output the DG after make0 has run |
---|
692 | */ |
---|
693 | |
---|
694 | static void |
---|
695 | dependGraphOutput( TARGET *t, int depth ) |
---|
696 | { |
---|
697 | TARGETS *c; |
---|
698 | |
---|
699 | if ( (t->flags & T_FLAG_VISITED) != 0 |
---|
700 | || !t->name |
---|
701 | || !t->boundname) |
---|
702 | return; |
---|
703 | |
---|
704 | t->flags |= T_FLAG_VISITED; |
---|
705 | |
---|
706 | switch (t->fate) |
---|
707 | { |
---|
708 | case T_FATE_TOUCHED: |
---|
709 | case T_FATE_MISSING: |
---|
710 | case T_FATE_OUTDATED: |
---|
711 | case T_FATE_UPDATE: |
---|
712 | printf( "->%s%2d Name: %s\n", spaces(depth), depth, target_name(t) ); |
---|
713 | break; |
---|
714 | default: |
---|
715 | printf( " %s%2d Name: %s\n", spaces(depth), depth, target_name(t) ); |
---|
716 | break; |
---|
717 | } |
---|
718 | |
---|
719 | if( strcmp (t->name, t->boundname) ) |
---|
720 | { |
---|
721 | printf( " %s Loc: %s\n", spaces(depth), t->boundname ); |
---|
722 | } |
---|
723 | |
---|
724 | switch( t->fate ) |
---|
725 | { |
---|
726 | case T_FATE_STABLE: |
---|
727 | printf( " %s : Stable\n", spaces(depth) ); |
---|
728 | break; |
---|
729 | case T_FATE_NEWER: |
---|
730 | printf( " %s : Newer\n", spaces(depth) ); |
---|
731 | break; |
---|
732 | case T_FATE_ISTMP: |
---|
733 | printf( " %s : Up to date temp file\n", spaces(depth) ); |
---|
734 | case T_FATE_NEEDTMP: |
---|
735 | printf( " %s : Temporary file, to be updated\n", spaces(depth) ); |
---|
736 | break; |
---|
737 | case T_FATE_TOUCHED: |
---|
738 | printf( " %s : Been touched, updating it\n", spaces(depth) ); |
---|
739 | break; |
---|
740 | case T_FATE_MISSING: |
---|
741 | printf( " %s : Missing, creating it\n", spaces(depth) ); |
---|
742 | break; |
---|
743 | case T_FATE_OUTDATED: |
---|
744 | printf( " %s : Outdated, updating it\n", spaces(depth) ); |
---|
745 | break; |
---|
746 | case T_FATE_REBUILD: |
---|
747 | printf( " %s : Rebuild, Updating it\n", spaces(depth) ); |
---|
748 | break; |
---|
749 | case T_FATE_UPDATE: |
---|
750 | printf( " %s : Updating it\n", spaces(depth) ); |
---|
751 | break; |
---|
752 | case T_FATE_CANTFIND: |
---|
753 | printf( " %s : Can't find it\n", spaces(depth) ); |
---|
754 | break; |
---|
755 | case T_FATE_CANTMAKE: |
---|
756 | printf( " %s : Can't make it\n", spaces(depth) ); |
---|
757 | break; |
---|
758 | } |
---|
759 | |
---|
760 | if( t->flags & ~T_FLAG_VISITED ) |
---|
761 | { |
---|
762 | printf( " %s : ", spaces(depth) ); |
---|
763 | if( t->flags & T_FLAG_TEMP ) printf ("TEMPORARY "); |
---|
764 | if( t->flags & T_FLAG_NOCARE ) printf ("NOCARE "); |
---|
765 | if( t->flags & T_FLAG_NOTFILE ) printf ("NOTFILE "); |
---|
766 | if( t->flags & T_FLAG_TOUCHED ) printf ("TOUCHED "); |
---|
767 | if( t->flags & T_FLAG_LEAVES ) printf ("LEAVES "); |
---|
768 | if( t->flags & T_FLAG_NOUPDATE ) printf ("NOUPDATE "); |
---|
769 | printf( "\n" ); |
---|
770 | } |
---|
771 | |
---|
772 | for( c = t->depends; c; c = c->next ) |
---|
773 | { |
---|
774 | printf( " %s : Depends on %s (%s)", spaces(depth), |
---|
775 | target_name(c->target), target_fate[ c->target->fate ] ); |
---|
776 | if (c->target->time == t->time) |
---|
777 | printf( " (max time)"); |
---|
778 | printf("\n"); |
---|
779 | |
---|
780 | } |
---|
781 | |
---|
782 | |
---|
783 | for( c = t->depends; c; c = c->next ) |
---|
784 | { |
---|
785 | |
---|
786 | dependGraphOutput( c->target, depth + 1 ); |
---|
787 | } |
---|
788 | } |
---|
789 | |
---|
790 | #endif |
---|
791 | /* |
---|
792 | * make0sort() - reorder TARGETS chain by their time (newest to oldest) |
---|
793 | */ |
---|
794 | |
---|
795 | static TARGETS * |
---|
796 | make0sort( TARGETS *chain ) |
---|
797 | { |
---|
798 | TARGETS *result = 0; |
---|
799 | |
---|
800 | /* We walk chain, taking each item and inserting it on the */ |
---|
801 | /* sorted result, with newest items at the front. This involves */ |
---|
802 | /* updating each TARGETS' c->next and c->tail. Note that we */ |
---|
803 | /* make c->tail a valid prev pointer for every entry. Normally, */ |
---|
804 | /* it is only valid at the head, where prev == tail. Note also */ |
---|
805 | /* that while tail is a loop, next ends at the end of the chain. */ |
---|
806 | |
---|
807 | /* Walk current target list */ |
---|
808 | |
---|
809 | while( chain ) |
---|
810 | { |
---|
811 | TARGETS *c = chain; |
---|
812 | TARGETS *s = result; |
---|
813 | |
---|
814 | chain = chain->next; |
---|
815 | |
---|
816 | /* Find point s in result for c */ |
---|
817 | |
---|
818 | while( s && s->target->time > c->target->time ) |
---|
819 | s = s->next; |
---|
820 | |
---|
821 | /* Insert c in front of s (might be 0). */ |
---|
822 | /* Don't even think of deciphering this. */ |
---|
823 | |
---|
824 | c->next = s; /* good even if s = 0 */ |
---|
825 | if( result == s ) result = c; /* new head of chain? */ |
---|
826 | if( !s ) s = result; /* wrap to ensure a next */ |
---|
827 | if( result != c ) s->tail->next = c; /* not head? be prev's next */ |
---|
828 | c->tail = s->tail; /* take on next's prev */ |
---|
829 | s->tail = c; /* make next's prev us */ |
---|
830 | } |
---|
831 | |
---|
832 | return result; |
---|
833 | } |
---|
834 | |
---|
835 | static LIST *targets_to_update_ = 0; |
---|
836 | |
---|
837 | void mark_target_for_updating(char *target) |
---|
838 | { |
---|
839 | targets_to_update_ = list_new( targets_to_update_, target ); |
---|
840 | } |
---|
841 | |
---|
842 | LIST *targets_to_update() |
---|
843 | { |
---|
844 | return targets_to_update_; |
---|
845 | } |
---|
846 | |
---|
847 | void clear_targets_to_update() |
---|
848 | { |
---|
849 | list_free(targets_to_update_); |
---|
850 | targets_to_update_ = 0; |
---|
851 | } |
---|