mirror of
https://github.com/boostorg/build.git
synced 2026-02-16 01:12:13 +00:00
Detect cycles created by rescanning.
[SVN r78249]
This commit is contained in:
@@ -74,6 +74,7 @@ static CMD * make1cmds ( TARGET * );
|
||||
static LIST * make1list ( LIST *, TARGETS *, int flags );
|
||||
static SETTINGS * make1settings( struct module_t * module, LIST * vars );
|
||||
static void make1bind ( TARGET * );
|
||||
static int make1findcycle( TARGET * t );
|
||||
|
||||
/* Ugly static - it is too hard to carry it through the callbacks. */
|
||||
|
||||
@@ -85,6 +86,8 @@ static struct
|
||||
int made;
|
||||
} counts[ 1 ] ;
|
||||
|
||||
int handling_rescan;
|
||||
|
||||
/* Target state - remove recursive calls by just keeping track of state target
|
||||
* is in.
|
||||
*/
|
||||
@@ -97,7 +100,8 @@ typedef struct _state
|
||||
#define T_STATE_MAKE1ATAIL 1 /* make1atail() should be called */
|
||||
#define T_STATE_MAKE1B 2 /* make1b() should be called */
|
||||
#define T_STATE_MAKE1C 3 /* make1c() should be called */
|
||||
#define T_STATE_MAKE1D 4 /* make1d() should be called */
|
||||
#define T_STATE_MAKE1CTAIL 4 /* make1ctail() should be called */
|
||||
#define T_STATE_MAKE1D 5 /* make1d() should be called */
|
||||
int curstate; /* current state */
|
||||
int status;
|
||||
} state;
|
||||
@@ -106,6 +110,7 @@ static void make1a ( state * );
|
||||
static void make1atail ( state * );
|
||||
static void make1b ( state * );
|
||||
static void make1c ( state * );
|
||||
static void make1ctail ( state * );
|
||||
static void make1d ( state * );
|
||||
static void make_closure( void * closure, int status, timing_info *, const char *, const char * );
|
||||
|
||||
@@ -227,6 +232,7 @@ int make1( TARGET * t )
|
||||
case T_STATE_MAKE1ATAIL: make1atail( pState ); break;
|
||||
case T_STATE_MAKE1B : make1b ( pState ); break;
|
||||
case T_STATE_MAKE1C : make1c ( pState ); break;
|
||||
case T_STATE_MAKE1CTAIL: make1ctail( pState ); break;
|
||||
case T_STATE_MAKE1D : make1d ( pState ); break;
|
||||
}
|
||||
}
|
||||
@@ -273,8 +279,9 @@ static void make1a( state * pState )
|
||||
if ( pState->parent )
|
||||
switch ( pState->t->progress )
|
||||
{
|
||||
case T_MAKE_INIT:
|
||||
case T_MAKE_ACTIVE:
|
||||
if ( handling_rescan && make1findcycle( t ) ) break;
|
||||
case T_MAKE_INIT:
|
||||
case T_MAKE_RUNNING:
|
||||
pState->t->parents = targetentry( pState->t->parents,
|
||||
pState->parent );
|
||||
@@ -632,8 +639,12 @@ static void make1c( state * pState )
|
||||
}
|
||||
|
||||
if ( additional_includes )
|
||||
{
|
||||
++handling_rescan;
|
||||
for ( c = t->parents; c; c = c->next )
|
||||
push_state( &temp_stack, additional_includes, c->target, T_STATE_MAKE1A );
|
||||
push_state( &temp_stack, additional_includes, NULL, T_STATE_MAKE1CTAIL );
|
||||
}
|
||||
|
||||
for ( c = t->parents; c; c = c->next )
|
||||
push_state( &temp_stack, c->target, NULL, T_STATE_MAKE1B );
|
||||
@@ -676,6 +687,12 @@ static void make1c( state * pState )
|
||||
}
|
||||
}
|
||||
|
||||
static void make1ctail( state * pState )
|
||||
{
|
||||
--handling_rescan;
|
||||
pop_state( &state_stack );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* call_timing_rule() - Look up the __TIMING_RULE__ variable on the given
|
||||
@@ -1163,3 +1180,42 @@ static void make1bind( TARGET * t )
|
||||
t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
|
||||
popsettings( root_module(), t->settings );
|
||||
}
|
||||
|
||||
|
||||
static int make1findcycle_impl( TARGET * t )
|
||||
{
|
||||
TARGETS * c;
|
||||
|
||||
if ( t->progress == T_MAKE_ONSTACK )
|
||||
return 1;
|
||||
else if ( t->progress != T_MAKE_ACTIVE )
|
||||
return 0;
|
||||
|
||||
t->progress = T_MAKE_FINDCYCLE;
|
||||
|
||||
for ( c = t->depends; c; c = c->next )
|
||||
if ( make1findcycle_impl( c->target ) )
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void make1findcycle_cleanup( TARGET * t )
|
||||
{
|
||||
TARGETS * c;
|
||||
|
||||
if ( t->progress != T_MAKE_FINDCYCLE )
|
||||
return;
|
||||
|
||||
t->progress = T_MAKE_ACTIVE;
|
||||
|
||||
for ( c = t->depends; c; c = c->next )
|
||||
make1findcycle_cleanup( c->target );
|
||||
}
|
||||
|
||||
static int make1findcycle( TARGET * t )
|
||||
{
|
||||
int result = make1findcycle_impl( t );
|
||||
make1findcycle_cleanup( t );
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -212,6 +212,8 @@ struct _target
|
||||
#define T_MAKE_RUNNING 3 /* make1(target) running commands */
|
||||
#define T_MAKE_DONE 4 /* make1(target) done */
|
||||
#define T_MAKE_NOEXEC_DONE 5 /* make1(target) done with -n in effect */
|
||||
#define T_MAKE_FINDCYCLE 6 /* make1(target) searching for cyclic includes after
|
||||
rescanning a generated file. */
|
||||
|
||||
#ifdef OPT_SEMAPHORE
|
||||
#define T_MAKE_SEMAPHORE 5 /* Special target type for semaphores */
|
||||
|
||||
@@ -82,7 +82,7 @@ actions copy {
|
||||
|
||||
make header1.h : header1.in : @common.copy ;
|
||||
make header2.h : header2.in : @common.copy ;
|
||||
make header3.h : header2.in : @common.copy ;
|
||||
make header3.h : header3.in : @common.copy ;
|
||||
obj test : test.cpp :
|
||||
<implicit-dependency>header1.h
|
||||
<implicit-dependency>header2.h
|
||||
@@ -97,4 +97,58 @@ t.expect_addition("bin/$toolset/debug/header3.h")
|
||||
t.expect_addition("bin/$toolset/debug/test.obj")
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.rm(".")
|
||||
|
||||
# Test a loop in generated headers.
|
||||
t.write("test.cpp", """
|
||||
#include "header1.h"
|
||||
""")
|
||||
|
||||
t.write("header1.in", """
|
||||
#ifndef HEADER1_H
|
||||
#define HEADER1_H
|
||||
#include "header2.h"
|
||||
#endif
|
||||
""")
|
||||
|
||||
t.write("header2.in", """
|
||||
#ifndef HEADER2_H
|
||||
#define HEADER2_H
|
||||
#include "header3.h"
|
||||
#endif
|
||||
""")
|
||||
|
||||
t.write("header3.in", """
|
||||
#ifndef HEADER2_H
|
||||
#define HEADER2_H
|
||||
#include "header1.h"
|
||||
#endif
|
||||
""")
|
||||
|
||||
t.write("Jamroot.jam", """
|
||||
import common ;
|
||||
|
||||
actions copy {
|
||||
sleep 1
|
||||
cp $(>) $(<)
|
||||
}
|
||||
|
||||
make header1.h : header1.in : @common.copy ;
|
||||
make header2.h : header2.in : @common.copy ;
|
||||
make header3.h : header3.in : @common.copy ;
|
||||
obj test : test.cpp :
|
||||
<implicit-dependency>header1.h
|
||||
<implicit-dependency>header2.h
|
||||
<implicit-dependency>header3.h
|
||||
;
|
||||
""")
|
||||
|
||||
t.run_build_system("-j2 test")
|
||||
t.expect_addition("bin/$toolset/debug/header1.h")
|
||||
t.expect_addition("bin/$toolset/debug/header2.h")
|
||||
t.expect_addition("bin/$toolset/debug/header3.h")
|
||||
t.expect_addition("bin/$toolset/debug/test.obj")
|
||||
t.expect_nothing_more()
|
||||
|
||||
|
||||
t.cleanup()
|
||||
|
||||
Reference in New Issue
Block a user