diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CHANGES.txt | 4 | ||||
-rw-r--r-- | src/engine/SCons/Action.py | 26 | ||||
-rw-r--r-- | src/engine/SCons/ActionTests.py | 11 | ||||
-rw-r--r-- | src/engine/SCons/Builder.py | 5 | ||||
-rw-r--r-- | src/engine/SCons/BuilderTests.py | 12 | ||||
-rw-r--r-- | src/engine/SCons/Node/FS.py | 4 | ||||
-rw-r--r-- | src/engine/SCons/Node/__init__.py | 5 | ||||
-rw-r--r-- | src/engine/SCons/Util.py | 13 | ||||
-rw-r--r-- | src/engine/SCons/UtilTests.py | 34 |
9 files changed, 94 insertions, 20 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 462e06a..44946a0 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -38,6 +38,10 @@ RELEASE 0.04 - - The C Scanner now always returns a sorted list of dependencies so order changes don't cause unnecessary rebuilds. + - Strip $(-$) bracketed text from command lines. Use this to + surround $_INCDIRS and $_LIBDIRS so we don't rebuild in response + to changes to -I or -L options. + From Steve Leblanc: - Add var=value command-line arguments. 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: |