summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2004-03-05 09:49:04 (GMT)
committerSteven Knight <knight@baldmt.com>2004-03-05 09:49:04 (GMT)
commitaede9c91b7e76c5dd1bf90d7677d10592f9a9ba5 (patch)
treebc5b96fdcd04e1f2bda812416b47d940dfe828ed /src
parentbb42c27bfa1a4208fc3cdc7b583b8093305fc4c0 (diff)
downloadSCons-aede9c91b7e76c5dd1bf90d7677d10592f9a9ba5.zip
SCons-aede9c91b7e76c5dd1bf90d7677d10592f9a9ba5.tar.gz
SCons-aede9c91b7e76c5dd1bf90d7677d10592f9a9ba5.tar.bz2
Fix use of things like ${TARGET.dir} in *PATH expansions.
Diffstat (limited to 'src')
-rw-r--r--src/CHANGES.txt2
-rw-r--r--src/engine/SCons/Environment.py51
-rw-r--r--src/engine/SCons/EnvironmentTests.py16
-rw-r--r--src/engine/SCons/Util.py35
-rw-r--r--src/engine/SCons/UtilTests.py26
5 files changed, 102 insertions, 28 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 76f08b5..1060939 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -192,6 +192,8 @@ RELEASE 0.95 - XXX
- Initialize all *FLAGS variables with objects do the right thing with
appending flags as strings or lists.
+ - Make things like ${TARGET.dir} work in *PATH construction variables.
+
From Vincent Risi:
- Add support for the bcc32, ilink32 and tlib Borland tools.
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py
index 2235ace..da455bc 100644
--- a/src/engine/SCons/Environment.py
+++ b/src/engine/SCons/Environment.py
@@ -366,17 +366,17 @@ class Base:
return scanner
return None
- def subst(self, string, raw=0, target=None, source=None, dict=None):
- """Recursively interpolates construction variables from the
- Environment into the specified string, returning the expanded
- result. Construction variables are specified by a $ prefix
- in the string and begin with an initial underscore or
- alphabetic character followed by any number of underscores
- or alphanumeric characters. The construction variable names
- may be surrounded by curly braces to separate the name from
- trailing characters.
- """
- return SCons.Util.scons_subst(string, self, raw, target, source, dict)
+ def subst(self, string, raw=0, target=None, source=None, dict=None, conv=None):
+ """Recursively interpolates construction variables from the
+ Environment into the specified string, returning the expanded
+ result. Construction variables are specified by a $ prefix
+ in the string and begin with an initial underscore or
+ alphabetic character followed by any number of underscores
+ or alphanumeric characters. The construction variable names
+ may be surrounded by curly braces to separate the name from
+ trailing characters.
+ """
+ return SCons.Util.scons_subst(string, self, raw, target, source, dict, conv)
def subst_kw(self, kw, raw=0, target=None, source=None, dict=None):
nkw = {}
@@ -387,21 +387,42 @@ class Base:
nkw[k] = v
return nkw
- def subst_list(self, string, raw=0, target=None, source=None, dict=None):
+ def subst_list(self, string, raw=0, target=None, source=None, dict=None, conv=None):
"""Calls through to SCons.Util.scons_subst_list(). See
the documentation for that function."""
- return SCons.Util.scons_subst_list(string, self, raw, target, source, dict)
+ return SCons.Util.scons_subst_list(string, self, raw, target, source, dict, conv)
+
def subst_path(self, path):
- """Substitute a path list."""
+ """Substitute a path list, turning EntryProxies into Nodes
+ and leaving Nodes (and other objects) as-is."""
if not SCons.Util.is_List(path):
path = [path]
+ def s(obj):
+ """This is the "string conversion" routine that we have our
+ substitutions use to return Nodes, not strings. This relies
+ on the fact that an EntryProxy object has a get() method that
+ returns the underlying Node that it wraps, which is a bit of
+ architectural dependence that we might need to break or modify
+ in the future in response to additional requirements."""
+ try:
+ get = obj.get
+ except AttributeError:
+ pass
+ else:
+ obj = get()
+ return obj
+
r = []
for p in path:
if SCons.Util.is_String(p):
- p = self.subst(p)
+ p = self.subst(p, conv=s)
+ if SCons.Util.is_List(p):
+ p = p[0]
+ else:
+ p = s(p)
r.append(p)
return r
diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py
index 45f5fdb..d450075 100644
--- a/src/engine/SCons/EnvironmentTests.py
+++ b/src/engine/SCons/EnvironmentTests.py
@@ -419,7 +419,16 @@ class EnvironmentTestCase(unittest.TestCase):
def test_subst_path(self):
"""Test substituting a path list
"""
- env = Environment(FOO='foo', BAR='bar')
+ class MyProxy:
+ def __init__(self, val):
+ self.val = val
+ def get(self):
+ return self.val + '-proxy'
+
+ class MyObj:
+ pass
+
+ env = Environment(FOO='foo', BAR='bar', PROXY=MyProxy('my1'))
r = env.subst_path('$FOO')
assert r == ['foo'], r
@@ -427,6 +436,11 @@ class EnvironmentTestCase(unittest.TestCase):
r = env.subst_path(['$FOO', 'xxx', '$BAR'])
assert r == ['foo', 'xxx', 'bar'], r
+ n = MyObj()
+
+ r = env.subst_path(['$PROXY', MyProxy('my2'), n])
+ assert r == ['my1-proxy', 'my2-proxy', n], r
+
def test_Builder_calls(self):
"""Test Builder calls through different environments
"""
diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py
index 97ba8b5..1722f3a 100644
--- a/src/engine/SCons/Util.py
+++ b/src/engine/SCons/Util.py
@@ -501,7 +501,7 @@ _separate_args = re.compile(r'(\$[\$\(\)]|\$[_a-zA-Z][\.\w]*|\${[^}]*}|\s+|[^\s\
# space characters in the string result from the scons_subst() function.
_space_sep = re.compile(r'[\t ]+(?![^{]*})')
-def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, dict=None):
+def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, dict=None, conv=None):
"""Expand a string containing construction variable substitutions.
This is the work-horse function for substitutions in file names
@@ -516,14 +516,14 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, dict=No
source with two methods (substitute() and expand()) that handle
the expansion.
"""
- def __init__(self, env, mode, target, source):
+ def __init__(self, env, mode, target, source, conv):
self.env = env
self.mode = mode
self.target = target
self.source = source
self.gvars = env.Dictionary()
- self.str = _strconv[mode]
+ self.conv = conv
def expand(self, s, lvars):
"""Expand a single "token" as necessary, returning an
@@ -570,7 +570,7 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, dict=No
elif is_List(s):
r = []
for l in s:
- r.append(self.str(self.substitute(l, lvars)))
+ r.append(self.conv(self.substitute(l, lvars)))
return string.join(r)
elif callable(s):
s = s(target=self.target,
@@ -593,15 +593,21 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, dict=No
args = _separate_args.findall(args)
result = []
for a in args:
- result.append(self.str(self.expand(a, lvars)))
- return string.join(result, '')
+ result.append(self.conv(self.expand(a, lvars)))
+ try:
+ result = string.join(result, '')
+ except TypeError:
+ pass
+ return result
else:
return self.expand(args, lvars)
if dict is None:
dict = subst_dict(target, source)
+ if conv is None:
+ conv = _strconv[mode]
- ss = StringSubber(env, mode, target, source)
+ ss = StringSubber(env, mode, target, source, conv)
result = ss.substitute(strSubst, dict)
if is_String(result):
@@ -617,7 +623,7 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, dict=No
return result
-def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, dict=None):
+def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, dict=None, conv=None):
"""Substitute construction variables in a string (or list or other
object) and separate the arguments into a command list.
@@ -641,7 +647,7 @@ def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, di
and the rest of the object takes care of doing the right thing
internally.
"""
- def __init__(self, env, mode, target, source):
+ def __init__(self, env, mode, target, source, conv):
UserList.UserList.__init__(self, [])
self.env = env
self.mode = mode
@@ -654,7 +660,7 @@ def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, di
self.add_strip = lambda x, s=self: s.append(x)
else:
self.add_strip = lambda x, s=self: None
- self.str = _strconv[mode]
+ self.conv = conv
self.in_strip = None
self.next_line()
@@ -768,7 +774,10 @@ def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, di
literal = None
else:
literal = l()
- self[-1].append(CmdStringHolder(self.str(x), literal))
+ x = self.conv(x)
+ if is_String(x):
+ x = CmdStringHolder(x, literal)
+ self[-1].append(x)
self.append = self.add_to_current_word
def open_strip(self, x):
@@ -782,8 +791,10 @@ def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, di
if dict is None:
dict = subst_dict(target, source)
+ if conv is None:
+ conv = _strconv[mode]
- ls = ListSubber(env, mode, target, source)
+ ls = ListSubber(env, mode, target, source, conv)
ls.substitute(strSubst, dict, 0)
return ls.data
diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py
index c96f124..38e8c30 100644
--- a/src/engine/SCons/UtilTests.py
+++ b/src/engine/SCons/UtilTests.py
@@ -429,6 +429,19 @@ class UtilTestCase(unittest.TestCase):
else:
raise AssertionError, "did not catch expected UserError"
+ # Test we handle overriding the internal conversion routines.
+ def s(obj):
+ return obj
+
+ n1 = MyNode('n1')
+ env = DummyEnv({'NODE' : n1})
+ node = scons_subst("$NODE", env, mode=SUBST_RAW, conv=s)
+ assert node == [n1], node
+ node = scons_subst("$NODE", env, mode=SUBST_CMD, conv=s)
+ assert node == [n1], node
+ node = scons_subst("$NODE", env, mode=SUBST_SIG, conv=s)
+ assert node == [n1], node
+
# Test returning a function.
#env = DummyEnv({'FUNCTION' : foo})
#func = scons_subst("$FUNCTION", env, mode=SUBST_RAW, call=None)
@@ -771,6 +784,19 @@ class UtilTestCase(unittest.TestCase):
else:
raise AssertionError, "did not catch expected SyntaxError"
+ # Test we handle overriding the internal conversion routines.
+ def s(obj):
+ return obj
+
+ n1 = MyNode('n1')
+ env = DummyEnv({'NODE' : n1})
+ node = scons_subst_list("$NODE", env, mode=SUBST_RAW, conv=s)
+ assert node == [[n1]], node
+ node = scons_subst_list("$NODE", env, mode=SUBST_CMD, conv=s)
+ assert node == [[n1]], node
+ node = scons_subst_list("$NODE", env, mode=SUBST_SIG, conv=s)
+ assert node == [[n1]], node
+
def test_subst_once(self):
"""Testing the scons_subst_once() method"""