2
0
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:
Steven Watanabe
2012-04-28 22:05:28 +00:00
parent 221841015d
commit 0090f72efa
3 changed files with 115 additions and 3 deletions

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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()