cosmetix in filesystem operations
[k8jam.git] / src / make.c
blobbe6e41b62a0d70214600ba60a44118ddcf7e5542
1 /*
2 * Copyright 1993, 1995 Christopher Seiwald.
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
6 /*
7 * make.c - bring a target up to date, once rules are in place
9 * This modules controls the execution of rules to bring a target and
10 * its dependencies up to date. It is invoked after the targets, rules,
11 * et. al. described in rules.h are created by the interpreting of the
12 * jam files.
14 * This file contains the main make() entry point and the first pass
15 * make0(). The second pass, make1(), which actually does the command
16 * execution, is in make1.c.
18 * External routines:
19 * make() - make a target, given its name
21 * Internal routines:
22 * make0() - bind and scan everything to make a TARGET
23 * make0sort() - reorder TARGETS chain by their time (newest to oldest)
25 * 12/26/93 (seiwald) - allow NOTIME targets to be expanded via $(<), $(>)
26 * 01/04/94 (seiwald) - print all targets, bounded, when tracing commands
27 * 04/08/94 (seiwald) - progress report now reflects only targets with actions
28 * 04/11/94 (seiwald) - Combined deps & headers into deps[2] in TARGET.
29 * 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
30 * 12/20/94 (seiwald) - make0() headers after determining fate of target, so
31 * that headers aren't seen as dependents on themselves.
32 * 01/19/95 (seiwald) - distinguish between CANTFIND/CANTMAKE targets.
33 * 02/02/95 (seiwald) - propagate leaf source time for new LEAVES rule.
34 * 02/14/95 (seiwald) - NOUPDATE rule means don't update existing target.
35 * 08/22/95 (seiwald) - NOUPDATE targets immune to anyhow (-a) flag.
36 * 09/06/00 (seiwald) - NOCARE affects targets with sources/actions.
37 * 03/02/01 (seiwald) - reverse NOCARE change.
38 * 03/14/02 (seiwald) - TEMPORARY targets no longer take on parents age
39 * 03/16/02 (seiwald) - support for -g (reorder builds by source time)
40 * 07/17/02 (seiwald) - TEMPORARY sources for headers now get built
41 * 09/19/02 (seiwald) - new -d displays
42 * 09/23/02 (seiwald) - suppress "...using temp..." in default output
43 * 09/28/02 (seiwald) - make0() takes parent pointer; new -dc display
44 * 11/04/02 (seiwald) - const-ing for string literals
45 * 12/03/02 (seiwald) - fix odd includes support by grafting them onto depends
46 * 12/17/02 (seiwald) - new copysettings() to protect target-specific vars
47 * 01/03/03 (seiwald) - T_FATE_NEWER once again gets set with missing parent
48 * 01/14/03 (seiwald) - fix includes fix with new internal includes TARGET
49 * 04/04/03 (seiwald) - fix INTERNAL node binding to avoid T_BIND_PARENTS
50 * 04/14/06 (kaib) - fix targets to show in 'updated' when their includes
51 * are newer
53 #include "jam.h"
55 #include "lists.h"
56 #include "parse.h"
57 #include "variable.h"
58 #include "rules.h"
60 #include "search.h"
61 #include "newstr.h"
62 #include "make.h"
63 #include "hcache.h"
64 #include "headers.h"
65 #include "command.h"
67 //#ifdef OPT_IMPROVED_PROGRESS_EXT
68 #include "progress.h"
69 //#endif
71 #ifndef max
72 # define max(a,b) ((a)>(b)?(a):(b))
73 #endif
76 typedef struct {
77 int temp;
78 int updating;
79 int cantfind;
80 int cantmake;
81 int targets;
82 int made;
83 } COUNTS;
86 static void make0 (TARGET *t, TARGET *p, int depth, COUNTS *counts, int anyhow);
89 static TARGETS *make0sort (TARGETS *c);
92 static const char *target_fate[] = {
93 "init", /* T_FATE_INIT */
94 "making", /* T_FATE_MAKING */
95 "stable", /* T_FATE_STABLE */
96 "newer", /* T_FATE_NEWER */
97 "temp", /* T_FATE_ISTMP */
98 "touched", /* T_FATE_TOUCHED */
99 "missing", /* T_FATE_MISSING */
100 "needtmp", /* T_FATE_NEEDTMP */
101 "old", /* T_FATE_OUTDATED */
102 "update", /* T_FATE_UPDATE */
103 "nofind", /* T_FATE_CANTFIND */
104 "nomake" /* T_FATE_CANTMAKE */
108 static const char *target_bind[] = {
109 "unbound",
110 "missing",
111 "parents",
112 "exists",
115 #define spaces(x) (" "+16-(x>16?16:x))
119 * Return 'silent make' flag
121 int is_make_silent (void) {
122 LIST *var = var_get("JAM_OPTION_MAKE_UPDATES_SILENT");
123 return (var && var->string &&
124 strcmp(var->string, "ona") != 0 &&
125 strcmp(var->string, "no") != 0 &&
126 strcmp(var->string, "false") != 0 &&
127 strcmp(var->string, "0") != 0);
132 * make() - make a target, given its name
134 int make (int n_targets, const char **targets, int anyhow) {
135 int i;
136 COUNTS counts[1];
137 int status = 0; /* 1 if anything fails */
139 //#ifdef OPT_HEADER_CACHE_EXT
140 hcache_init();
141 //#endif
142 memset((char *)counts, 0, sizeof(*counts));
143 for (i = 0; i < n_targets; ++i) {
144 TARGET *t = bindtarget(targets[i]);
145 make0(t, 0, 0, counts, anyhow);
147 if (DEBUG_MAKE) {
148 if (!is_make_silent()) {
149 if (counts->targets) printf("...found %d target%s...\n", counts->targets, multiFormSfx(counts->targets));
150 if (counts->temp) printf("...using %d temp target%s...\n", counts->temp, multiFormSfx(counts->temp));
151 if (counts->updating) printf("...updating %d target%s...\n", counts->updating, multiFormSfx(counts->updating));
153 if (counts->cantfind) printf("...can't find %d target%s...\n", counts->cantfind, multiFormSfx(counts->cantfind));
154 if (counts->cantmake) printf("...can't make %d target%s...\n", counts->cantmake, multiFormSfx(counts->cantmake));
156 //k8: don't write cache here, 'cause build directory can be created later; write cache in main jam function
157 //#ifdef OPT_HEADER_CACHE_EXT
158 //hcache_done();
159 //#endif
160 globs.updating = counts->updating; //k8
161 #ifndef __NEATCC__
162 globs.progress = progress_start(counts->updating);
163 #endif
164 status = counts->cantfind || counts->cantmake;
165 for (i = 0; i < n_targets; ++i) status |= make1(bindtarget(targets[i]));
166 return status;
171 * make0() - bind and scan everything to make a TARGET
173 * Make0() recursively binds a target, searches for #included headers,
174 * calls itself on those headers, and calls itself on any dependents.
176 static void make0 (
177 TARGET *t,
178 TARGET *p, /* parent */
179 int depth, /* for display purposes */
180 COUNTS *counts, /* for reporting */
181 int anyhow /* forcibly touch all (real) targets */
183 TARGETS *c, *incs;
184 TARGET *ptime = t;
185 time_t last, leaf, hlast;
186 int fate;
187 const char *flag = "";
188 SETTINGS *s;
190 /* step 1: initialize */
191 if (DEBUG_MAKEPROG) printf("make\t--\t%s%s\n", spaces(depth), t->name);
192 t->fate = T_FATE_MAKING;
193 /* step 2: under the influence of "on target" variables, bind the target and search for headers */
194 /* step 2a: set "on target" variables */
195 s = copysettings(t->settings);
196 pushsettings(s);
197 /* step 2b: find and timestamp the target file (if it's a file) */
198 if (t->binding == T_BIND_UNBOUND && !(t->flags & T_FLAG_NOTFILE)) {
199 t->boundname = search(t->name, &t->time);
200 t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
202 /* INTERNAL, NOTFILE header nodes have the time of their parents */
203 if (p && t->flags & T_FLAG_INTERNAL) ptime = p;
204 /* if temp file doesn't exist but parent does, use parent */
205 if (p && t->flags & T_FLAG_TEMP && t->binding == T_BIND_MISSING && p->binding != T_BIND_MISSING) {
206 t->binding = T_BIND_PARENTS;
207 ptime = p;
209 #ifdef JAM_OPT_SEMAPHORE
211 LIST *var = var_get("JAM_SEMAPHORE");
212 if (var) {
213 TARGET *semaphore = bindtarget(var->string);
214 semaphore->progress = T_MAKE_SEMAPHORE;
215 t->semaphore = semaphore;
218 #endif
219 /* step 2c: If its a file, search for headers */
220 if (t->binding == T_BIND_EXISTS) headers(t);
221 /* step 2d: reset "on target" variables */
222 popsettings(s);
223 freesettings(s);
224 /* pause for a little progress reporting */
225 if (DEBUG_MAKEPROG) {
226 if (strcmp(t->name, t->boundname)) {
227 printf("bind\t--\t%s%s: %s\n", spaces(depth), t->name, t->boundname);
229 switch (t->binding) {
230 case T_BIND_UNBOUND: case T_BIND_MISSING: case T_BIND_PARENTS:
231 printf("time\t--\t%s%s: %s\n", spaces(depth), t->name, target_bind[ (int)t->binding ]);
232 break;
233 case T_BIND_EXISTS:
234 printf("time\t--\t%s%s: %s", spaces(depth), t->name, ctime(&t->time));
235 break;
238 /* step 3: recursively make0() dependents & headers */
239 /* step 3a: recursively make0() dependents */
240 for (c = t->depends; c; c = c->next) {
241 int internal = t->flags & T_FLAG_INTERNAL;
243 if (DEBUG_DEPENDS) printf("%s \"%s\" : \"%s\" ;\n", internal?"Includes":"Depends", t->name, c->target->name);
244 /* warn about circular deps, except for includes, which include each other alot */
245 if (c->target->fate == T_FATE_INIT) make0(c->target, ptime, depth+1, counts, anyhow);
246 else if (c->target->fate == T_FATE_MAKING && !internal) printf("warning: %s depends on itself\n", c->target->name);
248 /* step 3b: recursively make0() internal includes node */
249 if (t->includes) make0(t->includes, p, depth+1, counts, anyhow);
250 /* step 3c: add dependents' includes to our direct dependencies */
251 incs = 0;
252 for (c = t->depends; c; c = c->next) {
253 if (c->target->includes) {
254 incs = targetentry(incs, c->target->includes);
255 /* if the includes are newer than we are their original target also needs to be marked newer */
256 /* this is needed so that 'updated' correctly will include the original target in the $(<) variable */
257 if (c->target->includes->time > t->time) c->target->fate = max(T_FATE_NEWER, c->target->fate);
260 t->depends = targetchain(t->depends, incs);
261 /* step 4: compute time & fate */
262 /* step 4a: pick up dependents' time and fate */
263 last = 0;
264 leaf = 0;
265 fate = T_FATE_STABLE;
266 for (c = t->depends; c; c = c->next) {
267 /* if LEAVES has been applied, we only heed the timestamps of the leaf source nodes */
268 leaf = max(leaf, c->target->leaf);
269 if (t->flags & T_FLAG_LEAVES) { last = leaf; continue; }
270 last = max(last, c->target->time);
271 fate = max(fate, c->target->fate);
273 /* step 4b: pick up included headers time */
274 /* if a header is newer than a temp source that includes it, the temp source will need building */
275 hlast = t->includes ? t->includes->time : 0;
276 /* step 4c: handle NOUPDATE oddity */
277 /* If a NOUPDATE file exists, make dependents eternally old */
278 /* don't inherit our fate from our dependents */
279 /* decide fate based only upon other flags and our binding (done later) */
280 if (t->flags & T_FLAG_NOUPDATE) {
281 last = 0;
282 t->time = 0;
283 fate = T_FATE_STABLE;
285 /* step 4d: determine fate: rebuild target or what? */
287 * In English:
288 * If can't find or make child, can't make target.
289 * If children changed, make target.
290 * If target missing, make it.
291 * If children newer, make target.
292 * If temp's children newer than parent, make temp.
293 * If temp's headers newer than parent, make temp.
294 * If deliberately touched, make it.
295 * If up-to-date temp file present, use it.
296 * If target newer than non-notfile parent, mark target newer.
297 * Otherwise, stable!
299 * Note this block runs from least to most stable:
300 * as we make it further down the list, the target's
301 * fate is getting stabler.
303 if (fate >= T_FATE_BROKEN) {
304 fate = T_FATE_CANTMAKE;
305 } else if (fate >= T_FATE_SPOIL) {
306 fate = T_FATE_UPDATE;
307 } else if (t->binding == T_BIND_MISSING) {
308 fate = T_FATE_MISSING;
309 } else if (t->binding == T_BIND_EXISTS && last > t->time) {
310 fate = T_FATE_OUTDATED;
311 } else if (t->binding == T_BIND_PARENTS && last > p->time) {
312 fate = T_FATE_NEEDTMP;
313 } else if (t->binding == T_BIND_PARENTS && hlast > p->time) {
314 fate = T_FATE_NEEDTMP;
315 } else if (t->flags & T_FLAG_TOUCHED) {
316 fate = T_FATE_TOUCHED;
317 } else if (anyhow && !(t->flags & T_FLAG_NOUPDATE)) {
318 fate = T_FATE_TOUCHED;
319 } else if (t->binding == T_BIND_EXISTS && t->flags & T_FLAG_TEMP) {
320 fate = T_FATE_ISTMP;
321 } else if (t->binding == T_BIND_EXISTS && p && p->binding != T_BIND_UNBOUND && t->time > p->time) {
322 fate = T_FATE_NEWER;
323 } else {
324 fate = T_FATE_STABLE;
326 /* step 4e: handle missing files */
327 /* if it's missing and there are no actions to create it, boom */
328 /* if we can't make a target we don't care about, 'sokay */
329 /* we could insist that there are updating actions for all missing
330 * files, but if they have dependents we just pretend it's NOTFILE */
331 if (fate == T_FATE_MISSING && !t->actions && !t->depends) {
332 if (t->flags & T_FLAG_NOCARE) {
333 fate = T_FATE_STABLE;
334 } else {
335 printf("don't know how to make %s\n", t->name);
336 fate = T_FATE_CANTFIND;
339 /* step 4f: propagate dependents' time & fate */
340 /* set leaf time to be our time only if this is a leaf */
341 t->time = max(t->time, last);
342 t->leaf = leaf?leaf:t->time;
343 t->fate = fate;
344 /* step 5: sort dependents by their update time */
345 if (globs.newestfirst) t->depends = make0sort(t->depends);
346 /* step 6: a little harmless tabulating for tracing purposes */
347 /* don't count or report interal includes nodes */
348 if (t->flags & T_FLAG_INTERNAL) return;
349 ++counts->targets;
350 if (counts->targets%4096 == 0 && DEBUG_MAKE) printf("...patience...\n");
352 if (fate == T_FATE_ISTMP) ++counts->temp;
353 else if (fate == T_FATE_CANTFIND) ++counts->cantfind;
354 else if (fate == T_FATE_CANTMAKE && t->actions) ++counts->cantmake;
355 else if (fate >= T_FATE_BUILD && fate < T_FATE_BROKEN && t->actions) ++counts->updating;
357 if (!(t->flags & T_FLAG_NOTFILE) && fate >= T_FATE_SPOIL) flag = "+";
358 else if (t->binding == T_BIND_EXISTS && p && t->time > p->time) flag = "*";
360 if (DEBUG_MAKEPROG) printf("made%s\t%s\t%s%s\n", flag, target_fate[(int)t->fate], spaces(depth), t->name);
361 if (DEBUG_CAUSES && t->fate >= T_FATE_NEWER && t->fate <= T_FATE_MISSING) {
362 printf("%s %s\n", target_fate[(int)t->fate], t->name);
368 * make0sort() - reorder TARGETS chain by their time (newest to oldest)
370 static TARGETS *make0sort (TARGETS *chain) {
371 TARGETS *result = 0;
372 /* we walk chain, taking each item and inserting it on the
373 * sorted result, with newest items at the front */
374 /* this involves updating each TARGETS' c->next and c->tail */
375 /* note that we make c->tail a valid prev pointer for every entry */
376 /* normally, it is only valid at the head, where prev == tail */
377 /* note also that while tail is a loop, next ends at the end of the chain */
378 /* walk current target list */
379 while (chain) {
380 TARGETS *c = chain, *s = result;
382 chain = chain->next;
383 /* find point s in result for c */
384 while (s && s->target->time > c->target->time) s = s->next;
385 /* insert c in front of s (might be 0) */
386 /* don't even think of deciphering this */
387 c->next = s; /* good even if s = 0 */
388 if (result == s) result = c; /* new head of chain? */
389 if (!s) s = result; /* wrap to ensure a next */
390 if (result != c) s->tail->next = c; /* not head? be prev's next */
391 c->tail = s->tail; /* take on next's prev */
392 s->tail = c; /* make next's prev us */
394 return result;