summaryrefslogtreecommitdiffstats
path: root/site_scons/site_tools/defer.py
diff options
context:
space:
mode:
authorbradnelson@chromium.org <bradnelson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-04 19:35:47 +0000
committerbradnelson@chromium.org <bradnelson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-04 19:35:47 +0000
commit5a17959168f700202c3ee498e88cca7bcfa43a97 (patch)
treef0c8d497ded5551516310cebec76c3395880c19c /site_scons/site_tools/defer.py
parentaedd85af7d7d0c90ed343ece4c66660db00841ec (diff)
downloadchromium_src-5a17959168f700202c3ee498e88cca7bcfa43a97.zip
chromium_src-5a17959168f700202c3ee498e88cca7bcfa43a97.tar.gz
chromium_src-5a17959168f700202c3ee498e88cca7bcfa43a97.tar.bz2
Pulling in hammer changes.
Review URL: http://codereview.chromium.org/13134 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@6370 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'site_scons/site_tools/defer.py')
-rw-r--r--site_scons/site_tools/defer.py71
1 files changed, 54 insertions, 17 deletions
diff --git a/site_scons/site_tools/defer.py b/site_scons/site_tools/defer.py
index 8b6de89..3da09ea 100644
--- a/site_scons/site_tools/defer.py
+++ b/site_scons/site_tools/defer.py
@@ -37,6 +37,11 @@ import types
import SCons.Errors
+# Current group name being executed by ExecuteDefer(). Set to None outside
+# of ExecuteDefer().
+_execute_defer_context = None
+
+
class DeferGroup:
"""Named list of functions to be deferred."""
# If we derive DeferGroup from object, instances of it return type
@@ -127,6 +132,11 @@ def ExecuteDefer(self):
Args:
self: Current environment context.
"""
+ # Check for re-entrancy
+ global _execute_defer_context
+ if _execute_defer_context:
+ raise SCons.Errors.UserError('Re-entrant call to ExecuteDefer().')
+
# Save directory, so SConscript functions can occur in the right subdirs
oldcwd = os.getcwd()
@@ -141,24 +151,39 @@ def ExecuteDefer(self):
defer_groups = GetDeferGroups(self)
# Loop through deferred functions
- while defer_groups:
- did_work = False
- for name, group in defer_groups.items():
- if group.after.intersection(defer_groups.keys()):
- continue # Still have dependencies
- if group.func_env_cwd:
- # Run all the functions in our named group
- for func, env, cwd in group.func_env_cwd:
- os.chdir(cwd)
- func(env)
- did_work = True
- del defer_groups[name]
- break
- if not did_work:
- errmsg = 'Error in ExecuteDefer: dependency cycle detected.\n'
+ try:
+ while defer_groups:
+ did_work = False
for name, group in defer_groups.items():
- errmsg += ' %s after: %s\n' % (name, group.after)
- raise SCons.Errors.UserError(errmsg)
+ if group.after.intersection(defer_groups.keys()):
+ continue # Still have dependencies
+
+ # Set defer context
+ _execute_defer_context = name
+
+ # Remove this group from the list of defer groups now, in case one of
+ # the functions it calls adds back a function into that defer group.
+ del defer_groups[name]
+
+ if group.func_env_cwd:
+ # Run all the functions in our named group
+ for func, env, cwd in group.func_env_cwd:
+ os.chdir(cwd)
+ func(env)
+
+ # The defer groups have been altered, so restart the search for
+ # functions that can be executed.
+ did_work = True
+ break
+
+ if not did_work:
+ errmsg = 'Error in ExecuteDefer: dependency cycle detected.\n'
+ for name, group in defer_groups.items():
+ errmsg += ' %s after: %s\n' % (name, group.after)
+ raise SCons.Errors.UserError(errmsg)
+ finally:
+ # No longer in a defer context
+ _execute_defer_context = None
# Restore directory
os.chdir(oldcwd)
@@ -272,6 +297,18 @@ def Defer(self, *args, **kwargs):
# Add dependencies for the function
group.after.update(after)
+ # If we are already inside a call to ExecuteDefer(), any functions which are
+ # deferring until after the current function must also be deferred until
+ # after this new function. In short, this means that if b() defers until
+ # after a() and a() calls Defer() to defer c(), then b() must also defer
+ # until after c().
+ if _execute_defer_context and name != _execute_defer_context:
+ for other_name, other_group in GetDeferGroups(self).items():
+ if other_name == name:
+ continue # Don't defer after ourselves
+ if _execute_defer_context in other_group.after:
+ other_group.after.add(name)
+
def generate(env):
# NOTE: SCons requires the use of this name, which fails gpylint.