2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
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, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * make1.c - execute command to bring targets up to date
21 * This module contains make1(), the entry point called by make() to
22 * recursively decend the dependency graph executing update actions as
27 * make1() - execute commands to update a TARGET and all its dependents
29 * Internal routines, the recursive/asynchronous command executors:
31 * make1a() - recursively traverse target tree, calling make1b()
32 * make1b() - dependents of target built, now build target with make1c()
33 * make1c() - launch target's next command, call make1b() when done
34 * make1d() - handle command execution completion and call back make1c()
36 * Internal support routines:
38 * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc
39 * make1list() - turn a list of targets into a LIST, for $(<) and $(>)
40 * make1settings() - for vars that get bound, build up replacement lists
41 * make1bind() - bind targets that weren't bound in dependency analysis
58 //#ifdef OPT_IMPROVED_PROGRESS_EXT
63 static void make1a (TARGET
*t
, TARGET
*parent
);
64 static void make1b (TARGET
*t
);
65 static void make1c (TARGET
*t
);
66 static void make1d (void *closure
, int status
);
68 static CMD
*make1cmds (ACTIONS
*a0
);
69 static LIST
*make1list (LIST
*l
, TARGETS
*targets
, int flags
);
70 static SETTINGS
*make1settings (LIST
*vars
);
71 static void make1bind (TARGET
*t
, int warn
);
74 /* Ugly static - it's too hard to carry it through the callbacks. */
84 * make1() - execute commands to update a TARGET and all its dependents
89 int make1 (TARGET
*t
) {
90 memset((char *)counts
, 0, sizeof(*counts
));
91 /* recursively make the target and its dependents */
92 make1a(t
, (TARGET
*)0);
93 /* wait for any outstanding commands to finish running */
96 if (DEBUG_MAKE
&& counts
->failed
) printf("...failed updating %d target%s...\n", counts
->failed
, multiform_suffix(counts
->failed
));
97 if (DEBUG_MAKE
&& counts
->skipped
) printf("...skipped %d target%s...\n", counts
->skipped
, multiform_suffix(counts
->skipped
));
98 if (DEBUG_MAKE
&& counts
->made
&& !is_make_silent()) printf("...updated %d target%s...\n", counts
->made
, multiform_suffix(counts
->made
));
99 return counts
->total
!= counts
->made
;
104 * make1a() - recursively traverse target tree, calling make1b()
106 static void make1a (TARGET
*t
, TARGET
*parent
) {
108 /* if the parent is the first to try to build this target */
109 /* or this target is in the make1c() quagmire, arrange for the */
110 /* parent to be notified when this target is built */
112 switch (t
->progress
) {
116 t
->parents
= targetentry(t
->parents
, parent
);
121 if (t
->progress
!= T_MAKE_INIT
) return;
122 /* asynccnt counts the dependents preventing this target from proceeding to make1b() for actual building */
123 /* we start off with a count of 1 to prevent anything from happening until we can call all dependents */
124 /* this 1 is accounted for when we call make1b() ourselves, below */
126 /* recurse on our dependents, manipulating progress to guard against circular dependency */
127 t
->progress
= T_MAKE_ONSTACK
;
128 for (c
= t
->depends
; c
&& !intr
; c
= c
->next
) make1a(c
->target
, t
);
129 t
->progress
= T_MAKE_ACTIVE
;
130 /* now that all dependents have bumped asynccnt, we now allow decrement our reference to asynccnt */
136 * make1b() - dependents of target built, now build target with make1c()
138 static void make1b (TARGET
*t
) {
140 const char *failed
= "dependents";
141 /* if any dependents are still outstanding, wait until they call make1b() to signal their completion */
142 if (--t
->asynccnt
) return;
143 #ifdef JAM_OPT_SEMAPHORE
144 /* try to aquire a semaphore. If it is locked, wait until the target that locked it is built and signal completition */
145 if (t
->semaphore
&& t
->semaphore
->asynccnt
) {
146 /* append 't' to the list of targets waiting on semaphore. */
147 t
->semaphore
->parents
= targetentry(t
->semaphore
->parents
, t
);
149 if (DEBUG_EXECCMD
) printf("SEM: %s is busy, delaying launch of %s\n", t
->semaphore
->name
, t
->name
);
150 //pop_state(&state_stack);
154 /* now ready to build target 't'... if dependents built ok */
155 /* collect status from dependents */
156 for (c
= t
->depends
; c
; c
= c
->next
) {
157 if (c
->target
->status
> t
->status
) {
158 failed
= c
->target
->name
;
159 t
->status
= c
->target
->status
;
162 /* if actions on deps have failed, bail, otherwise, execute all actions to make target */
163 if (t
->status
== EXEC_CMD_FAIL
&& t
->actions
) {
165 printf("...skipped %s for lack of %s...\n", t
->name
, failed
);
167 if (t
->status
== EXEC_CMD_OK
) {
171 /* shouldn't happen */
175 case T_FATE_CANTFIND
:
176 case T_FATE_CANTMAKE
:
177 t
->status
= EXEC_CMD_FAIL
;
180 if (DEBUG_MAKEQ
) printf("...using %s...\n", t
->name
);
185 case T_FATE_OUTDATED
:
187 /* set "on target" vars, build actions, unset vars */
188 /* set "progress" so that make1c() counts this target among the successes/failures. */
191 //if (DEBUG_MAKE && !(counts->total % 100)) printf("...on %dth target...\n", counts->total);
193 double est_remaining
= progress_update(globs
.progress
, counts
->total
);
194 if (est_remaining
> 0.0) {
195 int minutes
= (int)est_remaining
/60;
196 int seconds
= (int)est_remaining
%60;
197 if (minutes
> 0 || seconds
> 0) {
198 printf("*** completed %.0f%% (", ((double)counts
->total
*100/globs
.updating
));
199 if (minutes
> 0) printf("%d min ", minutes
);
200 if (seconds
>= 0) printf("%d sec ", seconds
);
201 printf("remaining)...\n");
205 pushsettings(t
->settings
);
206 t
->cmds
= (char *)make1cmds(t
->actions
);
207 popsettings(t
->settings
);
208 t
->progress
= T_MAKE_RUNNING
;
213 /* call make1c() to begin the execution of the chain of commands needed to build target */
214 /* if we're not going to build target (because of dependency failures or because no commands
215 * need to be run) the chain will be empty and make1c() will directly
216 * signal the completion of target */
217 #ifdef JAM_OPT_SEMAPHORE
218 /* if there is a semaphore, indicate that it is in use */
220 ++t
->semaphore
->asynccnt
;
221 if (DEBUG_EXECCMD
) printf( "SEM: %s now used by %s\n", t
->semaphore
->name
, t
->name
);
224 make1c(t
); //pState->curstate = T_STATE_MAKE1C;
229 * make1c() - launch target's next command, call make1b() when done
231 static void make1c (TARGET
*t
) {
232 CMD
*cmd
= (CMD
*)t
->cmds
;
233 /* if there are (more) commands to run to build this target
234 * (and we haven't hit an error running earlier comands) we
235 * launch the command with execcmd() */
236 /* if there are no more commands to run, we collect the status
237 * from all the actions then report our completion to all the
239 if (cmd
&& t
->status
== EXEC_CMD_OK
) {
241 if (DEBUG_MAKEQ
|| !(cmd
->rule
->flags
&RULE_QUIETLY
)) {
242 printf("(%3d%%) ", counts
->total
*100/globs
.updating
);
243 printf("%s ", cmd
->rule
->name
);
244 list_print_ex(stdout
, lol_get(&cmd
->args
, 0), LPFLAG_NO_TRSPACE
);
248 if (DEBUG_EXEC
) printf("%s\n", dstr_cstr(&cmd
->buf
));
249 if (globs
.cmdout
) fprintf(globs
.cmdout
, "%s", dstr_cstr(&cmd
->buf
));
250 if (globs
.noexec
) make1d(t
, EXEC_CMD_OK
);
253 execcmd(dstr_cstr(&cmd
->buf
), make1d
, t
, cmd
->shell
);
258 /* collect status from actions, and distribute it as well */
259 for (actions
= t
->actions
; actions
; actions
= actions
->next
) {
260 if (actions
->action
->status
> t
->status
) t
->status
= actions
->action
->status
;
262 for (actions
= t
->actions
; actions
; actions
= actions
->next
) {
263 if (t
->status
> actions
->action
->status
) actions
->action
->status
= t
->status
;
265 /* tally success/failure for those we tried to update */
266 if (t
->progress
== T_MAKE_RUNNING
) {
268 case EXEC_CMD_OK
: ++counts
->made
; break;
269 case EXEC_CMD_FAIL
: ++counts
->failed
; break;
272 /* tell parents dependent has been built */
273 t
->progress
= T_MAKE_DONE
;
274 for (c
= t
->parents
; c
; c
= c
->next
) make1b(c
->target
);
275 #ifdef JAM_OPT_SEMAPHORE
276 /* if there is a semaphore, it is now free */
278 /*assert(t->semaphore->asynccnt == 1);*/
279 if (t
->semaphore
->asynccnt
!= 1) { fprintf(stderr
, "FATAL: internal error: t->semaphore->asynccnt != 1!\n"); abort(); }
280 --t
->semaphore
->asynccnt
;
281 if (DEBUG_EXECCMD
) printf( "SEM: %s is now free\n", t
->semaphore
->name
);
282 /* If anything is waiting, notify the next target */
283 /* there is no point in notifying waiting targets, since they will be notified again */
284 if (t
->semaphore
->parents
) {
285 TARGETS
*first
= t
->semaphore
->parents
;
286 if (first
->next
) first
->next
->tail
= first
->tail
;
287 t
->semaphore
->parents
= first
->next
;
288 if (DEBUG_EXECCMD
) printf( "SEM: placing %s on stack\n", first
->target
->name
);
289 //push_state(&temp_stack, first->target, NULL, T_STATE_MAKE1B);
290 /*k8: memory leak, but it's safe: free(first);*/
299 * make1d() - handle command execution completion and call back make1c()
301 static void make1d (void *closure
, int status
) {
302 TARGET
*t
= (TARGET
*)closure
;
303 CMD
*cmd
= (CMD
*)t
->cmds
;
304 /* execcmd() has completed */
305 /* all we need to do is fiddle with the status and signal our completion so make1c() can run the next command */
306 /* in interrupts, we bail heavily */
307 if (status
== EXEC_CMD_FAIL
&& (cmd
->rule
->flags
&RULE_IGNORE
)) status
= EXEC_CMD_OK
;
308 /* on interrupt, set intr so _everything_ fails */
309 if (status
== EXEC_CMD_INTR
) ++intr
;
310 if (status
== EXEC_CMD_FAIL
&& DEBUG_MAKE
) {
311 /* print command text on failure */
312 if (!DEBUG_EXEC
) printf("%s\n", dstr_cstr(&cmd
->buf
));
313 printf("...failed %s ", cmd
->rule
->name
);
314 list_print(lol_get(&cmd
->args
, 0));
316 if (globs
.quitquick
) ++intr
;
318 /* if the command was interrupted or failed and the target is not "precious", remove the targets */
319 /* precious == 'actions updated' -- the target maintains state */
320 if (status
!= EXEC_CMD_OK
&& !(cmd
->rule
->flags
&RULE_UPDATED
)) {
321 LIST
*targets
= lol_get(&cmd
->args
, 0);
322 for (; targets
; targets
= list_next(targets
)) {
323 if (!unlink(targets
->string
)) printf("...removing %s\n", targets
->string
);
326 /* free this command and call make1c() to move onto next command */
328 t
->cmds
= (char *)cmd_next(cmd
);
335 * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc
337 * Essentially copies a chain of ACTIONs to a chain of CMDs,
338 * grouping RULE_TOGETHER actions, splitting RULE_PIECEMEAL actions,
339 * and handling RULE_UPDATED actions. The result is a chain of
340 * CMDs which can be expanded by var_string() and executed with
343 static CMD
*make1cmds (ACTIONS
*a0
) {
345 LIST
*shell
= var_get("JAMSHELL"); /* shell is per-target */
346 /* step through actions */
347 /* actions may be shared with other targets or grouped with RULE_TOGETHER, so actions already seen are skipped */
348 for (; a0
; a0
= a0
->next
) {
349 RULE
*rule
= a0
->action
->rule
;
353 int start
, chunk
, length
, maxline
;
354 /* only do rules with commands to execute */
355 /* if this action has already been executed, use saved status */
356 if (!rule
->actions
|| a0
->action
->running
) continue;
357 a0
->action
->running
= 1;
358 /* make LISTS of targets and sources */
359 /* if `execute together` has been specified for this rule, tack
360 * on sources from each instance of this rule for this target */
361 nt
= make1list(L0
, a0
->action
->targets
, 0);
362 ns
= make1list(L0
, a0
->action
->sources
, rule
->flags
);
363 if (rule
->flags
&RULE_TOGETHER
) {
364 for (a1
= a0
->next
; a1
; a1
= a1
->next
) {
365 if (a1
->action
->rule
== rule
&& !a1
->action
->running
) {
366 ns
= make1list(ns
, a1
->action
->sources
, rule
->flags
);
367 a1
->action
->running
= 1;
371 /* if doing only updated (or existing) sources, but none have
372 * been updated (or exist), skip this action */
373 if (!ns
&& (rule
->flags
&(RULE_UPDATED
|RULE_EXISTING
))) {
377 /* if we had 'actions xxx bind vars' we bind the vars now */
378 boundvars
= make1settings(rule
->bindlist
);
379 pushsettings(boundvars
);
381 * Build command, starting with all source args.
383 * If cmd_new returns 0, it's because the resulting command
384 * length is > MAXLINE. In this case, we'll slowly reduce
385 * the number of source arguments presented until it does
386 * fit. This only applies to actions that allow PIECEMEAL
389 * While reducing slowly takes a bit of compute time to get
390 * things just right, it's worth it to get as close to MAXLINE
391 * as possible, because launching the commands we're executing
392 * is likely to be much more compute intensive!
394 * Note we loop through at least once, for sourceless actions.
396 * Max line length is the action specific maxline or, if not
397 * given or bigger than MAXLINE, MAXLINE.
400 chunk
= length
= list_length(ns
);
401 maxline
= (rule
->flags
&RULE_MAXLINE
? rule
->flags
>>8 : 0);
402 maxline
= (maxline
&& maxline
< MAXLINE
? maxline
: MAXLINE
);
404 /* build cmd: cmd_new consumes its lists */
405 CMD
*cmd
= cmd_new(rule
,
407 list_sublist(ns
, start
, chunk
),
408 list_copy(L0
, shell
),
411 /* it fit: chain it up */
412 if (!cmds
) cmds
= cmd
; else cmds
->tail
->next
= cmd
;
415 } else if ((rule
->flags
&RULE_PIECEMEAL
) && chunk
> 1) {
416 /* reduce chunk size slowly */
419 /* too long and not splittable */
420 printf("%s actions too long (max %d)!\n", rule
->name
, maxline
);
423 } while (start
< length
);
424 /* these were always copied when used */
427 /* free the variables whose values were bound by 'actions xxx bind vars' */
428 popsettings(boundvars
);
429 freesettings(boundvars
);
436 * make1list() - turn a list of targets into a LIST, for $(<) and $(>)
438 static LIST
*make1list (LIST
*l
, TARGETS
*targets
, int flags
) {
439 for (; targets
; targets
= targets
->next
) {
440 TARGET
*t
= targets
->target
;
441 /* sources to 'actions existing' are never in the dependency
442 * graph (if they were, they'd get built and 'existing' would
443 * be superfluous, so throttle warning message about independent
445 if (t
->binding
== T_BIND_UNBOUND
) make1bind(t
, !(flags
&RULE_EXISTING
));
446 if ((flags
&RULE_EXISTING
) && t
->binding
!= T_BIND_EXISTS
) continue;
447 if ((flags
&RULE_UPDATED
) && t
->fate
<= T_FATE_STABLE
) continue;
448 /* prohibit duplicates for RULE_TOGETHER */
449 if (flags
&RULE_TOGETHER
) {
452 for (m
= l
; m
; m
= m
->next
) if (!strcmp(m
->string
, t
->boundname
)) break;
456 l
= list_new(l
, t
->boundname
, 1);
463 * make1settings() - for vars that get bound values, build up replacement lists
465 static SETTINGS
*make1settings (LIST
*vars
) {
466 SETTINGS
*settings
= NULL
;
467 for (; vars
; vars
= list_next(vars
)) {
468 LIST
*l
= var_get(vars
->string
), *nl
= NULL
;
469 for (; l
; l
= list_next(l
)) {
470 TARGET
*t
= bindtarget(l
->string
);
471 /* make sure the target is bound, warning if it is not in the dependency graph */
472 if (t
->binding
== T_BIND_UNBOUND
) make1bind(t
, 1);
474 nl
= list_new(nl
, t
->boundname
, 1);
476 /* add to settings chain */
477 settings
= addsettings(settings
, 0, vars
->string
, nl
);
484 * make1bind() - bind targets that weren't bound in dependency analysis
486 * Spot the kludge! If a target is not in the dependency tree, it didn't
487 * get bound by make0(), so we have to do it here. Ugly.
489 static void make1bind (TARGET
*t
, int warn
) {
490 if (t
->flags
&T_FLAG_NOTFILE
) return;
491 /* sources to 'actions existing' are never in the dependency
492 * graph (if they were, they'd get built and 'existing' would
493 * be superfluous, so throttle warning message about independent
495 if (warn
) printf("warning: using independent target %s\n", t
->name
);
496 pushsettings(t
->settings
);
497 t
->boundname
= search(t
->name
, &t
->time
);
498 t
->binding
= t
->time
?T_BIND_EXISTS
:T_BIND_MISSING
;
499 popsettings(t
->settings
);