option.c: fixed warnings
[k8jam.git] / src / make.c
blob259ee04ad4ee0f49597954937fb73a7fe17d6b19
1 /*
2 * Copyright 1993, 1995 Christopher Seiwald.
3 * This file is part of Jam - see jam.c for Copyright information.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * make.c - bring a target up to date, once rules are in place
20 * This modules controls the execution of rules to bring a target and
21 * its dependencies up to date. It is invoked after the targets, rules,
22 * et. al. described in rules.h are created by the interpreting of the
23 * jam files.
25 * This file contains the main make() entry point and the first pass
26 * make0(). The second pass, make1(), which actually does the command
27 * execution, is in make1.c.
29 * External routines:
30 * make() - make a target, given its name
32 * Internal routines:
33 * make0() - bind and scan everything to make a TARGET
34 * make0sort() - reorder TARGETS chain by their time (newest to oldest)
36 #include "jam.h"
38 #include "lists.h"
39 #include "parse.h"
40 #include "variable.h"
41 #include "rules.h"
43 #include "search.h"
44 #include "newstr.h"
45 #include "make.h"
46 #include "hcache.h"
47 #include "headers.h"
48 #include "command.h"
50 //#ifdef OPT_IMPROVED_PROGRESS_EXT
51 #include "progress.h"
52 //#endif
54 #ifndef max
55 # define max(a,b) ((a)>(b)?(a):(b))
56 #endif
59 typedef struct {
60 int temp;
61 int updating;
62 int cantfind;
63 int cantmake;
64 int targets;
65 int made;
66 } COUNTS;
69 static void make0 (TARGET *t, TARGET *p, int depth, COUNTS *counts, int anyhow);
72 static TARGETS *make0sort (TARGETS *c);
75 static const char *target_fate[] = {
76 "init", /* T_FATE_INIT */
77 "making", /* T_FATE_MAKING */
78 "stable", /* T_FATE_STABLE */
79 "newer", /* T_FATE_NEWER */
80 "temp", /* T_FATE_ISTMP */
81 "touched", /* T_FATE_TOUCHED */
82 "missing", /* T_FATE_MISSING */
83 "needtmp", /* T_FATE_NEEDTMP */
84 "old", /* T_FATE_OUTDATED */
85 "update", /* T_FATE_UPDATE */
86 "nofind", /* T_FATE_CANTFIND */
87 "nomake" /* T_FATE_CANTMAKE */
91 static const char *target_bind[] = {
92 "unbound",
93 "missing",
94 "parents",
95 "exists",
98 #define spaces(x) (" "+16-((x) > 16 ? 16 : (x)))
102 * Return 'silent make' flag
104 int is_make_silent (void) {
105 LIST *var = var_get("JAM_OPTION_MAKE_UPDATES_SILENT");
106 return (var && var->string &&
107 strcmp(var->string, "ona") != 0 &&
108 strcmp(var->string, "no") != 0 &&
109 strcmp(var->string, "false") != 0 &&
110 strcmp(var->string, "0") != 0);
115 * make() - make a target, given its name
117 int make (int n_targets, const char **targets, int anyhow) {
118 int i;
119 COUNTS counts[1];
120 int status = 0; /* 1 if anything fails */
121 //#ifdef OPT_HEADER_CACHE_EXT
122 hcache_init();
123 //#endif
124 memset((char *)counts, 0, sizeof(*counts));
125 for (i = 0; i < n_targets; ++i) {
126 TARGET *t = bindtarget(targets[i]);
127 make0(t, 0, 0, counts, anyhow);
129 if (DEBUG_MAKE) {
130 if (!is_make_silent()) {
131 if (counts->targets) printf("...found %d target%s...\n", counts->targets, multiform_suffix(counts->targets));
132 if (counts->temp) printf("...using %d temp target%s...\n", counts->temp, multiform_suffix(counts->temp));
133 if (counts->updating) printf("...updating %d target%s...\n", counts->updating, multiform_suffix(counts->updating));
135 if (counts->cantfind) printf("...can't find %d target%s...\n", counts->cantfind, multiform_suffix(counts->cantfind));
136 if (counts->cantmake) printf("...can't make %d target%s...\n", counts->cantmake, multiform_suffix(counts->cantmake));
138 //k8: don't write cache here, 'cause build directory can be created later; write cache in main jam function
139 //#ifdef OPT_HEADER_CACHE_EXT
140 //hcache_done();
141 //#endif
142 globs.updating = counts->updating; //k8
143 globs.progress = progress_start(counts->updating);
144 status = counts->cantfind || counts->cantmake;
145 for (i = 0; i < n_targets; ++i) status |= make1(bindtarget(targets[i]));
146 return status;
151 * make0() - bind and scan everything to make a TARGET
153 * Make0() recursively binds a target, searches for #included headers,
154 * calls itself on those headers, and calls itself on any dependents.
156 static void make0 (
157 TARGET *t,
158 TARGET *p, /* parent */
159 int depth, /* for display purposes */
160 COUNTS *counts, /* for reporting */
161 int anyhow /* forcibly touch all (real) targets */
163 TARGETS *c, *incs;
164 TARGET *ptime = t;
165 time_t last, leaf, hlast;
166 int fate;
167 const char *flag = "";
168 SETTINGS *s;
169 /* step 1: initialize */
170 if (DEBUG_MAKEPROG) printf("make\t--\t%s%s\n", spaces(depth), t->name);
171 t->fate = T_FATE_MAKING;
172 /* step 2: under the influence of "on target" variables, bind the target and search for headers */
173 /* step 2a: set "on target" variables */
174 s = copysettings(t->settings);
175 pushsettings(s);
176 /* step 2b: find and timestamp the target file (if it's a file) */
177 if (t->binding == T_BIND_UNBOUND && !(t->flags&T_FLAG_NOTFILE)) {
178 t->boundname = search(t->name, &t->time);
179 t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
181 /* INTERNAL, NOTFILE header nodes have the time of their parents */
182 if (p && t->flags&T_FLAG_INTERNAL) ptime = p;
183 /* if temp file doesn't exist but parent does, use parent */
184 if (p && t->flags&T_FLAG_TEMP && t->binding == T_BIND_MISSING && p->binding != T_BIND_MISSING) {
185 t->binding = T_BIND_PARENTS;
186 ptime = p;
188 #ifdef JAM_OPT_SEMAPHORE
190 LIST *var = var_get("JAM_SEMAPHORE");
191 if (var) {
192 TARGET *semaphore = bindtarget(var->string);
193 semaphore->progress = T_MAKE_SEMAPHORE;
194 t->semaphore = semaphore;
197 #endif
198 /* step 2c: If its a file, search for headers */
199 if (t->binding == T_BIND_EXISTS) headers(t);
200 /* step 2d: reset "on target" variables */
201 popsettings(s);
202 freesettings(s);
203 /* pause for a little progress reporting */
204 if (DEBUG_MAKEPROG) {
205 if (strcmp(t->name, t->boundname)) {
206 printf("bind\t--\t%s%s: %s\n", spaces(depth), t->name, t->boundname);
208 switch (t->binding) {
209 case T_BIND_UNBOUND: case T_BIND_MISSING: case T_BIND_PARENTS:
210 printf("time\t--\t%s%s: %s\n", spaces(depth), t->name, target_bind[ (int)t->binding ]);
211 break;
212 case T_BIND_EXISTS:
213 printf("time\t--\t%s%s: %s", spaces(depth), t->name, ctime(&t->time));
214 break;
217 /* step 3: recursively make0() dependents & headers */
218 /* step 3a: recursively make0() dependents */
219 for (c = t->depends; c; c = c->next) {
220 int internal = t->flags&T_FLAG_INTERNAL;
221 if (DEBUG_DEPENDS) printf("%s \"%s\" : \"%s\" ;\n", internal?"Includes":"Depends", t->name, c->target->name);
222 /* warn about circular deps, except for includes, which include each other alot */
223 if (c->target->fate == T_FATE_INIT) make0(c->target, ptime, depth+1, counts, anyhow);
224 else if (c->target->fate == T_FATE_MAKING && !internal) printf("warning: %s depends on itself\n", c->target->name);
226 /* step 3b: recursively make0() internal includes node */
227 if (t->includes) make0(t->includes, p, depth+1, counts, anyhow);
228 /* step 3c: add dependents' includes to our direct dependencies */
229 incs = 0;
230 for (c = t->depends; c; c = c->next) {
231 if (c->target->includes) {
232 incs = targetentry(incs, c->target->includes);
233 /* if the includes are newer than we are their original target also needs to be marked newer */
234 /* this is needed so that 'updated' correctly will include the original target in the $(<) variable */
235 if (c->target->includes->time > t->time) {
236 //if (DEBUG_DEPENDS) printf("TIME*\t--\t%s%s: %s :: %s\n", spaces(depth), t->name, ctime(&t->time), ctime(&c->target->includes->time));
237 c->target->fate = max(T_FATE_NEWER, c->target->fate);
241 t->depends = targetchain(t->depends, incs);
242 /* step 4: compute time & fate */
243 /* step 4a: pick up dependents' time and fate */
244 last = 0;
245 leaf = 0;
246 fate = T_FATE_STABLE;
247 for (c = t->depends; c; c = c->next) {
248 /* if LEAVES has been applied, we only heed the timestamps of the leaf source nodes */
249 leaf = max(leaf, c->target->leaf);
250 if (t->flags&T_FLAG_LEAVES) { last = leaf; continue; }
251 last = max(last, c->target->time);
252 fate = max(fate, c->target->fate);
254 /* step 4b: pick up included headers time */
255 /* if a header is newer than a temp source that includes it, the temp source will need building */
256 hlast = t->includes ? t->includes->time : 0;
257 /* step 4c: handle NOUPDATE oddity */
258 /* If a NOUPDATE file exists, make dependents eternally old */
259 /* don't inherit our fate from our dependents */
260 /* decide fate based only upon other flags and our binding (done later) */
261 if (t->flags&T_FLAG_NOUPDATE) {
262 last = 0;
263 t->time = 0;
264 fate = T_FATE_STABLE;
266 /* step 4d: determine fate: rebuild target or what? */
268 * In English:
269 * If can't find or make child, can't make target.
270 * If children changed, make target.
271 * If target missing, make it.
272 * If children newer, make target.
273 * If temp's children newer than parent, make temp.
274 * If temp's headers newer than parent, make temp.
275 * If deliberately touched, make it.
276 * If up-to-date temp file present, use it.
277 * If target newer than non-notfile parent, mark target newer.
278 * Otherwise, stable!
280 * Note this block runs from least to most stable:
281 * as we make it further down the list, the target's
282 * fate is getting stabler.
284 if (fate >= T_FATE_BROKEN) {
285 fate = T_FATE_CANTMAKE;
286 } else if (fate >= T_FATE_SPOIL) {
287 fate = T_FATE_UPDATE;
288 } else if (t->binding == T_BIND_MISSING) {
289 fate = T_FATE_MISSING;
290 } else if (t->binding == T_BIND_EXISTS && last > t->time) {
291 fate = T_FATE_OUTDATED;
292 } else if (t->binding == T_BIND_PARENTS && last > p->time) {
293 fate = T_FATE_NEEDTMP;
294 } else if (t->binding == T_BIND_PARENTS && hlast > p->time) {
295 fate = T_FATE_NEEDTMP;
296 } else if (t->flags&T_FLAG_TOUCHED) {
297 fate = T_FATE_TOUCHED;
298 } else if (anyhow && !(t->flags&T_FLAG_NOUPDATE)) {
299 fate = T_FATE_TOUCHED;
300 } else if (t->binding == T_BIND_EXISTS && (t->flags&T_FLAG_TEMP)) {
301 fate = T_FATE_ISTMP;
302 } else if (t->binding == T_BIND_EXISTS && p && p->binding != T_BIND_UNBOUND && t->time > p->time) {
303 fate = T_FATE_NEWER;
304 } else {
305 fate = T_FATE_STABLE;
307 /* step 4e: handle missing files */
308 /* if it's missing and there are no actions to create it, boom */
309 /* if we can't make a target we don't care about, 'sokay */
310 /* we could insist that there are updating actions for all missing
311 * files, but if they have dependents we just pretend it's NOTFILE */
312 if (fate == T_FATE_MISSING && !t->actions && !t->depends) {
313 if (t->flags&T_FLAG_NOCARE) {
314 fate = T_FATE_STABLE;
315 } else {
316 printf("don't know how to make %s\n", t->name);
317 fate = T_FATE_CANTFIND;
320 /* step 4f: propagate dependents' time & fate */
321 /* set leaf time to be our time only if this is a leaf */
322 t->time = max(t->time, last);
323 t->leaf = leaf?leaf:t->time;
324 t->fate = fate;
325 /* step 5: sort dependents by their update time */
326 if (globs.newestfirst) t->depends = make0sort(t->depends);
327 /* step 6: a little harmless tabulating for tracing purposes */
328 /* don't count or report interal includes nodes */
329 if (t->flags&T_FLAG_INTERNAL) return;
330 ++counts->targets;
331 if (counts->targets%4096 == 0 && DEBUG_MAKE) printf("...patience...\n");
333 if (fate == T_FATE_ISTMP) ++counts->temp;
334 else if (fate == T_FATE_CANTFIND) ++counts->cantfind;
335 else if (fate == T_FATE_CANTMAKE && t->actions) ++counts->cantmake;
336 else if (fate >= T_FATE_BUILD && fate < T_FATE_BROKEN && t->actions) ++counts->updating;
338 if (!(t->flags&T_FLAG_NOTFILE) && fate >= T_FATE_SPOIL) flag = "+";
339 else if (t->binding == T_BIND_EXISTS && p && t->time > p->time) flag = "*";
341 if (DEBUG_MAKEPROG) printf("made%s\t%s\t%s%s\n", flag, target_fate[(int)t->fate], spaces(depth), t->name);
342 if (DEBUG_CAUSES && t->fate >= T_FATE_NEWER && t->fate <= T_FATE_MISSING) {
343 printf("%s %s\n", target_fate[(int)t->fate], t->name);
349 * make0sort() - reorder TARGETS chain by their time (newest to oldest)
351 static TARGETS *make0sort (TARGETS *chain) {
352 TARGETS *result = 0;
353 /* we walk chain, taking each item and inserting it on the
354 * sorted result, with newest items at the front */
355 /* this involves updating each TARGETS' c->next and c->tail */
356 /* note that we make c->tail a valid prev pointer for every entry */
357 /* normally, it is only valid at the head, where prev == tail */
358 /* note also that while tail is a loop, next ends at the end of the chain */
359 /* walk current target list */
360 while (chain) {
361 TARGETS *c = chain, *s = result;
362 chain = chain->next;
363 /* find point s in result for c */
364 while (s && s->target->time > c->target->time) s = s->next;
365 /* insert c in front of s (might be 0) */
366 /* don't even think of deciphering this */
367 c->next = s; /* good even if s = 0 */
368 if (result == s) result = c; /* new head of chain? */
369 if (!s) s = result; /* wrap to ensure a next */
370 if (result != c) s->tail->next = c; /* not head? be prev's next */
371 c->tail = s->tail; /* take on next's prev */
372 s->tail = c; /* make next's prev us */
374 return result;