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
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.
30 * make() - make a target, given its name
33 * make0() - bind and scan everything to make a TARGET
34 * make0sort() - reorder TARGETS chain by their time (newest to oldest)
50 //#ifdef OPT_IMPROVED_PROGRESS_EXT
55 # define max(a,b) ((a)>(b)?(a):(b))
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
[] = {
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
) {
120 int status
= 0; /* 1 if anything fails */
121 //#ifdef OPT_HEADER_CACHE_EXT
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
);
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
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
]));
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.
158 TARGET
*p
, /* parent */
159 int depth
, /* for display purposes */
160 COUNTS
*counts
, /* for reporting */
161 int anyhow
/* forcibly touch all (real) targets */
165 time_t last
, leaf
, hlast
;
167 const char *flag
= "";
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
);
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
;
188 #ifdef JAM_OPT_SEMAPHORE
190 LIST
*var
= var_get("JAM_SEMAPHORE");
192 TARGET
*semaphore
= bindtarget(var
->string
);
193 semaphore
->progress
= T_MAKE_SEMAPHORE
;
194 t
->semaphore
= semaphore
;
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 */
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
]);
213 printf("time\t--\t%s%s: %s", spaces(depth
), t
->name
, ctime(&t
->time
));
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 */
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 */
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
) {
264 fate
= T_FATE_STABLE
;
266 /* step 4d: determine fate: rebuild target or what? */
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.
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
)) {
302 } else if (t
->binding
== T_BIND_EXISTS
&& p
&& p
->binding
!= T_BIND_UNBOUND
&& t
->time
> p
->time
) {
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
;
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
;
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;
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
) {
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 */
361 TARGETS
*c
= chain
, *s
= result
;
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 */