Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r78249 - in trunk/tools/build/v2: engine test
From: steven_at_[hidden]
Date: 2012-04-28 18:05:29


Author: steven_watanabe
Date: 2012-04-28 18:05:28 EDT (Sat, 28 Apr 2012)
New Revision: 78249
URL: http://svn.boost.org/trac/boost/changeset/78249

Log:
Detect cycles created by rescanning.
Text files modified:
   trunk/tools/build/v2/engine/make1.c | 60 ++++++++++++++++++++++++++++++++++++++-
   trunk/tools/build/v2/engine/rules.h | 2 +
   trunk/tools/build/v2/test/rescan_header.py | 56 ++++++++++++++++++++++++++++++++++++
   3 files changed, 115 insertions(+), 3 deletions(-)

Modified: trunk/tools/build/v2/engine/make1.c
==============================================================================
--- trunk/tools/build/v2/engine/make1.c (original)
+++ trunk/tools/build/v2/engine/make1.c 2012-04-28 18:05:28 EDT (Sat, 28 Apr 2012)
@@ -74,6 +74,7 @@
 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 @@
     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 @@
 #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 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 @@
                 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 @@
     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 @@
             }
 
             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 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 @@
     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;
+}

Modified: trunk/tools/build/v2/engine/rules.h
==============================================================================
--- trunk/tools/build/v2/engine/rules.h (original)
+++ trunk/tools/build/v2/engine/rules.h 2012-04-28 18:05:28 EDT (Sat, 28 Apr 2012)
@@ -212,6 +212,8 @@
 #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 */

Modified: trunk/tools/build/v2/test/rescan_header.py
==============================================================================
--- trunk/tools/build/v2/test/rescan_header.py (original)
+++ trunk/tools/build/v2/test/rescan_header.py 2012-04-28 18:05:28 EDT (Sat, 28 Apr 2012)
@@ -82,7 +82,7 @@
 
 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/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()


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk