$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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()