summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/SCons')
-rw-r--r--src/engine/SCons/Action.py26
-rw-r--r--src/engine/SCons/ActionTests.py11
-rw-r--r--src/engine/SCons/Builder.py5
-rw-r--r--src/engine/SCons/BuilderTests.py12
-rw-r--r--src/engine/SCons/Node/FS.py4
-rw-r--r--src/engine/SCons/Node/__init__.py5
-rw-r--r--src/engine/SCons/Util.py13
-rw-r--r--src/engine/SCons/UtilTests.py34
8 files changed, 90 insertions, 20 deletions
diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py
index 38a4c70..26e81a5 100644
--- a/src/engine/SCons/Action.py
+++ b/src/engine/SCons/Action.py
@@ -31,6 +31,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
import os.path
+import re
import string
import sys
@@ -238,6 +239,9 @@ class ActionBase:
return dict
+_rm = re.compile(r'\$[()]')
+_remove = re.compile(r'\$\(([^\$]|\$[^\(])*?\$\)')
+
class CommandAction(ActionBase):
"""Class for command-execution actions."""
def __init__(self, string):
@@ -246,7 +250,7 @@ class CommandAction(ActionBase):
def execute(self, **kw):
import SCons.Util
dict = apply(self.subst_dict, (), kw)
- cmd_list = SCons.Util.scons_subst_list(self.command, dict, {})
+ cmd_list = SCons.Util.scons_subst_list(self.command, dict, {}, _rm)
for cmd_line in cmd_list:
if len(cmd_line):
if print_actions:
@@ -262,8 +266,8 @@ class CommandAction(ActionBase):
return ret
return 0
- def get_contents(self, **kw):
- """Return the signature contents of this action's command line.
+ def _sig_dict(self, kw):
+ """Supply a dictionary for use in computing signatures.
For signature purposes, it doesn't matter what targets or
sources we use, so long as we use the same ones every time
@@ -272,8 +276,20 @@ class CommandAction(ActionBase):
"""
kw['target'] = ['__t1__', '__t2__']
kw['source'] = ['__s1__', '__s2__']
- dict = apply(self.subst_dict, (), kw)
- return SCons.Util.scons_subst(self.command, dict, {})
+ return apply(self.subst_dict, (), kw)
+
+ def get_raw_contents(self, **kw):
+ """Return the complete contents of this action's command line.
+ """
+ return SCons.Util.scons_subst(self.command, self._sig_dict(kw), {})
+
+ def get_contents(self, **kw):
+ """Return the signature contents of this action's command line.
+
+ This strips $(-$) and everything in between the string,
+ since those parts don't affect signatures.
+ """
+ return SCons.Util.scons_subst(self.command, self._sig_dict(kw), {}, _remove)
class FunctionAction(ActionBase):
"""Class for Python function actions."""
diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py
index a70fd99..30bf093 100644
--- a/src/engine/SCons/ActionTests.py
+++ b/src/engine/SCons/ActionTests.py
@@ -125,12 +125,19 @@ class CommandActionTestCase(unittest.TestCase):
a.execute()
assert t.executed == 1
+ def test_get_raw_contents(self):
+ """Test fetching the contents of a command Action
+ """
+ a = SCons.Action.CommandAction("| $( $foo | $bar $) |")
+ c = a.get_contents(foo = 'FFF', bar = 'BBB')
+ assert c == "| $( FFF | BBB $) |"
+
def test_get_contents(self):
"""Test fetching the contents of a command Action
"""
- a = SCons.Action.CommandAction("| $foo | $bar |")
+ a = SCons.Action.CommandAction("| $foo $( | $) $bar |")
c = a.get_contents(foo = 'FFF', bar = 'BBB')
- assert c == "| FFF | BBB |"
+ assert c == "| FFF BBB |"
class FunctionActionTestCase(unittest.TestCase):
diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py
index db1e701..6fffeee 100644
--- a/src/engine/SCons/Builder.py
+++ b/src/engine/SCons/Builder.py
@@ -145,6 +145,11 @@ class BuilderBase:
"""
return apply(self.action.execute, (), kw)
+ def get_raw_contents(self, **kw):
+ """Fetch the "contents" of the builder's action.
+ """
+ return apply(self.action.get_raw_contents, (), kw)
+
def get_contents(self, **kw):
"""Fetch the "contents" of the builder's action
(for signature calculation).
diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py
index e383ee1..65aa934 100644
--- a/src/engine/SCons/BuilderTests.py
+++ b/src/engine/SCons/BuilderTests.py
@@ -349,8 +349,11 @@ class BuilderTestCase(unittest.TestCase):
'INCPREFIX' : '-I',
'INCSUFFIX' : ''}
+ contents = apply(b4.get_raw_contents, (), kw)
+ assert contents == "-ll1 -ll2 $( -LlibX $) $( -Ic -Ip $)", contents
+
contents = apply(b4.get_contents, (), kw)
- assert contents == "-ll1 -ll2 -LlibX -Ic -Ip", contents
+ assert contents == "-ll1 -ll2", "'%s'" % contents
# SCons.Node.FS has been imported by our import of
# SCons.Node.Builder. It's kind of bogus that we don't
@@ -358,8 +361,13 @@ class BuilderTestCase(unittest.TestCase):
# maybe a little cleaner than tying these tests directly
# to the other module via a direct import.
kw['dir'] = SCons.Node.FS.default_fs.Dir('d')
+
+ contents = apply(b4.get_raw_contents, (), kw)
+ expect = os.path.normpath("-ll1 -ll2 $( -Ld/libX $) $( -Id/c -Id/p $)")
+ assert contents == expect, contents + " != " + expect
+
contents = apply(b4.get_contents, (), kw)
- expect = os.path.normpath("-ll1 -ll2 -Ld/libX -Id/c -Id/p")
+ expect = os.path.normpath("-ll1 -ll2")
assert contents == expect, contents + " != " + expect
def test_node_factory(self):
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 66b7314..96ce148 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -162,6 +162,7 @@ class FS:
except KeyError:
dir_temp = Dir(path_name, directory)
directory.entries[path_norm] = dir_temp
+ directory.add_wkid(dir_temp)
directory = dir_temp
file_name = _my_normcase(path_comp[-1])
try:
@@ -169,6 +170,7 @@ class FS:
except KeyError:
ret = fsclass(path_comp[-1], directory)
directory.entries[file_name] = ret
+ directory.add_wkid(ret)
return ret
def __transformPath(self, name, directory):
@@ -431,7 +433,7 @@ class Dir(Entry):
if s and (not state or s > state):
state = s
import SCons.Node
- if state == SCons.Node.up_to_date:
+ if state == 0 or state == SCons.Node.up_to_date:
return 1
else:
return 0
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index b11027f..f2d379f 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -190,6 +190,11 @@ class Node:
if parent not in self.parents: self.parents.append(parent)
+ def add_wkid(self, wkid):
+ """Add a node to the list of kids waiting to be evaluated"""
+ if self.wkids != None:
+ self.wkids.append(wkid)
+
def children(self):
#XXX Need to remove duplicates from this
return self.sources \
diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py
index a207ffc..16d2c76 100644
--- a/src/engine/SCons/Util.py
+++ b/src/engine/SCons/Util.py
@@ -170,7 +170,7 @@ class PathList(UserList.UserList):
_cv = re.compile(r'\$([_a-zA-Z]\w*|{[^}]*})')
_space_sep = re.compile(r'[\t ]+(?![^{]*})')
-def scons_subst_list(strSubst, locals, globals):
+def scons_subst_list(strSubst, locals, globals, remove=None):
"""
This function is similar to scons_subst(), but with
one important difference. Instead of returning a single
@@ -214,10 +214,12 @@ def scons_subst_list(strSubst, locals, globals):
strSubst, n = _cv.subn(repl, strSubst)
# Now parse the whole list into tokens.
listLines = string.split(strSubst, '\n')
+ if remove:
+ listLines = map(lambda x,re=remove: re.sub('', x), listLines)
return map(lambda x: filter(lambda y: y, string.split(x, '\0')),
listLines)
-def scons_subst(strSubst, locals, globals):
+def scons_subst(strSubst, locals, globals, remove=None):
"""Recursively interpolates dictionary variables into
the specified string, returning the expanded result.
Variables are specified by a $ prefix in the string and
@@ -227,7 +229,7 @@ def scons_subst(strSubst, locals, globals):
surrounded by curly braces to separate the name from
trailing characters.
"""
- cmd_list = scons_subst_list(strSubst, locals, globals)
+ cmd_list = scons_subst_list(strSubst, locals, globals, remove)
return string.join(map(string.join, cmd_list), '\n')
def find_files(filenames, paths,
@@ -351,6 +353,11 @@ class DirVarInterp(VarInterpolator):
self.dictInstCache[(dir, fs)] = ret
return ret
+ def generate(self, dict):
+ VarInterpolator.generate(self, dict)
+ if dict[self.dest]:
+ dict[self.dest] = ['$('] + dict[self.dest] + ['$)']
+
AUTO_GEN_VARS = ( VarInterpolator('_LIBFLAGS',
'LIBS',
'LIBLINKPREFIX',
diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py
index e9e763c..ed72ebb 100644
--- a/src/engine/SCons/UtilTests.py
+++ b/src/engine/SCons/UtilTests.py
@@ -25,6 +25,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
import os.path
+import re
import string
import sys
import unittest
@@ -127,6 +128,21 @@ class UtilTestCase(unittest.TestCase):
newcom = scons_subst("test $xxx", loc, {})
assert newcom == cvt("test"), newcom
+ newcom = scons_subst("test $($xxx$)", loc, {})
+ assert newcom == cvt("test $($)"), newcom
+
+ newcom = scons_subst("test $( $xxx $)", loc, {})
+ assert newcom == cvt("test $( $)"), newcom
+
+ newcom = scons_subst("test $($xxx$)", loc, {}, re.compile('\$[()]'))
+ assert newcom == cvt("test"), newcom
+
+ newcom = scons_subst("test $( $xxx $)", loc, {}, re.compile('\$[()]'))
+ assert newcom == cvt("test"), newcom
+
+ newcom = scons_subst("test aXbXcXd", loc, {}, re.compile('X'))
+ assert newcom == cvt("test abcd"), newcom
+
def test_subst_list(self):
"""Testing the scons_subst_list() method..."""
loc = {}
@@ -196,18 +212,22 @@ class UtilTestCase(unittest.TestCase):
'INCSUFFIX' : 'bar',
'FOO' : 'baz' }
autogenerate(dict, dir = SCons.Node.FS.default_fs.Dir('/xx'))
- assert len(dict['_INCFLAGS']) == 5, dict['_INCFLAGS']
- assert dict['_INCFLAGS'][0] == os.path.normpath('foo/xx/foobar'), \
+ assert len(dict['_INCFLAGS']) == 7, dict['_INCFLAGS']
+ assert dict['_INCFLAGS'][0] == '$(', \
dict['_INCFLAGS'][0]
- assert dict['_INCFLAGS'][1] == os.path.normpath('foo/xx/barbar'), \
+ assert dict['_INCFLAGS'][1] == os.path.normpath('foo/xx/foobar'), \
dict['_INCFLAGS'][1]
- assert dict['_INCFLAGS'][2] == os.path.normpath('foo/xx/bazbar'), \
+ assert dict['_INCFLAGS'][2] == os.path.normpath('foo/xx/barbar'), \
dict['_INCFLAGS'][2]
- assert dict['_INCFLAGS'][3] == os.path.normpath('foo/xx/baz/barbar'), \
+ assert dict['_INCFLAGS'][3] == os.path.normpath('foo/xx/bazbar'), \
dict['_INCFLAGS'][3]
-
- assert dict['_INCFLAGS'][4] == os.path.normpath('fooblatbar'), \
+ assert dict['_INCFLAGS'][4] == os.path.normpath('foo/xx/baz/barbar'), \
dict['_INCFLAGS'][4]
+
+ assert dict['_INCFLAGS'][5] == os.path.normpath('fooblatbar'), \
+ dict['_INCFLAGS'][5]
+ assert dict['_INCFLAGS'][6] == '$)', \
+ dict['_INCFLAGS'][6]
def test_render_tree(self):
class Node: