Index: pylib/gyp/input.py |
diff --git a/pylib/gyp/input.py b/pylib/gyp/input.py |
index f694e57b9fe455197bcd5eb423c48b66a8f0376e..ff88c7b4249e7833910b1ece857461b347c5db03 100644 |
--- a/pylib/gyp/input.py |
+++ b/pylib/gyp/input.py |
@@ -1000,6 +1000,58 @@ def ExpandVariables(input, phase, variables, build_file): |
return output |
+# The same condition is often evaluated over and over again so it |
+# makes sense to cache as much as possible between evaluations. |
+cached_conditions_asts = {} |
+ |
+def EvalCondition(condition, conditions_key, phase, variables, build_file): |
+ """Returns the dict that should be used or None if the result was |
+ that nothing should be used.""" |
+ if not isinstance(condition, list): |
+ raise GypError(conditions_key + ' must be a list') |
+ if len(condition) != 2 and len(condition) != 3: |
+ # It's possible that condition[0] won't work in which case this |
+ # attempt will raise its own IndexError. That's probably fine. |
+ raise GypError(conditions_key + ' ' + condition[0] + |
+ ' must be length 2 or 3, not ' + str(len(condition))) |
+ |
+ [cond_expr, true_dict] = condition[0:2] |
+ false_dict = None |
+ if len(condition) == 3: |
+ false_dict = condition[2] |
+ |
+ # Do expansions on the condition itself. Since the conditon can naturally |
+ # contain variable references without needing to resort to GYP expansion |
+ # syntax, this is of dubious value for variables, but someone might want to |
+ # use a command expansion directly inside a condition. |
+ cond_expr_expanded = ExpandVariables(cond_expr, phase, variables, |
+ build_file) |
+ if not isinstance(cond_expr_expanded, str) and \ |
+ not isinstance(cond_expr_expanded, int): |
+ raise ValueError, \ |
+ 'Variable expansion in this context permits str and int ' + \ |
+ 'only, found ' + cond_expr_expanded.__class__.__name__ |
+ |
+ try: |
+ if cond_expr_expanded in cached_conditions_asts: |
+ ast_code = cached_conditions_asts[cond_expr_expanded] |
+ else: |
+ ast_code = compile(cond_expr_expanded, '<string>', 'eval') |
+ cached_conditions_asts[cond_expr_expanded] = ast_code |
+ if eval(ast_code, {'__builtins__': None}, variables): |
+ return true_dict |
+ return false_dict |
+ except SyntaxError, e: |
+ syntax_error = SyntaxError('%s while evaluating condition \'%s\' in %s ' |
+ 'at character %d.' % |
+ (str(e.args[0]), e.text, build_file, e.offset), |
+ e.filename, e.lineno, e.offset, e.text) |
+ raise syntax_error |
+ except NameError, e: |
+ gyp.common.ExceptionAppend(e, 'while evaluating condition \'%s\' in %s' % |
+ (cond_expr_expanded, build_file)) |
+ raise GypError(e) |
+ |
def ProcessConditionsInDict(the_dict, phase, variables, build_file): |
# Process a 'conditions' or 'target_conditions' section in the_dict, |
@@ -1035,48 +1087,8 @@ def ProcessConditionsInDict(the_dict, phase, variables, build_file): |
del the_dict[conditions_key] |
for condition in conditions_list: |
- if not isinstance(condition, list): |
- raise GypError(conditions_key + ' must be a list') |
- if len(condition) != 2 and len(condition) != 3: |
- # It's possible that condition[0] won't work in which case this |
- # attempt will raise its own IndexError. That's probably fine. |
- raise GypError(conditions_key + ' ' + condition[0] + |
- ' must be length 2 or 3, not ' + str(len(condition))) |
- |
- [cond_expr, true_dict] = condition[0:2] |
- false_dict = None |
- if len(condition) == 3: |
- false_dict = condition[2] |
- |
- # Do expansions on the condition itself. Since the conditon can naturally |
- # contain variable references without needing to resort to GYP expansion |
- # syntax, this is of dubious value for variables, but someone might want to |
- # use a command expansion directly inside a condition. |
- cond_expr_expanded = ExpandVariables(cond_expr, phase, variables, |
- build_file) |
- if not isinstance(cond_expr_expanded, str) and \ |
- not isinstance(cond_expr_expanded, int): |
- raise ValueError, \ |
- 'Variable expansion in this context permits str and int ' + \ |
- 'only, found ' + expanded.__class__.__name__ |
- |
- try: |
- ast_code = compile(cond_expr_expanded, '<string>', 'eval') |
- |
- if eval(ast_code, {'__builtins__': None}, variables): |
- merge_dict = true_dict |
- else: |
- merge_dict = false_dict |
- except SyntaxError, e: |
- syntax_error = SyntaxError('%s while evaluating condition \'%s\' in %s ' |
- 'at character %d.' % |
- (str(e.args[0]), e.text, build_file, e.offset), |
- e.filename, e.lineno, e.offset, e.text) |
- raise syntax_error |
- except NameError, e: |
- gyp.common.ExceptionAppend(e, 'while evaluating condition \'%s\' in %s' % |
- (cond_expr_expanded, build_file)) |
- raise GypError(e) |
+ merge_dict = EvalCondition(condition, conditions_key, phase, variables, |
+ build_file) |
if merge_dict != None: |
# Expand variables and nested conditinals in the merge_dict before |