]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. | |
3 | * | |
4 | * This file is part of Jam - see jam.c for Copyright information. | |
5 | */ | |
6 | ||
7 | /* This file is ALSO: | |
8 | * Copyright 2001-2004 David Abrahams. | |
9 | * Distributed under the Boost Software License, Version 1.0. | |
10 | * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) | |
11 | */ | |
12 | ||
13 | /* | |
14 | * make1.c - execute commands to bring targets up to date | |
15 | * | |
16 | * This module contains make1(), the entry point called by make() to recursively | |
17 | * descend the dependency graph executing update actions as marked by make0(). | |
18 | * | |
19 | * External routines: | |
20 | * make1() - execute commands to update a TARGET and all of its dependencies | |
21 | * | |
22 | * Internal routines, the recursive/asynchronous command executors: | |
23 | * make1a() - recursively schedules dependency builds and then goes to | |
24 | * MAKE1B | |
25 | * make1b() - if nothing is blocking this target's build, proceed to | |
26 | * MAKE1C | |
27 | * make1c() - launch target's next command, or go to parents' MAKE1B | |
28 | * if none | |
29 | * make1c_closure() - handle command execution completion and go to MAKE1C | |
30 | * | |
31 | * Internal support routines: | |
32 | * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc. | |
33 | * make1list() - turn a list of targets into a LIST, for $(<) and $(>) | |
34 | * make1settings() - for vars with bound values, build up replacement lists | |
35 | * make1bind() - bind targets that weren't bound in dependency analysis | |
36 | */ | |
37 | ||
38 | #include "jam.h" | |
39 | #include "make.h" | |
40 | ||
41 | #include "command.h" | |
42 | #include "compile.h" | |
43 | #include "execcmd.h" | |
44 | #include "headers.h" | |
45 | #include "lists.h" | |
46 | #include "object.h" | |
47 | #include "output.h" | |
48 | #include "parse.h" | |
49 | #include "rules.h" | |
50 | #include "search.h" | |
51 | #include "variable.h" | |
52 | #include "output.h" | |
53 | ||
54 | #include <assert.h> | |
55 | #include <stdlib.h> | |
56 | ||
57 | #if !defined( NT ) || defined( __GNUC__ ) | |
58 | #include <unistd.h> /* for unlink */ | |
59 | #endif | |
60 | ||
61 | static CMD * make1cmds ( TARGET * ); | |
62 | static LIST * make1list ( LIST *, TARGETS *, int flags ); | |
63 | static SETTINGS * make1settings ( struct module_t *, LIST * vars ); | |
64 | static void make1bind ( TARGET * ); | |
65 | static TARGET * make1findcycle ( TARGET * ); | |
66 | static void make1breakcycle( TARGET *, TARGET * cycle_root ); | |
67 | static void push_cmds( CMDLIST * cmds, int status ); | |
68 | static int cmd_sem_lock( TARGET * t ); | |
69 | static void cmd_sem_unlock( TARGET * t ); | |
70 | ||
71 | static int targets_contains( TARGETS * l, TARGET * t ); | |
72 | static int targets_equal( TARGETS * l1, TARGETS * l2 ); | |
73 | ||
74 | /* Ugly static - it is too hard to carry it through the callbacks. */ | |
75 | ||
76 | static struct | |
77 | { | |
78 | int failed; | |
79 | int skipped; | |
80 | int total; | |
81 | int made; | |
82 | } counts[ 1 ]; | |
83 | ||
84 | /* Target state. */ | |
85 | #define T_STATE_MAKE1A 0 /* make1a() should be called */ | |
86 | #define T_STATE_MAKE1B 1 /* make1b() should be called */ | |
87 | #define T_STATE_MAKE1C 2 /* make1c() should be called */ | |
88 | ||
89 | typedef struct _state state; | |
90 | struct _state | |
91 | { | |
92 | state * prev; /* previous state on stack */ | |
93 | TARGET * t; /* current target */ | |
94 | TARGET * parent; /* parent argument necessary for MAKE1A */ | |
95 | int curstate; /* current state */ | |
96 | }; | |
97 | ||
98 | static void make1a( state * const ); | |
99 | static void make1b( state * const ); | |
100 | static void make1c( state const * const ); | |
101 | ||
102 | static void make1c_closure( void * const closure, int status, | |
103 | timing_info const * const, char const * const cmd_stdout, | |
104 | char const * const cmd_stderr, int const cmd_exit_reason ); | |
105 | ||
106 | typedef struct _stack | |
107 | { | |
108 | state * stack; | |
109 | } stack; | |
110 | ||
111 | static stack state_stack = { NULL }; | |
112 | ||
113 | static state * state_freelist = NULL; | |
114 | ||
115 | /* Currently running command counter. */ | |
116 | static int cmdsrunning; | |
117 | ||
118 | ||
119 | static state * alloc_state() | |
120 | { | |
121 | if ( state_freelist ) | |
122 | { | |
123 | state * const pState = state_freelist; | |
124 | state_freelist = pState->prev; | |
125 | memset( pState, 0, sizeof( state ) ); | |
126 | return pState; | |
127 | } | |
128 | return (state *)BJAM_MALLOC( sizeof( state ) ); | |
129 | } | |
130 | ||
131 | ||
132 | static void free_state( state * const pState ) | |
133 | { | |
134 | pState->prev = state_freelist; | |
135 | state_freelist = pState; | |
136 | } | |
137 | ||
138 | ||
139 | static void clear_state_freelist() | |
140 | { | |
141 | while ( state_freelist ) | |
142 | { | |
143 | state * const pState = state_freelist; | |
144 | state_freelist = state_freelist->prev; | |
145 | BJAM_FREE( pState ); | |
146 | } | |
147 | } | |
148 | ||
149 | ||
150 | static state * current_state( stack * const pStack ) | |
151 | { | |
152 | return pStack->stack; | |
153 | } | |
154 | ||
155 | ||
156 | static void pop_state( stack * const pStack ) | |
157 | { | |
158 | if ( pStack->stack ) | |
159 | { | |
160 | state * const pState = pStack->stack->prev; | |
161 | free_state( pStack->stack ); | |
162 | pStack->stack = pState; | |
163 | } | |
164 | } | |
165 | ||
166 | ||
167 | static state * push_state( stack * const pStack, TARGET * const t, | |
168 | TARGET * const parent, int const curstate ) | |
169 | { | |
170 | state * const pState = alloc_state(); | |
171 | pState->t = t; | |
172 | pState->parent = parent; | |
173 | pState->prev = pStack->stack; | |
174 | pState->curstate = curstate; | |
175 | return pStack->stack = pState; | |
176 | } | |
177 | ||
178 | ||
179 | /* | |
180 | * Pushes a stack onto another stack, effectively reversing the order. | |
181 | */ | |
182 | ||
183 | static void push_stack_on_stack( stack * const pDest, stack * const pSrc ) | |
184 | { | |
185 | while ( pSrc->stack ) | |
186 | { | |
187 | state * const pState = pSrc->stack; | |
188 | pSrc->stack = pState->prev; | |
189 | pState->prev = pDest->stack; | |
190 | pDest->stack = pState; | |
191 | } | |
192 | } | |
193 | ||
194 | ||
195 | /* | |
196 | * make1() - execute commands to update a list of targets and all of their dependencies | |
197 | */ | |
198 | ||
199 | static int intr = 0; | |
200 | static int quit = 0; | |
201 | ||
202 | int make1( LIST * targets ) | |
203 | { | |
204 | state * pState; | |
205 | int status = 0; | |
206 | ||
207 | memset( (char *)counts, 0, sizeof( *counts ) ); | |
208 | ||
209 | { | |
210 | LISTITER iter, end; | |
211 | stack temp_stack = { NULL }; | |
212 | for ( iter = list_begin( targets ), end = list_end( targets ); | |
213 | iter != end; iter = list_next( iter ) ) | |
214 | push_state( &temp_stack, bindtarget( list_item( iter ) ), NULL, T_STATE_MAKE1A ); | |
215 | push_stack_on_stack( &state_stack, &temp_stack ); | |
216 | } | |
217 | ||
218 | /* Clear any state left over from the past */ | |
219 | quit = 0; | |
220 | ||
221 | /* Recursively make the target and its dependencies. */ | |
222 | ||
223 | while ( 1 ) | |
224 | { | |
225 | while ( ( pState = current_state( &state_stack ) ) ) | |
226 | { | |
227 | if ( quit ) | |
228 | pop_state( &state_stack ); | |
229 | ||
230 | switch ( pState->curstate ) | |
231 | { | |
232 | case T_STATE_MAKE1A: make1a( pState ); break; | |
233 | case T_STATE_MAKE1B: make1b( pState ); break; | |
234 | case T_STATE_MAKE1C: make1c( pState ); break; | |
235 | default: | |
236 | assert( !"make1(): Invalid state detected." ); | |
237 | } | |
238 | } | |
239 | if ( !cmdsrunning ) | |
240 | break; | |
241 | /* Wait for outstanding commands to finish running. */ | |
242 | exec_wait(); | |
243 | } | |
244 | ||
245 | clear_state_freelist(); | |
246 | ||
247 | /* Talk about it. */ | |
248 | if ( counts->failed ) | |
249 | out_printf( "...failed updating %d target%s...\n", counts->failed, | |
250 | counts->failed > 1 ? "s" : "" ); | |
251 | if ( DEBUG_MAKE && counts->skipped ) | |
252 | out_printf( "...skipped %d target%s...\n", counts->skipped, | |
253 | counts->skipped > 1 ? "s" : "" ); | |
254 | if ( DEBUG_MAKE && counts->made ) | |
255 | out_printf( "...updated %d target%s...\n", counts->made, | |
256 | counts->made > 1 ? "s" : "" ); | |
257 | ||
258 | /* If we were interrupted, exit now that all child processes | |
259 | have finished. */ | |
260 | if ( intr ) | |
261 | exit( EXITBAD ); | |
262 | ||
263 | { | |
264 | LISTITER iter, end; | |
265 | for ( iter = list_begin( targets ), end = list_end( targets ); | |
266 | iter != end; iter = list_next( iter ) ) | |
267 | { | |
268 | /* Check that the target was updated and that the | |
269 | update succeeded. */ | |
270 | TARGET * t = bindtarget( list_item( iter ) ); | |
271 | if (t->progress == T_MAKE_DONE) | |
272 | { | |
273 | if (t->status != EXEC_CMD_OK) | |
274 | status = 1; | |
275 | } | |
276 | else if ( ! ( t->progress == T_MAKE_NOEXEC_DONE && globs.noexec ) ) | |
277 | { | |
278 | status = 1; | |
279 | } | |
280 | } | |
281 | } | |
282 | return status; | |
283 | } | |
284 | ||
285 | ||
286 | /* | |
287 | * make1a() - recursively schedules dependency builds and then goes to MAKE1B | |
288 | * | |
289 | * Called to start processing a specified target. Does nothing if the target is | |
290 | * already being processed or otherwise starts processing all of its | |
291 | * dependencies. | |
292 | */ | |
293 | ||
294 | static void make1a( state * const pState ) | |
295 | { | |
296 | TARGET * t = pState->t; | |
297 | TARGET * const scc_root = target_scc( t ); | |
298 | ||
299 | if ( !pState->parent || target_scc( pState->parent ) != scc_root ) | |
300 | pState->t = t = scc_root; | |
301 | ||
302 | /* If the parent is the first to try to build this target or this target is | |
303 | * in the MAKE1C quagmire, arrange for the parent to be notified when this | |
304 | * target has been built. | |
305 | */ | |
306 | if ( pState->parent && t->progress <= T_MAKE_RUNNING ) | |
307 | { | |
308 | TARGET * const parent_scc = target_scc( pState->parent ); | |
309 | if ( t != parent_scc ) | |
310 | { | |
311 | t->parents = targetentry( t->parents, parent_scc ); | |
312 | ++parent_scc->asynccnt; | |
313 | } | |
314 | } | |
315 | ||
316 | /* If the target has been previously updated with -n in effect, and we are | |
317 | * now ignoring -n, update it for real. E.g. if the UPDATE_NOW rule was | |
318 | * called for it twice - first with the -n option and then without. | |
319 | */ | |
320 | if ( !globs.noexec && t->progress == T_MAKE_NOEXEC_DONE ) | |
321 | t->progress = T_MAKE_INIT; | |
322 | ||
323 | /* If this target is already being processed then do nothing. There is no | |
324 | * need to start processing the same target all over again. | |
325 | */ | |
326 | if ( t->progress != T_MAKE_INIT ) | |
327 | { | |
328 | pop_state( &state_stack ); | |
329 | return; | |
330 | } | |
331 | ||
332 | /* Guard against circular dependencies. */ | |
333 | t->progress = T_MAKE_ONSTACK; | |
334 | ||
335 | /* 'asynccnt' counts the dependencies preventing this target from proceeding | |
336 | * to MAKE1C for actual building. We start off with a count of 1 to prevent | |
337 | * anything from happening until we can notify all dependencies that they | |
338 | * are needed. This 1 is then accounted for when we enter MAKE1B ourselves, | |
339 | * below. Without this if a dependency gets built before we finish | |
340 | * processing all of our other dependencies our build might be triggerred | |
341 | * prematurely. | |
342 | */ | |
343 | t->asynccnt = 1; | |
344 | ||
345 | /* Push dependency build requests (to be executed in the natural order). */ | |
346 | { | |
347 | stack temp_stack = { NULL }; | |
348 | TARGETS * c; | |
349 | for ( c = t->depends; c && !quit; c = c->next ) | |
350 | push_state( &temp_stack, c->target, t, T_STATE_MAKE1A ); | |
351 | push_stack_on_stack( &state_stack, &temp_stack ); | |
352 | } | |
353 | ||
354 | t->progress = T_MAKE_ACTIVE; | |
355 | ||
356 | /* Once all of our dependencies have started getting processed we can move | |
357 | * onto MAKE1B. | |
358 | */ | |
359 | /* Implementation note: | |
360 | * In theory this would be done by popping this state before pushing | |
361 | * dependency target build requests but as a slight optimization we simply | |
362 | * modify our current state and leave it on the stack instead. | |
363 | */ | |
364 | pState->curstate = T_STATE_MAKE1B; | |
365 | } | |
366 | ||
367 | ||
368 | /* | |
369 | * make1b() - if nothing is blocking this target's build, proceed to MAKE1C | |
370 | * | |
371 | * Called after something stops blocking this target's build, e.g. that all of | |
372 | * its dependencies have started being processed, one of its dependencies has | |
373 | * been built or a semaphore this target has been waiting for is free again. | |
374 | */ | |
375 | ||
376 | static void make1b( state * const pState ) | |
377 | { | |
378 | TARGET * const t = pState->t; | |
379 | TARGET * failed = 0; | |
380 | char const * failed_name = "dependencies"; | |
381 | ||
382 | pop_state( &state_stack ); | |
383 | ||
384 | /* If any dependencies are still outstanding, wait until they signal their | |
385 | * completion by pushing this same state for their parent targets. | |
386 | */ | |
387 | if ( --t->asynccnt ) | |
388 | { | |
389 | return; | |
390 | } | |
391 | ||
392 | /* Now ready to build target 't', if dependencies built OK. */ | |
393 | ||
394 | /* Collect status from dependencies. If -n was passed then act as though all | |
395 | * dependencies built correctly (the only way they can fail is if UPDATE_NOW | |
396 | * was called). If the dependencies can not be found or we got an interrupt, | |
397 | * we can not get here. | |
398 | */ | |
399 | if ( !globs.noexec ) | |
400 | { | |
401 | TARGETS * c; | |
402 | for ( c = t->depends; c; c = c->next ) | |
403 | if ( c->target->status > t->status && !( c->target->flags & | |
404 | T_FLAG_NOCARE ) ) | |
405 | { | |
406 | failed = c->target; | |
407 | t->status = c->target->status; | |
408 | } | |
409 | } | |
410 | ||
411 | /* If an internal header node failed to build, we want to output the target | |
412 | * that it failed on. | |
413 | */ | |
414 | if ( failed ) | |
415 | failed_name = failed->flags & T_FLAG_INTERNAL | |
416 | ? failed->failed | |
417 | : object_str( failed->name ); | |
418 | t->failed = failed_name; | |
419 | ||
420 | /* If actions for building any of the dependencies have failed, bail. | |
421 | * Otherwise, execute all actions to make the current target. | |
422 | */ | |
423 | if ( ( t->status == EXEC_CMD_FAIL ) && t->actions ) | |
424 | { | |
425 | ++counts->skipped; | |
426 | if ( ( t->flags & ( T_FLAG_RMOLD | T_FLAG_NOTFILE ) ) == T_FLAG_RMOLD ) | |
427 | { | |
428 | if ( !unlink( object_str( t->boundname ) ) ) | |
429 | out_printf( "...removing outdated %s\n", object_str( t->boundname ) | |
430 | ); | |
431 | } | |
432 | else | |
433 | out_printf( "...skipped %s for lack of %s...\n", object_str( t->name ), | |
434 | failed_name ); | |
435 | } | |
436 | ||
437 | if ( t->status == EXEC_CMD_OK ) | |
438 | switch ( t->fate ) | |
439 | { | |
440 | case T_FATE_STABLE: | |
441 | case T_FATE_NEWER: | |
442 | break; | |
443 | ||
444 | case T_FATE_CANTFIND: | |
445 | case T_FATE_CANTMAKE: | |
446 | t->status = EXEC_CMD_FAIL; | |
447 | break; | |
448 | ||
449 | case T_FATE_ISTMP: | |
450 | if ( DEBUG_MAKE ) | |
451 | out_printf( "...using %s...\n", object_str( t->name ) ); | |
452 | break; | |
453 | ||
454 | case T_FATE_TOUCHED: | |
455 | case T_FATE_MISSING: | |
456 | case T_FATE_NEEDTMP: | |
457 | case T_FATE_OUTDATED: | |
458 | case T_FATE_UPDATE: | |
459 | case T_FATE_REBUILD: | |
460 | /* Prepare commands for executing actions scheduled for this target. | |
461 | * Commands have their embedded variables automatically expanded, | |
462 | * including making use of any "on target" variables. | |
463 | */ | |
464 | if ( t->actions ) | |
465 | { | |
466 | ++counts->total; | |
467 | if ( DEBUG_MAKE && !( counts->total % 100 ) ) | |
468 | out_printf( "...on %dth target...\n", counts->total ); | |
469 | ||
470 | t->cmds = (char *)make1cmds( t ); | |
471 | /* Update the target's "progress" so MAKE1C processing counts it | |
472 | * among its successes/failures. | |
473 | */ | |
474 | t->progress = T_MAKE_RUNNING; | |
475 | } | |
476 | break; | |
477 | ||
478 | /* All valid fates should have been accounted for by now. */ | |
479 | default: | |
480 | err_printf( "ERROR: %s has bad fate %d", object_str( t->name ), | |
481 | t->fate ); | |
482 | abort(); | |
483 | } | |
484 | ||
485 | /* Proceed to MAKE1C to begin executing the chain of commands prepared for | |
486 | * building the target. If we are not going to build the target (e.g. due to | |
487 | * dependency failures or no commands needing to be run) the chain will be | |
488 | * empty and MAKE1C processing will directly signal the target's completion. | |
489 | */ | |
490 | ||
491 | if ( t->cmds == NULL || --( ( CMD * )t->cmds )->asynccnt == 0 ) | |
492 | push_state( &state_stack, t, NULL, T_STATE_MAKE1C ); | |
493 | else if ( DEBUG_EXECCMD ) | |
494 | { | |
495 | CMD * cmd = ( CMD * )t->cmds; | |
496 | out_printf( "Delaying %s %s: %d targets not ready\n", object_str( cmd->rule->name ), object_str( t->boundname ), cmd->asynccnt ); | |
497 | } | |
498 | } | |
499 | ||
500 | ||
501 | /* | |
502 | * make1c() - launch target's next command, or go to parents' MAKE1B if none | |
503 | * | |
504 | * If there are (more) commands to run to build this target (and we have not hit | |
505 | * an error running earlier comands) we launch the command using exec_cmd(). | |
506 | * Command execution signals its completion in exec_wait() by calling our | |
507 | * make1c_closure() callback. | |
508 | * | |
509 | * If there are no more commands to run, we collect the status from all the | |
510 | * actions and report our completion to all the parents. | |
511 | */ | |
512 | ||
513 | static void make1c( state const * const pState ) | |
514 | { | |
515 | TARGET * const t = pState->t; | |
516 | CMD * const cmd = (CMD *)t->cmds; | |
517 | ||
518 | if ( cmd ) | |
519 | { | |
520 | /* Pop state first in case something below (e.g. exec_cmd(), exec_wait() | |
521 | * or make1c_closure()) pushes a new state. Note that we must not access | |
522 | * the popped state data after this as the same stack node might have | |
523 | * been reused internally for some newly pushed state. | |
524 | */ | |
525 | pop_state( &state_stack ); | |
526 | ||
527 | if ( cmd->status != EXEC_CMD_OK ) | |
528 | { | |
529 | t->cmds = NULL; | |
530 | push_cmds( cmd->next, cmd->status ); | |
531 | cmd_free( cmd ); | |
532 | return; | |
533 | } | |
534 | ||
535 | #ifdef OPT_SEMAPHORE | |
536 | if ( ! cmd_sem_lock( t ) ) | |
537 | { | |
538 | return; | |
539 | } | |
540 | #endif | |
541 | ||
542 | /* Increment the jobs running counter. */ | |
543 | ++cmdsrunning; | |
544 | ||
545 | /* Execute the actual build command or fake it if no-op. */ | |
546 | if ( globs.noexec || cmd->noop ) | |
547 | { | |
548 | timing_info time_info = { 0 }; | |
549 | timestamp_current( &time_info.start ); | |
550 | timestamp_copy( &time_info.end, &time_info.start ); | |
551 | make1c_closure( t, EXEC_CMD_OK, &time_info, "", "", EXIT_OK ); | |
552 | } | |
553 | else | |
554 | { | |
555 | exec_cmd( cmd->buf, make1c_closure, t, cmd->shell ); | |
556 | ||
557 | /* Wait until under the concurrent command count limit. */ | |
558 | /* FIXME: This wait could be skipped here and moved to just before | |
559 | * trying to execute a command that would cross the command count | |
560 | * limit. Note though that this might affect the order in which | |
561 | * unrelated targets get built and would thus require that all | |
562 | * affected Boost Build tests be updated. | |
563 | */ | |
564 | assert( 0 < globs.jobs ); | |
7c673cae FG |
565 | while ( cmdsrunning >= globs.jobs ) |
566 | exec_wait(); | |
567 | } | |
568 | } | |
569 | else | |
570 | { | |
571 | ACTIONS * actions; | |
572 | ||
573 | /* Tally success/failure for those we tried to update. */ | |
574 | if ( t->progress == T_MAKE_RUNNING ) | |
575 | switch ( t->status ) | |
576 | { | |
577 | case EXEC_CMD_OK: ++counts->made; break; | |
578 | case EXEC_CMD_FAIL: ++counts->failed; break; | |
579 | } | |
580 | ||
581 | /* Tell parents their dependency has been built. */ | |
582 | { | |
583 | TARGETS * c; | |
584 | stack temp_stack = { NULL }; | |
585 | TARGET * additional_includes = NULL; | |
586 | ||
587 | t->progress = globs.noexec ? T_MAKE_NOEXEC_DONE : T_MAKE_DONE; | |
588 | ||
589 | /* Target has been updated so rescan it for dependencies. */ | |
590 | if ( t->fate >= T_FATE_MISSING && t->status == EXEC_CMD_OK && | |
591 | !( t->flags & T_FLAG_INTERNAL ) ) | |
592 | { | |
593 | TARGET * saved_includes; | |
594 | SETTINGS * s; | |
595 | ||
596 | /* Clean current includes. */ | |
597 | saved_includes = t->includes; | |
598 | t->includes = 0; | |
599 | ||
600 | s = copysettings( t->settings ); | |
601 | pushsettings( root_module(), s ); | |
602 | headers( t ); | |
603 | popsettings( root_module(), s ); | |
604 | freesettings( s ); | |
605 | ||
606 | if ( t->includes ) | |
607 | { | |
608 | /* Tricky. The parents have already been processed, but they | |
609 | * have not seen the internal node, because it was just | |
610 | * created. We need to: | |
611 | * - push MAKE1A states that would have been pushed by the | |
612 | * parents here | |
613 | * - make sure all unprocessed parents will pick up the | |
614 | * new includes | |
615 | * - make sure processing the additional MAKE1A states is | |
616 | * done before processing the MAKE1B state for our | |
617 | * current target (which would mean this target has | |
618 | * already been built), otherwise the parent would be | |
619 | * considered built before the additional MAKE1A state | |
620 | * processing even got a chance to start. | |
621 | */ | |
622 | make0( t->includes, t->parents->target, 0, 0, 0, t->includes | |
623 | ); | |
624 | /* Link the old includes on to make sure that it gets | |
625 | * cleaned up correctly. | |
626 | */ | |
627 | t->includes->includes = saved_includes; | |
628 | for ( c = t->dependants; c; c = c->next ) | |
629 | c->target->depends = targetentry( c->target->depends, | |
630 | t->includes ); | |
631 | /* Will be processed below. */ | |
632 | additional_includes = t->includes; | |
633 | } | |
634 | else | |
635 | { | |
636 | t->includes = saved_includes; | |
637 | } | |
638 | } | |
639 | ||
640 | if ( additional_includes ) | |
641 | for ( c = t->parents; c; c = c->next ) | |
642 | push_state( &temp_stack, additional_includes, c->target, | |
643 | T_STATE_MAKE1A ); | |
644 | ||
645 | if ( t->scc_root ) | |
646 | { | |
647 | TARGET * const scc_root = target_scc( t ); | |
648 | assert( scc_root->progress < T_MAKE_DONE ); | |
649 | for ( c = t->parents; c; c = c->next ) | |
650 | { | |
651 | if ( target_scc( c->target ) == scc_root ) | |
652 | push_state( &temp_stack, c->target, NULL, T_STATE_MAKE1B | |
653 | ); | |
654 | else | |
655 | scc_root->parents = targetentry( scc_root->parents, | |
656 | c->target ); | |
657 | } | |
658 | } | |
659 | else | |
660 | { | |
661 | for ( c = t->parents; c; c = c->next ) | |
662 | push_state( &temp_stack, c->target, NULL, T_STATE_MAKE1B ); | |
663 | } | |
664 | ||
665 | /* Must pop state before pushing any more. */ | |
666 | pop_state( &state_stack ); | |
667 | ||
668 | /* Using stacks reverses the order of execution. Reverse it back. */ | |
669 | push_stack_on_stack( &state_stack, &temp_stack ); | |
670 | } | |
671 | } | |
672 | } | |
673 | ||
674 | ||
675 | /* | |
676 | * call_timing_rule() - Look up the __TIMING_RULE__ variable on the given | |
677 | * target, and if non-empty, invoke the rule it names, passing the given | |
678 | * timing_info. | |
679 | */ | |
680 | ||
681 | static void call_timing_rule( TARGET * target, timing_info const * const time ) | |
682 | { | |
683 | LIST * timing_rule; | |
684 | ||
685 | pushsettings( root_module(), target->settings ); | |
686 | timing_rule = var_get( root_module(), constant_TIMING_RULE ); | |
687 | popsettings( root_module(), target->settings ); | |
688 | ||
689 | if ( !list_empty( timing_rule ) ) | |
690 | { | |
691 | /* rule timing-rule ( args * : target : start end user system clock ) */ | |
692 | ||
693 | /* Prepare the argument list. */ | |
694 | FRAME frame[ 1 ]; | |
695 | OBJECT * rulename = list_front( timing_rule ); | |
696 | frame_init( frame ); | |
697 | ||
698 | /* args * :: $(__TIMING_RULE__[2-]) */ | |
699 | lol_add( frame->args, list_copy_range( timing_rule, list_next( | |
700 | list_begin( timing_rule ) ), list_end( timing_rule ) ) ); | |
701 | ||
702 | /* target :: the name of the target */ | |
703 | lol_add( frame->args, list_new( object_copy( target->name ) ) ); | |
704 | ||
705 | /* start end user system clock :: info about the action command */ | |
706 | lol_add( frame->args, list_push_back( list_push_back( list_push_back( list_push_back( list_new( | |
707 | outf_time( &time->start ) ), | |
708 | outf_time( &time->end ) ), | |
709 | outf_double( time->user ) ), | |
710 | outf_double( time->system ) ), | |
711 | outf_double( timestamp_delta_seconds(&time->start, &time->end) ) ) | |
712 | ); | |
713 | ||
714 | /* Call the rule. */ | |
715 | evaluate_rule( bindrule( rulename , root_module() ), rulename, frame ); | |
716 | ||
717 | /* Clean up. */ | |
718 | frame_free( frame ); | |
719 | } | |
720 | } | |
721 | ||
722 | ||
723 | /* | |
724 | * call_action_rule() - Look up the __ACTION_RULE__ variable on the given | |
725 | * target, and if non-empty, invoke the rule it names, passing the given info, | |
726 | * timing_info, executed command and command output. | |
727 | */ | |
728 | ||
729 | static void call_action_rule | |
730 | ( | |
731 | TARGET * target, | |
732 | int status, | |
733 | timing_info const * time, | |
734 | char const * executed_command, | |
735 | char const * command_output | |
736 | ) | |
737 | { | |
738 | LIST * action_rule; | |
739 | ||
740 | pushsettings( root_module(), target->settings ); | |
741 | action_rule = var_get( root_module(), constant_ACTION_RULE ); | |
742 | popsettings( root_module(), target->settings ); | |
743 | ||
744 | if ( !list_empty( action_rule ) ) | |
745 | { | |
746 | /* rule action-rule ( | |
747 | args * : | |
748 | target : | |
749 | command status start end user system : | |
750 | output ? ) */ | |
751 | ||
752 | /* Prepare the argument list. */ | |
753 | FRAME frame[ 1 ]; | |
754 | OBJECT * rulename = list_front( action_rule ); | |
755 | frame_init( frame ); | |
756 | ||
757 | /* args * :: $(__ACTION_RULE__[2-]) */ | |
758 | lol_add( frame->args, list_copy_range( action_rule, list_next( | |
759 | list_begin( action_rule ) ), list_end( action_rule ) ) ); | |
760 | ||
761 | /* target :: the name of the target */ | |
762 | lol_add( frame->args, list_new( object_copy( target->name ) ) ); | |
763 | ||
764 | /* command status start end user system :: info about the action command | |
765 | */ | |
766 | lol_add( frame->args, | |
767 | list_push_back( list_push_back( list_push_back( list_push_back( list_push_back( list_new( | |
768 | object_new( executed_command ) ), | |
769 | outf_int( status ) ), | |
770 | outf_time( &time->start ) ), | |
771 | outf_time( &time->end ) ), | |
772 | outf_double( time->user ) ), | |
773 | outf_double( time->system ) ) ); | |
774 | ||
775 | /* output ? :: the output of the action command */ | |
776 | if ( command_output ) | |
b32b8144 FG |
777 | { |
778 | OBJECT * command_output_obj = object_new( command_output ); | |
779 | char * output_i = (char*)object_str(command_output_obj); | |
780 | /* Clean the output of control characters. */ | |
781 | for (; *output_i; ++output_i) | |
782 | { | |
783 | if (iscntrl(*output_i) && !isspace(*output_i)) *output_i = '?'; | |
784 | } | |
785 | lol_add( frame->args, list_new( command_output_obj ) ); | |
786 | } | |
7c673cae FG |
787 | else |
788 | lol_add( frame->args, L0 ); | |
789 | ||
790 | /* Call the rule. */ | |
791 | evaluate_rule( bindrule( rulename, root_module() ), rulename, frame ); | |
792 | ||
793 | /* Clean up. */ | |
794 | frame_free( frame ); | |
795 | } | |
796 | } | |
797 | ||
798 | ||
799 | /* | |
800 | * make1c_closure() - handle command execution completion and go to MAKE1C. | |
801 | * | |
802 | * Internal function passed as a notification callback for when a command | |
803 | * finishes getting executed by the OS or called directly when faking that a | |
804 | * command had been executed by the OS. | |
805 | * | |
806 | * Now all we need to do is fiddle with the command exit status and push a new | |
807 | * MAKE1C state to execute the next command scheduled for building this target | |
808 | * or close up the target's build process in case there are no more commands | |
809 | * scheduled for it. On interrupts, we bail heavily. | |
810 | */ | |
811 | ||
812 | static void make1c_closure | |
813 | ( | |
814 | void * const closure, | |
815 | int status_orig, | |
816 | timing_info const * const time, | |
817 | char const * const cmd_stdout, | |
818 | char const * const cmd_stderr, | |
819 | int const cmd_exit_reason | |
820 | ) | |
821 | { | |
822 | TARGET * const t = (TARGET *)closure; | |
823 | CMD * const cmd = (CMD *)t->cmds; | |
824 | char const * rule_name = 0; | |
825 | char const * target_name = 0; | |
826 | ||
827 | assert( cmd ); | |
828 | ||
829 | --cmdsrunning; | |
830 | ||
831 | /* Calculate the target's status from the cmd execution result. */ | |
832 | { | |
833 | /* Store the target's status. */ | |
834 | t->status = status_orig; | |
835 | ||
836 | /* Invert OK/FAIL target status when FAIL_EXPECTED has been applied. */ | |
837 | if ( t->flags & T_FLAG_FAIL_EXPECTED && !globs.noexec ) | |
838 | { | |
839 | switch ( t->status ) | |
840 | { | |
841 | case EXEC_CMD_FAIL: t->status = EXEC_CMD_OK; break; | |
842 | case EXEC_CMD_OK: t->status = EXEC_CMD_FAIL; break; | |
843 | } | |
844 | } | |
845 | ||
846 | /* Ignore failures for actions marked as 'ignore'. */ | |
847 | if ( t->status == EXEC_CMD_FAIL && cmd->rule->actions->flags & | |
848 | RULE_IGNORE ) | |
849 | t->status = EXEC_CMD_OK; | |
850 | } | |
851 | ||
852 | if ( DEBUG_MAKEQ || | |
853 | ( DEBUG_MAKE && !( cmd->rule->actions->flags & RULE_QUIETLY ) ) ) | |
854 | { | |
855 | rule_name = object_str( cmd->rule->name ); | |
856 | target_name = object_str( list_front( lol_get( (LOL *)&cmd->args, 0 ) ) | |
857 | ); | |
858 | } | |
859 | ||
860 | out_action( rule_name, target_name, cmd->buf->value, cmd_stdout, cmd_stderr, | |
861 | cmd_exit_reason ); | |
862 | ||
863 | if ( !globs.noexec ) | |
864 | { | |
865 | call_timing_rule( t, time ); | |
866 | if ( DEBUG_EXECCMD ) | |
867 | out_printf( "%f sec system; %f sec user; %f sec clock\n", | |
868 | time->system, time->user, | |
869 | timestamp_delta_seconds(&time->start, &time->end) ); | |
870 | ||
871 | /* Assume -p0 is in effect, i.e. cmd_stdout contains merged output. */ | |
872 | call_action_rule( t, status_orig, time, cmd->buf->value, cmd_stdout ); | |
873 | } | |
874 | ||
875 | /* Print command text on failure. */ | |
876 | if ( t->status == EXEC_CMD_FAIL && DEBUG_MAKE ) | |
877 | { | |
878 | if ( !DEBUG_EXEC ) | |
879 | out_printf( "%s\n", cmd->buf->value ); | |
880 | ||
881 | out_printf( "...failed %s ", object_str( cmd->rule->name ) ); | |
882 | list_print( lol_get( (LOL *)&cmd->args, 0 ) ); | |
883 | out_printf( "...\n" ); | |
884 | } | |
885 | ||
886 | /* On interrupt, set quit so _everything_ fails. Do the same for failed | |
887 | * commands if we were asked to stop the build in case of any errors. | |
888 | */ | |
889 | if ( t->status == EXEC_CMD_INTR ) | |
890 | { | |
891 | ++intr; | |
892 | ++quit; | |
893 | } | |
894 | if ( t->status == EXEC_CMD_FAIL && globs.quitquick ) | |
895 | ++quit; | |
896 | ||
897 | /* If the command was not successful remove all of its targets not marked as | |
898 | * "precious". | |
899 | */ | |
900 | if ( t->status != EXEC_CMD_OK ) | |
901 | { | |
902 | LIST * const targets = lol_get( (LOL *)&cmd->args, 0 ); | |
903 | LISTITER iter = list_begin( targets ); | |
904 | LISTITER const end = list_end( targets ); | |
905 | for ( ; iter != end; iter = list_next( iter ) ) | |
906 | { | |
907 | char const * const filename = object_str( list_item( iter ) ); | |
908 | TARGET const * const t = bindtarget( list_item( iter ) ); | |
909 | if ( !( t->flags & T_FLAG_PRECIOUS ) && !unlink( filename ) ) | |
910 | out_printf( "...removing %s\n", filename ); | |
911 | } | |
912 | } | |
913 | ||
914 | #ifdef OPT_SEMAPHORE | |
915 | /* Release any semaphores used by this action. */ | |
916 | cmd_sem_unlock( t ); | |
917 | #endif | |
918 | ||
919 | /* Free this command and push the MAKE1C state to execute the next one | |
920 | * scheduled for building this same target. | |
921 | */ | |
922 | t->cmds = NULL; | |
923 | push_cmds( cmd->next, t->status ); | |
924 | cmd_free( cmd ); | |
925 | } | |
926 | ||
927 | /* push the next MAKE1C state after a command is run. */ | |
928 | static void push_cmds( CMDLIST * cmds, int status ) | |
929 | { | |
930 | CMDLIST * cmd_iter; | |
931 | for( cmd_iter = cmds; cmd_iter; cmd_iter = cmd_iter->next ) | |
932 | { | |
933 | if ( cmd_iter->iscmd ) | |
934 | { | |
935 | CMD * next_cmd = cmd_iter->impl.cmd; | |
936 | /* Propagate the command status. */ | |
937 | if ( next_cmd->status < status ) | |
938 | next_cmd->status = status; | |
939 | if ( --next_cmd->asynccnt == 0 ) | |
940 | { | |
941 | /* Select the first target associated with the action. | |
942 | * This is safe because sibling CMDs cannot have targets | |
943 | * in common. | |
944 | */ | |
945 | TARGET * first_target = bindtarget( list_front( lol_get( &next_cmd->args, 0 ) ) ); | |
946 | first_target->cmds = (char *)next_cmd; | |
947 | push_state( &state_stack, first_target, NULL, T_STATE_MAKE1C ); | |
948 | } | |
949 | else if ( DEBUG_EXECCMD ) | |
950 | { | |
951 | TARGET * first_target = bindtarget( list_front( lol_get( &next_cmd->args, 0 ) ) ); | |
952 | out_printf( "Delaying %s %s: %d targets not ready\n", object_str( next_cmd->rule->name ), object_str( first_target->boundname ), next_cmd->asynccnt ); | |
953 | } | |
954 | } | |
955 | else | |
956 | { | |
957 | /* This is a target that we're finished updating */ | |
958 | TARGET * updated_target = cmd_iter->impl.t; | |
959 | if ( updated_target->status < status ) | |
960 | updated_target->status = status; | |
961 | updated_target->cmds = NULL; | |
962 | push_state( &state_stack, updated_target, NULL, T_STATE_MAKE1C ); | |
963 | } | |
964 | } | |
965 | } | |
966 | ||
967 | ||
968 | /* | |
969 | * swap_settings() - replace the settings from the current module and target | |
970 | * with those from the new module and target | |
971 | */ | |
972 | ||
973 | static void swap_settings | |
974 | ( | |
975 | module_t * * current_module, | |
976 | TARGET * * current_target, | |
977 | module_t * new_module, | |
978 | TARGET * new_target | |
979 | ) | |
980 | { | |
981 | if ( ( new_target == *current_target ) && | |
982 | ( new_module == *current_module ) ) | |
983 | return; | |
984 | ||
985 | if ( *current_target ) | |
986 | popsettings( *current_module, (*current_target)->settings ); | |
987 | ||
988 | if ( new_target ) | |
989 | pushsettings( new_module, new_target->settings ); | |
990 | ||
991 | *current_module = new_module; | |
992 | *current_target = new_target; | |
993 | } | |
994 | ||
995 | ||
996 | /* | |
997 | * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc. | |
998 | * | |
999 | * Essentially copies a chain of ACTIONs to a chain of CMDs, grouping | |
1000 | * RULE_TOGETHER actions, splitting RULE_PIECEMEAL actions, and handling | |
1001 | * RULE_NEWSRCS actions. The result is a chain of CMDs which has already had all | |
1002 | * of its embedded variable references expanded and can now be executed using | |
1003 | * exec_cmd(). | |
1004 | */ | |
1005 | ||
1006 | static CMD * make1cmds( TARGET * t ) | |
1007 | { | |
1008 | CMD * cmds = 0; | |
1009 | CMD * last_cmd; | |
1010 | LIST * shell = L0; | |
1011 | module_t * settings_module = 0; | |
1012 | TARGET * settings_target = 0; | |
1013 | ACTIONS * a0; | |
1014 | int const running_flag = globs.noexec ? A_RUNNING_NOEXEC : A_RUNNING; | |
1015 | ||
1016 | /* Step through actions. | |
1017 | */ | |
1018 | for ( a0 = t->actions; a0; a0 = a0->next ) | |
1019 | { | |
1020 | RULE * rule = a0->action->rule; | |
1021 | rule_actions * actions = rule->actions; | |
1022 | SETTINGS * boundvars; | |
1023 | LIST * nt; | |
1024 | LIST * ns; | |
1025 | ACTIONS * a1; | |
1026 | ||
1027 | /* Only do rules with commands to execute. | |
1028 | */ | |
1029 | if ( !actions ) | |
1030 | continue; | |
1031 | ||
1032 | if ( a0->action->running >= running_flag ) | |
1033 | { | |
1034 | CMD * first; | |
1035 | /* If this action was skipped either because it was | |
1036 | * combined with another action by RULE_TOGETHER, or | |
1037 | * because all of its sources were filtered out, | |
1038 | * then we don't have anything to do here. | |
1039 | */ | |
1040 | if ( a0->action->first_cmd == NULL ) | |
1041 | continue; | |
1042 | /* This action has already been processed for another target. | |
1043 | * Just set up the dependency graph correctly and move on. | |
1044 | */ | |
1045 | first = a0->action->first_cmd; | |
1046 | if( cmds ) | |
1047 | { | |
1048 | last_cmd->next = cmdlist_append_cmd( last_cmd->next, first ); | |
1049 | } | |
1050 | else | |
1051 | { | |
1052 | cmds = first; | |
1053 | } | |
1054 | last_cmd = a0->action->last_cmd; | |
1055 | continue; | |
1056 | } | |
1057 | ||
1058 | a0->action->running = running_flag; | |
1059 | ||
1060 | /* Make LISTS of targets and sources. If `execute together` has been | |
1061 | * specified for this rule, tack on sources from each instance of this | |
1062 | * rule for this target. | |
1063 | */ | |
1064 | nt = make1list( L0, a0->action->targets, 0 ); | |
1065 | ns = make1list( L0, a0->action->sources, actions->flags ); | |
1066 | if ( actions->flags & RULE_TOGETHER ) | |
1067 | for ( a1 = a0->next; a1; a1 = a1->next ) | |
1068 | if ( a1->action->rule == rule && | |
1069 | a1->action->running < running_flag && | |
1070 | targets_equal( a0->action->targets, a1->action->targets ) ) | |
1071 | { | |
1072 | ns = make1list( ns, a1->action->sources, actions->flags ); | |
1073 | a1->action->running = running_flag; | |
1074 | } | |
1075 | ||
1076 | /* If doing only updated (or existing) sources, but none have been | |
1077 | * updated (or exist), skip this action. | |
1078 | */ | |
1079 | if ( list_empty( ns ) && | |
1080 | ( actions->flags & ( RULE_NEWSRCS | RULE_EXISTING ) ) ) | |
1081 | { | |
1082 | list_free( nt ); | |
1083 | continue; | |
1084 | } | |
1085 | ||
1086 | swap_settings( &settings_module, &settings_target, rule->module, t ); | |
1087 | if ( list_empty( shell ) ) | |
1088 | { | |
1089 | /* shell is per-target */ | |
1090 | shell = var_get( rule->module, constant_JAMSHELL ); | |
1091 | } | |
1092 | ||
1093 | /* If we had 'actions xxx bind vars' we bind the vars now. */ | |
1094 | boundvars = make1settings( rule->module, actions->bindlist ); | |
1095 | pushsettings( rule->module, boundvars ); | |
1096 | ||
1097 | /* | |
1098 | * Build command, starting with all source args. | |
1099 | * | |
1100 | * For actions that allow PIECEMEAL commands, if the constructed command | |
1101 | * string is too long, we retry constructing it with a reduced number of | |
1102 | * source arguments presented. | |
1103 | * | |
1104 | * While reducing slowly takes a bit of compute time to get things just | |
1105 | * right, it is worth it to get as close to maximum allowed command | |
1106 | * string length as possible, because launching the commands we are | |
1107 | * executing is likely to be much more compute intensive. | |
1108 | * | |
1109 | * Note that we loop through at least once, for sourceless actions. | |
1110 | */ | |
1111 | { | |
1112 | int const length = list_length( ns ); | |
1113 | int start = 0; | |
1114 | int chunk = length; | |
1115 | int cmd_count = 0; | |
1116 | LIST * cmd_targets = L0; | |
1117 | LIST * cmd_shell = L0; | |
1118 | TARGETS * semaphores = NULL; | |
1119 | TARGETS * targets_iter; | |
1120 | int unique_targets; | |
1121 | do | |
1122 | { | |
1123 | CMD * cmd; | |
1124 | int cmd_check_result; | |
1125 | int cmd_error_length; | |
1126 | int cmd_error_max_length; | |
1127 | int retry = 0; | |
1128 | int accept_command = 0; | |
1129 | ||
1130 | /* Build cmd: cmd_new() takes ownership of its lists. */ | |
1131 | if ( list_empty( cmd_targets ) ) cmd_targets = list_copy( nt ); | |
1132 | if ( list_empty( cmd_shell ) ) cmd_shell = list_copy( shell ); | |
1133 | cmd = cmd_new( rule, cmd_targets, list_sublist( ns, start, | |
1134 | chunk ), cmd_shell ); | |
1135 | ||
1136 | cmd_check_result = exec_check( cmd->buf, &cmd->shell, | |
1137 | &cmd_error_length, &cmd_error_max_length ); | |
1138 | ||
1139 | if ( cmd_check_result == EXEC_CHECK_OK ) | |
1140 | { | |
1141 | accept_command = 1; | |
1142 | } | |
1143 | else if ( cmd_check_result == EXEC_CHECK_NOOP ) | |
1144 | { | |
1145 | accept_command = 1; | |
1146 | cmd->noop = 1; | |
1147 | } | |
1148 | else if ( ( actions->flags & RULE_PIECEMEAL ) && ( chunk > 1 ) ) | |
1149 | { | |
1150 | /* Too long but splittable. Reduce chunk size slowly and | |
1151 | * retry. | |
1152 | */ | |
1153 | assert( cmd_check_result == EXEC_CHECK_TOO_LONG || | |
1154 | cmd_check_result == EXEC_CHECK_LINE_TOO_LONG ); | |
1155 | chunk = chunk * 9 / 10; | |
1156 | retry = 1; | |
1157 | } | |
1158 | else | |
1159 | { | |
1160 | /* Too long and not splittable. */ | |
1161 | char const * const error_message = cmd_check_result == | |
1162 | EXEC_CHECK_TOO_LONG | |
1163 | ? "is too long" | |
1164 | : "contains a line that is too long"; | |
1165 | assert( cmd_check_result == EXEC_CHECK_TOO_LONG || | |
1166 | cmd_check_result == EXEC_CHECK_LINE_TOO_LONG ); | |
1167 | out_printf( "%s action %s (%d, max %d):\n", object_str( | |
1168 | rule->name ), error_message, cmd_error_length, | |
1169 | cmd_error_max_length ); | |
1170 | ||
1171 | /* Tell the user what did not fit. */ | |
1172 | out_puts( cmd->buf->value ); | |
1173 | exit( EXITBAD ); | |
1174 | } | |
1175 | ||
1176 | assert( !retry || !accept_command ); | |
1177 | ||
1178 | if ( accept_command ) | |
1179 | { | |
1180 | /* Chain it up. */ | |
1181 | if ( cmds ) | |
1182 | { | |
1183 | last_cmd->next = cmdlist_append_cmd( last_cmd->next, cmd ); | |
1184 | last_cmd = cmd; | |
1185 | } | |
1186 | else | |
1187 | { | |
1188 | cmds = last_cmd = cmd; | |
1189 | } | |
1190 | ||
1191 | if ( cmd_count++ == 0 ) | |
1192 | { | |
1193 | a0->action->first_cmd = cmd; | |
1194 | } | |
1195 | ||
1196 | /* Mark lists we need recreated for the next command since | |
1197 | * they got consumed by the cmd object. | |
1198 | */ | |
1199 | cmd_targets = L0; | |
1200 | cmd_shell = L0; | |
1201 | } | |
1202 | else | |
1203 | { | |
1204 | /* We can reuse targets & shell lists for the next command | |
1205 | * if we do not let them die with this cmd object. | |
1206 | */ | |
1207 | cmd_release_targets_and_shell( cmd ); | |
1208 | cmd_free( cmd ); | |
1209 | } | |
1210 | ||
1211 | if ( !retry ) | |
1212 | start += chunk; | |
1213 | } | |
1214 | while ( start < length ); | |
1215 | ||
1216 | /* Record the end of the actions cmds */ | |
1217 | a0->action->last_cmd = last_cmd; | |
1218 | ||
1219 | unique_targets = 0; | |
1220 | for ( targets_iter = a0->action->targets; targets_iter; targets_iter = targets_iter->next ) | |
1221 | { | |
1222 | if ( targets_contains( targets_iter->next, targets_iter->target ) ) | |
1223 | continue; | |
1224 | /* Add all targets produced by the action to the update list. */ | |
1225 | push_state( &state_stack, targets_iter->target, NULL, T_STATE_MAKE1A ); | |
1226 | ++unique_targets; | |
1227 | } | |
1228 | /* We need to wait until all the targets agree that | |
1229 | * it's okay to run this action. | |
1230 | */ | |
1231 | ( ( CMD * )a0->action->first_cmd )->asynccnt = unique_targets; | |
1232 | ||
1233 | #if OPT_SEMAPHORE | |
1234 | /* Collect semaphores */ | |
1235 | for ( targets_iter = a0->action->targets; targets_iter; targets_iter = targets_iter->next ) | |
1236 | { | |
1237 | TARGET * sem = targets_iter->target->semaphore; | |
1238 | if ( sem ) | |
1239 | { | |
1240 | TARGETS * semiter; | |
1241 | if ( ! targets_contains( semaphores, sem ) ) | |
1242 | semaphores = targetentry( semaphores, sem ); | |
1243 | } | |
1244 | } | |
1245 | ( ( CMD * )a0->action->first_cmd )->lock = semaphores; | |
1246 | ( ( CMD * )a0->action->last_cmd )->unlock = semaphores; | |
1247 | #endif | |
1248 | } | |
1249 | ||
1250 | /* These were always copied when used. */ | |
1251 | list_free( nt ); | |
1252 | list_free( ns ); | |
1253 | ||
1254 | /* Free variables with values bound by 'actions xxx bind vars'. */ | |
1255 | popsettings( rule->module, boundvars ); | |
1256 | freesettings( boundvars ); | |
1257 | } | |
1258 | ||
1259 | if ( cmds ) | |
1260 | { | |
1261 | last_cmd->next = cmdlist_append_target( last_cmd->next, t ); | |
1262 | } | |
1263 | ||
1264 | swap_settings( &settings_module, &settings_target, 0, 0 ); | |
1265 | return cmds; | |
1266 | } | |
1267 | ||
1268 | ||
1269 | /* | |
1270 | * make1list() - turn a list of targets into a LIST, for $(<) and $(>) | |
1271 | */ | |
1272 | ||
1273 | static LIST * make1list( LIST * l, TARGETS * targets, int flags ) | |
1274 | { | |
1275 | for ( ; targets; targets = targets->next ) | |
1276 | { | |
1277 | TARGET * t = targets->target; | |
1278 | ||
1279 | if ( t->binding == T_BIND_UNBOUND ) | |
1280 | make1bind( t ); | |
1281 | ||
1282 | if ( ( flags & RULE_EXISTING ) && ( flags & RULE_NEWSRCS ) ) | |
1283 | { | |
1284 | if ( ( t->binding != T_BIND_EXISTS ) && | |
1285 | ( t->fate <= T_FATE_STABLE ) ) | |
1286 | continue; | |
1287 | } | |
1288 | else if ( flags & RULE_EXISTING ) | |
1289 | { | |
1290 | if ( t->binding != T_BIND_EXISTS ) | |
1291 | continue; | |
1292 | } | |
1293 | else if ( flags & RULE_NEWSRCS ) | |
1294 | { | |
1295 | if ( t->fate <= T_FATE_STABLE ) | |
1296 | continue; | |
1297 | } | |
1298 | ||
1299 | /* Prohibit duplicates for RULE_TOGETHER. */ | |
1300 | if ( flags & RULE_TOGETHER ) | |
1301 | { | |
1302 | LISTITER iter = list_begin( l ); | |
1303 | LISTITER const end = list_end( l ); | |
1304 | for ( ; iter != end; iter = list_next( iter ) ) | |
1305 | if ( object_equal( list_item( iter ), t->boundname ) ) | |
1306 | break; | |
1307 | if ( iter != end ) | |
1308 | continue; | |
1309 | } | |
1310 | ||
1311 | /* Build new list. */ | |
1312 | l = list_push_back( l, object_copy( t->boundname ) ); | |
1313 | } | |
1314 | ||
1315 | return l; | |
1316 | } | |
1317 | ||
1318 | ||
1319 | /* | |
1320 | * make1settings() - for vars with bound values, build up replacement lists | |
1321 | */ | |
1322 | ||
1323 | static SETTINGS * make1settings( struct module_t * module, LIST * vars ) | |
1324 | { | |
1325 | SETTINGS * settings = 0; | |
1326 | ||
1327 | LISTITER vars_iter = list_begin( vars ); | |
1328 | LISTITER const vars_end = list_end( vars ); | |
1329 | for ( ; vars_iter != vars_end; vars_iter = list_next( vars_iter ) ) | |
1330 | { | |
1331 | LIST * const l = var_get( module, list_item( vars_iter ) ); | |
1332 | LIST * nl = L0; | |
1333 | LISTITER iter = list_begin( l ); | |
1334 | LISTITER const end = list_end( l ); | |
1335 | ||
1336 | for ( ; iter != end; iter = list_next( iter ) ) | |
1337 | { | |
1338 | TARGET * const t = bindtarget( list_item( iter ) ); | |
1339 | ||
1340 | /* Make sure the target is bound. */ | |
1341 | if ( t->binding == T_BIND_UNBOUND ) | |
1342 | make1bind( t ); | |
1343 | ||
1344 | /* Build a new list. */ | |
1345 | nl = list_push_back( nl, object_copy( t->boundname ) ); | |
1346 | } | |
1347 | ||
1348 | /* Add to settings chain. */ | |
1349 | settings = addsettings( settings, VAR_SET, list_item( vars_iter ), nl ); | |
1350 | } | |
1351 | ||
1352 | return settings; | |
1353 | } | |
1354 | ||
1355 | ||
1356 | /* | |
1357 | * make1bind() - bind targets that were not bound during dependency analysis | |
1358 | * | |
1359 | * Spot the kludge! If a target is not in the dependency tree, it did not get | |
1360 | * bound by make0(), so we have to do it here. Ugly. | |
1361 | */ | |
1362 | ||
1363 | static void make1bind( TARGET * t ) | |
1364 | { | |
1365 | if ( t->flags & T_FLAG_NOTFILE ) | |
1366 | return; | |
1367 | ||
1368 | pushsettings( root_module(), t->settings ); | |
1369 | object_free( t->boundname ); | |
1370 | t->boundname = search( t->name, &t->time, 0, t->flags & T_FLAG_ISFILE ); | |
1371 | t->binding = timestamp_empty( &t->time ) ? T_BIND_MISSING : T_BIND_EXISTS; | |
1372 | popsettings( root_module(), t->settings ); | |
1373 | } | |
1374 | ||
1375 | ||
1376 | static int targets_contains( TARGETS * l, TARGET * t ) | |
1377 | { | |
1378 | for ( ; l; l = l->next ) | |
1379 | { | |
1380 | if ( t == l->target ) | |
1381 | { | |
1382 | return 1; | |
1383 | } | |
1384 | } | |
1385 | return 0; | |
1386 | } | |
1387 | ||
1388 | static int targets_equal( TARGETS * l1, TARGETS * l2 ) | |
1389 | { | |
1390 | for ( ; l1 && l2; l1 = l1->next, l2 = l2->next ) | |
1391 | { | |
1392 | if ( l1->target != l2->target ) | |
1393 | return 0; | |
1394 | } | |
1395 | return !l1 && !l2; | |
1396 | } | |
1397 | ||
1398 | ||
1399 | #ifdef OPT_SEMAPHORE | |
1400 | ||
1401 | static int cmd_sem_lock( TARGET * t ) | |
1402 | { | |
1403 | CMD * cmd = (CMD *)t->cmds; | |
1404 | TARGETS * iter; | |
1405 | /* Check whether all the semaphores required for updating | |
1406 | * this target are free. | |
1407 | */ | |
1408 | for ( iter = cmd->lock; iter; iter = iter->next ) | |
1409 | { | |
1410 | if ( iter->target->asynccnt > 0 ) | |
1411 | { | |
1412 | if ( DEBUG_EXECCMD ) | |
1413 | out_printf( "SEM: %s is busy, delaying launch of %s\n", | |
1414 | object_str( iter->target->name ), object_str( t->name ) ); | |
1415 | iter->target->parents = targetentry( iter->target->parents, t ); | |
1416 | return 0; | |
1417 | } | |
1418 | } | |
1419 | /* Lock the semaphores. */ | |
1420 | for ( iter = cmd->lock; iter; iter = iter->next ) | |
1421 | { | |
1422 | ++iter->target->asynccnt; | |
1423 | if ( DEBUG_EXECCMD ) | |
1424 | out_printf( "SEM: %s now used by %s\n", object_str( iter->target->name | |
1425 | ), object_str( t->name ) ); | |
1426 | } | |
1427 | /* A cmd only needs to be locked around its execution. | |
1428 | * clearing cmd->lock here makes it safe to call cmd_sem_lock | |
1429 | * twice. | |
1430 | */ | |
1431 | cmd->lock = NULL; | |
1432 | return 1; | |
1433 | } | |
1434 | ||
1435 | static void cmd_sem_unlock( TARGET * t ) | |
1436 | { | |
1437 | CMD * cmd = ( CMD * )t->cmds; | |
1438 | TARGETS * iter; | |
1439 | /* Release the semaphores. */ | |
1440 | for ( iter = cmd->unlock; iter; iter = iter->next ) | |
1441 | { | |
1442 | if ( DEBUG_EXECCMD ) | |
1443 | out_printf( "SEM: %s is now free\n", object_str( | |
1444 | iter->target->name ) ); | |
1445 | --iter->target->asynccnt; | |
1446 | assert( iter->target->asynccnt <= 0 ); | |
1447 | } | |
1448 | for ( iter = cmd->unlock; iter; iter = iter->next ) | |
1449 | { | |
1450 | /* Find a waiting target that's ready */ | |
1451 | while ( iter->target->parents ) | |
1452 | { | |
1453 | TARGETS * first = iter->target->parents; | |
1454 | TARGET * t1 = first->target; | |
1455 | ||
1456 | /* Pop the first waiting CMD */ | |
1457 | if ( first->next ) | |
1458 | first->next->tail = first->tail; | |
1459 | iter->target->parents = first->next; | |
1460 | BJAM_FREE( first ); | |
1461 | ||
1462 | if ( cmd_sem_lock( t1 ) ) | |
1463 | { | |
1464 | push_state( &state_stack, t1, NULL, T_STATE_MAKE1C ); | |
1465 | break; | |
1466 | } | |
1467 | } | |
1468 | } | |
1469 | } | |
1470 | ||
1471 | #endif |