option.c: fixed warnings
[k8jam.git] / src / make1.c
blobd0f98a14d7115c5fb84c28589845ba401d8c89a2
1 /*
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, 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 * make1.c - execute command to bring targets up to date
20 * This module contains make1(), the entry point called by make() to
21 * recursively decend the dependency graph executing update actions as
22 * marked by make0().
24 * External routines:
26 * make1() - execute commands to update a TARGET and all its dependents
28 * Internal routines, the recursive/asynchronous command executors:
30 * make1a() - recursively traverse target tree, calling make1b()
31 * make1b() - dependents of target built, now build target with make1c()
32 * make1c() - launch target's next command, call make1b() when done
33 * make1d() - handle command execution completion and call back make1c()
35 * Internal support routines:
37 * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc
38 * make1list() - turn a list of targets into a LIST, for $(<) and $(>)
39 * make1settings() - for vars that get bound, build up replacement lists
40 * make1bind() - bind targets that weren't bound in dependency analysis
42 #include <unistd.h>
44 #include "jam.h"
46 #include "lists.h"
47 #include "parse.h"
48 #include "variable.h"
49 #include "rules.h"
51 #include "search.h"
52 #include "newstr.h"
53 #include "make.h"
54 #include "command.h"
55 #include "execcmd.h"
57 //#ifdef OPT_IMPROVED_PROGRESS_EXT
58 #include "progress.h"
59 //#endif
62 static void make1a (TARGET *t, TARGET *parent);
63 static void make1b (TARGET *t);
64 static void make1c (TARGET *t);
65 static void make1d (void *closure, int status);
67 static CMD *make1cmds (ACTIONS *a0);
68 static LIST *make1list (LIST *l, TARGETS *targets, int flags);
69 static SETTINGS *make1settings (LIST *vars);
70 static void make1bind (TARGET *t, int warn);
73 /* Ugly static - it's too hard to carry it through the callbacks. */
74 static struct {
75 int failed;
76 int skipped;
77 int total;
78 int made;
79 } counts[1];
83 * make1() - execute commands to update a TARGET and all its dependents
85 static int intr = 0;
88 int make1 (TARGET *t) {
89 memset((char *)counts, 0, sizeof(*counts));
90 /* recursively make the target and its dependents */
91 make1a(t, (TARGET *)0);
92 /* wait for any outstanding commands to finish running */
93 while (execwait()) ;
94 /* talk about it */
95 if (DEBUG_MAKE && counts->failed) printf("...failed updating %d target%s...\n", counts->failed, multiform_suffix(counts->failed));
96 if (DEBUG_MAKE && counts->skipped) printf("...skipped %d target%s...\n", counts->skipped, multiform_suffix(counts->skipped));
97 if (DEBUG_MAKE && counts->made && !is_make_silent()) printf("...updated %d target%s...\n", counts->made, multiform_suffix(counts->made));
98 return counts->total != counts->made;
103 * make1a() - recursively traverse target tree, calling make1b()
105 static void make1a (TARGET *t, TARGET *parent) {
106 TARGETS *c;
107 /* if the parent is the first to try to build this target */
108 /* or this target is in the make1c() quagmire, arrange for the */
109 /* parent to be notified when this target is built */
110 if (parent) {
111 switch (t->progress) {
112 case T_MAKE_INIT:
113 case T_MAKE_ACTIVE:
114 case T_MAKE_RUNNING:
115 t->parents = targetentry(t->parents, parent);
116 ++parent->asynccnt;
117 break;
120 if (t->progress != T_MAKE_INIT) return;
121 /* asynccnt counts the dependents preventing this target from proceeding to make1b() for actual building */
122 /* we start off with a count of 1 to prevent anything from happening until we can call all dependents */
123 /* this 1 is accounted for when we call make1b() ourselves, below */
124 t->asynccnt = 1;
125 /* recurse on our dependents, manipulating progress to guard against circular dependency */
126 t->progress = T_MAKE_ONSTACK;
127 for (c = t->depends; c && !intr; c = c->next) make1a(c->target, t);
128 t->progress = T_MAKE_ACTIVE;
129 /* now that all dependents have bumped asynccnt, we now allow decrement our reference to asynccnt */
130 make1b(t);
135 * make1b() - dependents of target built, now build target with make1c()
137 static void make1b (TARGET *t) {
138 TARGETS *c;
139 const char *failed = "dependents";
140 /* if any dependents are still outstanding, wait until they call make1b() to signal their completion */
141 if (--t->asynccnt) return;
142 #ifdef JAM_OPT_SEMAPHORE
143 /* try to aquire a semaphore. If it is locked, wait until the target that locked it is built and signal completition */
144 if (t->semaphore && t->semaphore->asynccnt) {
145 /* append 't' to the list of targets waiting on semaphore. */
146 t->semaphore->parents = targetentry(t->semaphore->parents, t);
147 ++t->asynccnt;
148 if (DEBUG_EXECCMD) printf("SEM: %s is busy, delaying launch of %s\n", t->semaphore->name, t->name);
149 //pop_state(&state_stack);
150 return;
152 #endif
153 /* now ready to build target 't'... if dependents built ok */
154 /* collect status from dependents */
155 for (c = t->depends; c; c = c->next) {
156 if (c->target->status > t->status) {
157 failed = c->target->name;
158 t->status = c->target->status;
161 /* if actions on deps have failed, bail, otherwise, execute all actions to make target */
162 if (t->status == EXEC_CMD_FAIL && t->actions) {
163 ++counts->skipped;
164 printf("...skipped %s for lack of %s...\n", t->name, failed);
166 if (t->status == EXEC_CMD_OK) {
167 switch(t->fate) {
168 case T_FATE_INIT:
169 case T_FATE_MAKING:
170 /* shouldn't happen */
171 case T_FATE_STABLE:
172 case T_FATE_NEWER:
173 break;
174 case T_FATE_CANTFIND:
175 case T_FATE_CANTMAKE:
176 t->status = EXEC_CMD_FAIL;
177 break;
178 case T_FATE_ISTMP:
179 if (DEBUG_MAKEQ) printf("...using %s...\n", t->name);
180 break;
181 case T_FATE_TOUCHED:
182 case T_FATE_MISSING:
183 case T_FATE_NEEDTMP:
184 case T_FATE_OUTDATED:
185 case T_FATE_UPDATE:
186 /* set "on target" vars, build actions, unset vars */
187 /* set "progress" so that make1c() counts this target among the successes/failures. */
188 if (t->actions) {
189 ++counts->total;
190 //if (DEBUG_MAKE && !(counts->total % 100)) printf("...on %dth target...\n", counts->total);
192 double est_remaining = progress_update(globs.progress, counts->total);
193 if (est_remaining > 0.0) {
194 int minutes = (int)est_remaining/60;
195 int seconds = (int)est_remaining%60;
196 if (minutes > 0 || seconds > 0) {
197 printf("*** completed %.0f%% (", ((double)counts->total*100/globs.updating));
198 if (minutes > 0) printf("%d min ", minutes);
199 if (seconds >= 0) printf("%d sec ", seconds);
200 printf("remaining)...\n");
204 pushsettings(t->settings);
205 t->cmds = (char *)make1cmds(t->actions);
206 popsettings(t->settings);
207 t->progress = T_MAKE_RUNNING;
209 break;
212 /* call make1c() to begin the execution of the chain of commands needed to build target */
213 /* if we're not going to build target (because of dependency failures or because no commands
214 * need to be run) the chain will be empty and make1c() will directly
215 * signal the completion of target */
216 #ifdef JAM_OPT_SEMAPHORE
217 /* if there is a semaphore, indicate that it is in use */
218 if (t->semaphore) {
219 ++t->semaphore->asynccnt;
220 if (DEBUG_EXECCMD) printf( "SEM: %s now used by %s\n", t->semaphore->name, t->name);
222 #endif
223 make1c(t); //pState->curstate = T_STATE_MAKE1C;
228 * make1c() - launch target's next command, call make1b() when done
230 static void make1c (TARGET *t) {
231 CMD *cmd = (CMD *)t->cmds;
232 /* if there are (more) commands to run to build this target
233 * (and we haven't hit an error running earlier comands) we
234 * launch the command with execcmd() */
235 /* if there are no more commands to run, we collect the status
236 * from all the actions then report our completion to all the
237 * parents */
238 if (cmd && t->status == EXEC_CMD_OK) {
239 if (DEBUG_MAKE) {
240 if (DEBUG_MAKEQ || !(cmd->rule->flags&RULE_QUIETLY)) {
241 printf("(%3d%%) ", counts->total*100/globs.updating);
242 printf("%s ", cmd->rule->name);
243 list_print_ex(stdout, lol_get(&cmd->args, 0), LPFLAG_NO_TRSPACE);
244 printf("\n");
247 if (DEBUG_EXEC) printf("%s\n", dstr_cstr(&cmd->buf));
248 if (globs.cmdout) fprintf(globs.cmdout, "%s", dstr_cstr(&cmd->buf));
249 if (globs.noexec) make1d(t, EXEC_CMD_OK);
250 else {
251 fflush(stdout);
252 execcmd(dstr_cstr(&cmd->buf), make1d, t, cmd->shell);
254 } else {
255 TARGETS *c;
256 ACTIONS *actions;
257 /* collect status from actions, and distribute it as well */
258 for (actions = t->actions; actions; actions = actions->next) {
259 if (actions->action->status > t->status) t->status = actions->action->status;
261 for (actions = t->actions; actions; actions = actions->next) {
262 if (t->status > actions->action->status) actions->action->status = t->status;
264 /* tally success/failure for those we tried to update */
265 if (t->progress == T_MAKE_RUNNING) {
266 switch(t->status) {
267 case EXEC_CMD_OK: ++counts->made; break;
268 case EXEC_CMD_FAIL: ++counts->failed; break;
271 /* tell parents dependent has been built */
272 t->progress = T_MAKE_DONE;
273 for (c = t->parents; c; c = c->next) make1b(c->target);
274 #ifdef JAM_OPT_SEMAPHORE
275 /* if there is a semaphore, it is now free */
276 if (t->semaphore) {
277 /*assert(t->semaphore->asynccnt == 1);*/
278 if (t->semaphore->asynccnt != 1) { fprintf(stderr, "FATAL: internal error: t->semaphore->asynccnt != 1!\n"); abort(); }
279 --t->semaphore->asynccnt;
280 if (DEBUG_EXECCMD) printf( "SEM: %s is now free\n", t->semaphore->name);
281 /* If anything is waiting, notify the next target */
282 /* there is no point in notifying waiting targets, since they will be notified again */
283 if (t->semaphore->parents) {
284 TARGETS *first = t->semaphore->parents;
285 if (first->next) first->next->tail = first->tail;
286 t->semaphore->parents = first->next;
287 if (DEBUG_EXECCMD) printf( "SEM: placing %s on stack\n", first->target->name);
288 //push_state(&temp_stack, first->target, NULL, T_STATE_MAKE1B);
289 /*k8: memory leak, but it's safe: free(first);*/
292 #endif
298 * make1d() - handle command execution completion and call back make1c()
300 static void make1d (void *closure, int status) {
301 TARGET *t = (TARGET *)closure;
302 CMD *cmd = (CMD *)t->cmds;
303 /* execcmd() has completed */
304 /* all we need to do is fiddle with the status and signal our completion so make1c() can run the next command */
305 /* in interrupts, we bail heavily */
306 if (status == EXEC_CMD_FAIL && (cmd->rule->flags&RULE_IGNORE)) status = EXEC_CMD_OK;
307 /* on interrupt, set intr so _everything_ fails */
308 if (status == EXEC_CMD_INTR) ++intr;
309 if (status == EXEC_CMD_FAIL && DEBUG_MAKE) {
310 /* print command text on failure */
311 if (!DEBUG_EXEC) printf("%s\n", dstr_cstr(&cmd->buf));
312 printf("...failed %s ", cmd->rule->name);
313 list_print(lol_get(&cmd->args, 0));
314 printf("...\n");
315 if (globs.quitquick) ++intr;
317 /* if the command was interrupted or failed and the target is not "precious", remove the targets */
318 /* precious == 'actions updated' -- the target maintains state */
319 if (status != EXEC_CMD_OK && !(cmd->rule->flags&RULE_UPDATED)) {
320 LIST *targets = lol_get(&cmd->args, 0);
321 for (; targets; targets = list_next(targets)) {
322 if (!unlink(targets->string)) printf("...removing %s\n", targets->string);
325 /* free this command and call make1c() to move onto next command */
326 t->status = status;
327 t->cmds = (char *)cmd_next(cmd);
328 cmd_free(cmd);
329 make1c(t);
334 * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc
336 * Essentially copies a chain of ACTIONs to a chain of CMDs,
337 * grouping RULE_TOGETHER actions, splitting RULE_PIECEMEAL actions,
338 * and handling RULE_UPDATED actions. The result is a chain of
339 * CMDs which can be expanded by var_string() and executed with
340 * execcmd().
342 static CMD *make1cmds (ACTIONS *a0) {
343 CMD *cmds = 0;
344 LIST *shell = var_get("JAMSHELL"); /* shell is per-target */
345 /* step through actions */
346 /* actions may be shared with other targets or grouped with RULE_TOGETHER, so actions already seen are skipped */
347 for (; a0; a0 = a0->next) {
348 RULE *rule = a0->action->rule;
349 SETTINGS *boundvars;
350 LIST *nt, *ns;
351 ACTIONS *a1;
352 int start, chunk, length, maxline;
353 /* only do rules with commands to execute */
354 /* if this action has already been executed, use saved status */
355 if (!rule->actions || a0->action->running) continue;
356 a0->action->running = 1;
357 /* make LISTS of targets and sources */
358 /* if `execute together` has been specified for this rule, tack
359 * on sources from each instance of this rule for this target */
360 nt = make1list(L0, a0->action->targets, 0);
361 ns = make1list(L0, a0->action->sources, rule->flags);
362 if (rule->flags&RULE_TOGETHER) {
363 for (a1 = a0->next; a1; a1 = a1->next) {
364 if (a1->action->rule == rule && !a1->action->running) {
365 ns = make1list(ns, a1->action->sources, rule->flags);
366 a1->action->running = 1;
370 /* if doing only updated (or existing) sources, but none have
371 * been updated (or exist), skip this action */
372 if (!ns && (rule->flags&(RULE_UPDATED|RULE_EXISTING))) {
373 list_free(nt);
374 continue;
376 /* if we had 'actions xxx bind vars' we bind the vars now */
377 boundvars = make1settings(rule->bindlist);
378 pushsettings(boundvars);
380 * Build command, starting with all source args.
382 * If cmd_new returns 0, it's because the resulting command
383 * length is > MAXLINE. In this case, we'll slowly reduce
384 * the number of source arguments presented until it does
385 * fit. This only applies to actions that allow PIECEMEAL
386 * commands.
388 * While reducing slowly takes a bit of compute time to get
389 * things just right, it's worth it to get as close to MAXLINE
390 * as possible, because launching the commands we're executing
391 * is likely to be much more compute intensive!
393 * Note we loop through at least once, for sourceless actions.
395 * Max line length is the action specific maxline or, if not
396 * given or bigger than MAXLINE, MAXLINE.
398 start = 0;
399 chunk = length = list_length(ns);
400 maxline = (rule->flags&RULE_MAXLINE ? rule->flags>>8 : 0);
401 maxline = (maxline && maxline < MAXLINE ? maxline : MAXLINE);
402 do {
403 /* build cmd: cmd_new consumes its lists */
404 CMD *cmd = cmd_new(rule,
405 list_copy(L0, nt),
406 list_sublist(ns, start, chunk),
407 list_copy(L0, shell),
408 maxline);
409 if (cmd) {
410 /* it fit: chain it up */
411 if (!cmds) cmds = cmd; else cmds->tail->next = cmd;
412 cmds->tail = cmd;
413 start += chunk;
414 } else if ((rule->flags&RULE_PIECEMEAL) && chunk > 1) {
415 /* reduce chunk size slowly */
416 chunk = chunk*9/10;
417 } else {
418 /* too long and not splittable */
419 printf("%s actions too long (max %d)!\n", rule->name, maxline);
420 exit(EXITBAD);
422 } while (start < length);
423 /* these were always copied when used */
424 list_free(nt);
425 list_free(ns);
426 /* free the variables whose values were bound by 'actions xxx bind vars' */
427 popsettings(boundvars);
428 freesettings(boundvars);
430 return cmds;
435 * make1list() - turn a list of targets into a LIST, for $(<) and $(>)
437 static LIST *make1list (LIST *l, TARGETS *targets, int flags) {
438 for (; targets; targets = targets->next) {
439 TARGET *t = targets->target;
440 /* sources to 'actions existing' are never in the dependency
441 * graph (if they were, they'd get built and 'existing' would
442 * be superfluous, so throttle warning message about independent
443 * targets */
444 if (t->binding == T_BIND_UNBOUND) make1bind(t, !(flags&RULE_EXISTING));
445 if ((flags&RULE_EXISTING) && t->binding != T_BIND_EXISTS) continue;
446 if ((flags&RULE_UPDATED) && t->fate <= T_FATE_STABLE) continue;
447 /* prohibit duplicates for RULE_TOGETHER */
448 if (flags&RULE_TOGETHER) {
449 LIST *m;
451 for (m = l; m; m = m->next) if (!strcmp(m->string, t->boundname)) break;
452 if (m) continue;
454 /* build new list */
455 l = list_new(l, t->boundname, 1);
457 return l;
462 * make1settings() - for vars that get bound values, build up replacement lists
464 static SETTINGS *make1settings (LIST *vars) {
465 SETTINGS *settings = NULL;
466 for (; vars; vars = list_next(vars)) {
467 LIST *l = var_get(vars->string), *nl = NULL;
468 for (; l; l = list_next(l)) {
469 TARGET *t = bindtarget(l->string);
470 /* make sure the target is bound, warning if it is not in the dependency graph */
471 if (t->binding == T_BIND_UNBOUND) make1bind(t, 1);
472 /* build new list */
473 nl = list_new(nl, t->boundname, 1);
475 /* add to settings chain */
476 settings = addsettings(settings, 0, vars->string, nl);
478 return settings;
483 * make1bind() - bind targets that weren't bound in dependency analysis
485 * Spot the kludge! If a target is not in the dependency tree, it didn't
486 * get bound by make0(), so we have to do it here. Ugly.
488 static void make1bind (TARGET *t, int warn) {
489 if (t->flags&T_FLAG_NOTFILE) return;
490 /* sources to 'actions existing' are never in the dependency
491 * graph (if they were, they'd get built and 'existing' would
492 * be superfluous, so throttle warning message about independent
493 * targets */
494 if (warn) printf("warning: using independent target %s\n", t->name);
495 pushsettings(t->settings);
496 t->boundname = search(t->name, &t->time);
497 t->binding = t->time?T_BIND_EXISTS:T_BIND_MISSING;
498 popsettings(t->settings);