diff --git a/src/engine/builtins.c b/src/engine/builtins.c index dec2ef77e..1fe0dcf50 100644 --- a/src/engine/builtins.c +++ b/src/engine/builtins.c @@ -1443,7 +1443,6 @@ LIST * builtin_update_now( FRAME * frame, int flags ) if ( !list_empty( force ) ) { globs.noexec = original_noexec; - globs.quitquick = original_quitquick; } if ( !list_empty( continue_ ) ) diff --git a/src/engine/make.c b/src/engine/make.c index b0b668008..afc8bb938 100644 --- a/src/engine/make.c +++ b/src/engine/make.c @@ -148,12 +148,8 @@ int make( LIST * targets, int anyhow ) status = counts->cantfind || counts->cantmake; { - LISTITER iter; - LISTITER end; PROFILE_ENTER( MAKE_MAKE1 ); - for ( iter = list_begin( targets ), end = list_end( targets ); iter != - end; iter = list_next( iter ) ) - status |= make1( bindtarget( list_item( iter ) ) ); + status |= make1( targets ); PROFILE_EXIT( MAKE_MAKE1 ); } diff --git a/src/engine/make.h b/src/engine/make.h index 882ccebd7..2c3ba1678 100644 --- a/src/engine/make.h +++ b/src/engine/make.h @@ -16,7 +16,7 @@ #include "rules.h" int make( LIST * targets, int anyhow ); -int make1( TARGET * const t ); +int make1( LIST * t ); typedef struct { int temp; diff --git a/src/engine/make1.c b/src/engine/make1.c index 2c9797f18..319dc85ba 100644 --- a/src/engine/make1.c +++ b/src/engine/make1.c @@ -186,25 +186,37 @@ static void push_stack_on_stack( stack * const pDest, stack * const pSrc ) /* - * make1() - execute commands to update a TARGET and all of its dependencies + * make1() - execute commands to update a list of targets and all of their dependencies */ static int intr = 0; +static int quit = 0; -int make1( TARGET * const t ) +int make1( LIST * targets ) { state * pState; memset( (char *)counts, 0, sizeof( *counts ) ); + + { + LISTITER iter, end; + stack temp_stack = { NULL }; + for ( iter = list_begin( targets ), end = list_end( targets ); + iter != end; iter = list_next( iter ) ) + push_state( &temp_stack, bindtarget( list_item( iter ) ), NULL, T_STATE_MAKE1A ); + push_stack_on_stack( &state_stack, &temp_stack ); + } + + /* Clear any state left over from the past */ + quit = 0; /* Recursively make the target and its dependencies. */ - push_state( &state_stack, t, NULL, T_STATE_MAKE1A ); while ( 1 ) { while ( ( pState = current_state( &state_stack ) ) ) { - if ( intr ) + if ( quit ) pop_state( &state_stack ); switch ( pState->curstate ) @@ -235,6 +247,11 @@ int make1( TARGET * const t ) printf( "...updated %d target%s...\n", counts->made, counts->made > 1 ? "s" : "" ); + /* If we were interrupted, exit now that all child processes + have finished. */ + if ( intr ) + exit( 1 ); + return counts->total != counts->made; } @@ -302,7 +319,7 @@ static void make1a( state * const pState ) { stack temp_stack = { NULL }; TARGETS * c; - for ( c = t->depends; c && !intr; c = c->next ) + for ( c = t->depends; c && !quit; c = c->next ) push_state( &temp_stack, c->target, t, T_STATE_MAKE1A ); push_stack_on_stack( &state_stack, &temp_stack ); } @@ -878,12 +895,16 @@ static void make1c_closure printf( "...\n" ); } - /* On interrupt, set intr so _everything_ fails. Do the same for failed + /* On interrupt, set quit so _everything_ fails. Do the same for failed * commands if we were asked to stop the build in case of any errors. */ - if ( t->status == EXEC_CMD_INTR || - ( t->status == EXEC_CMD_FAIL && globs.quitquick ) ) + if ( t->status == EXEC_CMD_INTR ) + { ++intr; + ++quit; + } + if ( t->status == EXEC_CMD_FAIL && globs.quitquick ) + ++quit; /* If the command was not successful remove all of its targets not marked as * "precious". diff --git a/test/core_update_now.py b/test/core_update_now.py index e1fd49e27..c16901965 100755 --- a/test/core_update_now.py +++ b/test/core_update_now.py @@ -193,9 +193,143 @@ updating target1 t.cleanup() +def save_restore(): + """Tests that ignore-minus-n and ignore-minus-q are + local to the call to UPDATE_NOW""" + t = BoostBuild.Tester(pass_toolset=0, pass_d0=False) + + t.write("actions.jam", """\ +rule fail +{ + NOTFILE $(<) ; + ALWAYS $(<) ; +} +actions fail +{ + exit 1 +} + +rule pass +{ + NOTFILE $(<) ; + ALWAYS $(<) ; +} +actions pass +{ + echo updating $(<) +} +""") + t.write("file.jam", """ +include actions.jam ; +fail target1 ; +fail target2 ; +UPDATE_NOW target1 target2 : : $(IGNORE_MINUS_N) : $(IGNORE_MINUS_Q) ; +fail target3 ; +fail target4 ; +UPDATE_NOW target3 target4 ; +UPDATE ; +""") + t.run_build_system(['-n', '-sIGNORE_MINUS_N=1', '-ffile.jam'], + stdout='''...found 2 targets... +...updating 2 targets... +fail target1 + + exit 1 + +...failed fail target1... +fail target2 + + exit 1 + +...failed fail target2... +...failed updating 2 targets... +...found 2 targets... +...updating 2 targets... +fail target3 + + exit 1 + +fail target4 + + exit 1 + +...updated 2 targets... +''') + + t.run_build_system(['-q', '-sIGNORE_MINUS_N=1', '-ffile.jam'], + status=1, stdout='''...found 2 targets... +...updating 2 targets... +fail target1 + + exit 1 + +...failed fail target1... +...failed updating 1 target... +...found 2 targets... +...updating 2 targets... +fail target3 + + exit 1 + +...failed fail target3... +...failed updating 1 target... +''') + + t.run_build_system(['-n', '-sIGNORE_MINUS_Q=1', '-ffile.jam'], + stdout='''...found 2 targets... +...updating 2 targets... +fail target1 + + exit 1 + +fail target2 + + exit 1 + +...updated 2 targets... +...found 2 targets... +...updating 2 targets... +fail target3 + + exit 1 + +fail target4 + + exit 1 + +...updated 2 targets... +''') + + t.run_build_system(['-q', '-sIGNORE_MINUS_Q=1', '-ffile.jam'], + status=1, stdout='''...found 2 targets... +...updating 2 targets... +fail target1 + + exit 1 + +...failed fail target1... +fail target2 + + exit 1 + +...failed fail target2... +...failed updating 2 targets... +...found 2 targets... +...updating 2 targets... +fail target3 + + exit 1 + +...failed fail target3... +...failed updating 1 target... +''') + + t.cleanup() + basic() ignore_minus_n() failed_target() missing_target() build_once() +save_restore()