summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2003-08-03 19:48:29 (GMT)
committerSteven Knight <knight@baldmt.com>2003-08-03 19:48:29 (GMT)
commit1a7fcd1d270120232358e875bf53a95194352204 (patch)
tree51ec6a084612a69f96c1ae5747757d3559bd7979
parent7500d447bdc3bd94db8ffbc8b90298fd9479e8c3 (diff)
downloadSCons-1a7fcd1d270120232358e875bf53a95194352204.zip
SCons-1a7fcd1d270120232358e875bf53a95194352204.tar.gz
SCons-1a7fcd1d270120232358e875bf53a95194352204.tar.bz2
Refactor extension splitting to make it more flexible (for SWIG).
-rw-r--r--doc/man/scons.133
-rw-r--r--src/CHANGES.txt3
-rw-r--r--src/engine/SCons/Builder.py48
-rw-r--r--src/engine/SCons/BuilderTests.py47
-rw-r--r--src/engine/SCons/Node/FS.py10
-rw-r--r--src/engine/SCons/Tool/gnulink.py2
-rw-r--r--src/engine/SCons/Tool/midl.py6
-rw-r--r--src/engine/SCons/Tool/msvc.py6
-rw-r--r--src/engine/SCons/Tool/msvs.py10
-rw-r--r--src/engine/SCons/Tool/qt.py13
10 files changed, 137 insertions, 41 deletions
diff --git a/doc/man/scons.1 b/doc/man/scons.1
index 3f5e4d5..862b65f 100644
--- a/doc/man/scons.1
+++ b/doc/man/scons.1
@@ -4901,9 +4901,42 @@ builder with the target.
.IP prefix
The prefix that will be prepended to the target file name.
+This may be a simple string, or a callable object that takes
+a construction environment as its argument
+and returns a prefix.
+
+.ES
+b = Builder("build_it < $SOURCE > $TARGET"
+ prefix = "file-")
+
+def gen_prefix(env):
+ return "file-" + env['PLATFORM'] + '-'
+b = Builder("build_it < $SOURCE > $TARGET"
+ prefix = gen_prefix)
+.EE
.IP suffix
The suffix that will be appended to the target file name.
+This may be a simple string, or a callable object that takes
+a construction environment as its argument
+and returns a suffix.
+If the suffix is a string, then
+.B scons
+will append a '.' to the beginning of the
+suffix if it's not already there.
+The string returned by callable object
+is untouched and must append its own '.'
+to the beginning if one is desired.
+
+.ES
+b = Builder("build_it < $SOURCE > $TARGET"
+ suffix = "file-"
+
+def gen_suffix(env):
+ return "." + env['PLATFORM'] + "-file"
+b = Builder("build_it < $SOURCE > $TARGET"
+ suffix = gen_suffix)
+.EE
.IP src_suffix
The expected source file name suffix.
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index acf7e88..9a1966d 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -77,6 +77,9 @@ RELEASE 0.XX - XXX
- Add /TP to the default CXXFLAGS for msvc, so it can compile all
of the suffixes we use as C++ files.
+ - Allow the "prefix" and "suffix" attributes of a Builder to be
+ callable objects that return generated strings.
+
From Gary Oberbrunner:
- Report the target being built in error messages when building
diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py
index 4b6464a..b7bc1a3 100644
--- a/src/engine/SCons/Builder.py
+++ b/src/engine/SCons/Builder.py
@@ -238,12 +238,6 @@ def _init_nodes(builder, env, overrides, tlist, slist):
if scanner:
s.source_scanner = scanner
-
-def _adjust_suffix(suff):
- if suff and not suff[0] in [ '.', '$' ]:
- return '.' + suff
- return suff
-
class EmitterProxy:
"""This is a callable class that can act as a
Builder emitter. It holds on to a string that
@@ -322,10 +316,13 @@ class BuilderBase:
def __cmp__(self, other):
return cmp(self.__dict__, other.__dict__)
+ def splitext(self, path):
+ return SCons.Util.splitext(path)
+
def _create_nodes(self, env, overrides, target = None, source = None):
"""Create and return lists of target and source nodes.
"""
- def adjustixes(files, pre, suf):
+ def adjustixes(files, pre, suf, self=self):
if not files:
return []
ret = []
@@ -339,7 +336,7 @@ class BuilderBase:
if fn[:len(pre)] != pre:
f = os.path.join(path, pre + fn)
# Only append a suffix if the file does not have one.
- if suf and not SCons.Util.splitext(f)[1]:
+ if suf and not self.splitext(f)[1]:
if f[-len(suf):] != suf:
f = f + suf
ret.append(f)
@@ -357,7 +354,7 @@ class BuilderBase:
if isinstance(s, SCons.Node.Node):
s = str(s)
dir, s = os.path.split(s)
- target = pre + os.path.splitext(s)[0] + suf
+ target = pre + self.splitext(s)[0] + suf
if dir:
target = [ os.path.join(dir, target) ]
else:
@@ -410,8 +407,27 @@ class BuilderBase:
return tlist
+ def adjust_suffix(self, suff):
+ if suff and not suff[0] in [ '.', '$' ]:
+ return '.' + suff
+ return suff
+
+ def get_prefix(self, env):
+ prefix = self.prefix
+ if callable(prefix):
+ prefix = prefix(env)
+ return env.subst(prefix)
+
+ def get_suffix(self, env):
+ suffix = self.suffix
+ if callable(suffix):
+ suffix = suffix(env)
+ else:
+ suffix = self.adjust_suffix(suffix)
+ return env.subst(suffix)
+
def src_suffixes(self, env):
- return map(lambda x, e=env: e.subst(_adjust_suffix(x)),
+ return map(lambda x, s=self, e=env: e.subst(s.adjust_suffix(x)),
self.src_suffix)
def set_src_suffix(self, src_suffix):
@@ -428,12 +444,6 @@ class BuilderBase:
return ''
return ret[0]
- def get_suffix(self, env):
- return env.subst(_adjust_suffix(self.suffix))
-
- def get_prefix(self, env):
- return env.subst(self.prefix)
-
def targets(self, node):
"""Return the list of targets for this builder instance.
@@ -532,15 +542,15 @@ class MultiStepBuilder(BuilderBase):
src_suffixes = self.src_suffixes(env)
for snode in slist:
- path, ext = SCons.Util.splitext(snode.get_abspath())
+ path, ext = self.splitext(snode.get_abspath())
if sdict.has_key(ext):
src_bld = sdict[ext]
tgt = apply(src_bld, (env, path, snode), kw)
# Only supply the builder with sources it is capable
# of building.
if SCons.Util.is_List(tgt):
- tgt = filter(lambda x, suf=src_suffixes:
- SCons.Util.splitext(SCons.Util.to_String(x))[1] in suf,
+ tgt = filter(lambda x, self=self, suf=src_suffixes:
+ self.splitext(SCons.Util.to_String(x))[1] in suf,
tgt)
if not SCons.Util.is_List(tgt):
final_sources.append(tgt)
diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py
index ded5354..a7c2f12 100644
--- a/src/engine/SCons/BuilderTests.py
+++ b/src/engine/SCons/BuilderTests.py
@@ -287,6 +287,37 @@ class BuilderTestCase(unittest.TestCase):
assert not builder.target_factory is FooFactory
assert builder.source_factory is FooFactory
+ def test_splitext(self):
+ """Test the splitext() method attached to a Builder."""
+ b = SCons.Builder.Builder()
+ assert b.splitext('foo') == ('foo','')
+ assert b.splitext('foo.bar') == ('foo','.bar')
+ assert b.splitext(os.path.join('foo.bar', 'blat')) == (os.path.join('foo.bar', 'blat'),'')
+
+ class MyBuilder(SCons.Builder.BuilderBase):
+ def splitext(self, path):
+ return "called splitext()"
+
+ b = MyBuilder()
+ ret = b.splitext('xyz.c')
+ assert ret == "called splitext()", ret
+
+ def test_adjust_suffix(self):
+ """Test how a Builder adjusts file suffixes
+ """
+ b = SCons.Builder.Builder()
+ assert b.adjust_suffix('.foo') == '.foo'
+ assert b.adjust_suffix('foo') == '.foo'
+ assert b.adjust_suffix('$foo') == '$foo'
+
+ class MyBuilder(SCons.Builder.BuilderBase):
+ def adjust_suffix(self, suff):
+ return "called adjust_suffix()"
+
+ b = MyBuilder()
+ ret = b.adjust_suffix('.foo')
+ assert ret == "called adjust_suffix()", ret
+
def test_prefix(self):
"""Test Builder creation with a specified target prefix
@@ -312,6 +343,14 @@ class BuilderTestCase(unittest.TestCase):
assert tgt.path == os.path.join('lib', 'libtgt5'), \
"Target has unexpected name: %s" % tgt.path
+ def gen_prefix(env):
+ return "gen_prefix() says " + env['FOO']
+ my_env = Environment(FOO = 'xyzzy')
+ builder = SCons.Builder.Builder(prefix = gen_prefix)
+ assert builder.get_prefix(my_env) == "gen_prefix() says xyzzy"
+ my_env['FOO'] = 'abracadabra'
+ assert builder.get_prefix(my_env) == "gen_prefix() says abracadabra"
+
def test_src_suffix(self):
"""Test Builder creation with a specified source file suffix
@@ -366,6 +405,14 @@ class BuilderTestCase(unittest.TestCase):
assert tgt.path == 'src5.o', \
"Target has unexpected name: %s" % tgt.path
+ def gen_suffix(env):
+ return "gen_suffix() says " + env['BAR']
+ my_env = Environment(BAR = 'hocus pocus')
+ builder = SCons.Builder.Builder(suffix = gen_suffix)
+ assert builder.get_suffix(my_env) == "gen_suffix() says hocus pocus", builder.get_suffix(my_env)
+ my_env['BAR'] = 'presto chango'
+ assert builder.get_suffix(my_env) == "gen_suffix() says presto chango"
+
def test_ListBuilder(self):
"""Testing ListBuilder class."""
def function2(target, source, env, tlist = [outfile, outfile2], **kw):
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 0951935..d12a504 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -232,12 +232,12 @@ class EntryProxy(SCons.Util.Proxy):
def __get_filebase(self):
name = self.get().name
- return SCons.Util.SpecialAttrWrapper(os.path.splitext(name)[0],
+ return SCons.Util.SpecialAttrWrapper(SCons.Util.splitext(name)[0],
name + "_filebase")
def __get_suffix(self):
name = self.get().name
- return SCons.Util.SpecialAttrWrapper(os.path.splitext(name)[1],
+ return SCons.Util.SpecialAttrWrapper(SCons.Util.splitext(name)[1],
name + "_suffix")
def __get_file(self):
@@ -248,7 +248,7 @@ class EntryProxy(SCons.Util.Proxy):
"""Return the file's directory and file name, with the
suffix stripped."""
entry = self.get()
- return SCons.Util.SpecialAttrWrapper(os.path.splitext(entry.get_path())[0],
+ return SCons.Util.SpecialAttrWrapper(SCons.Util.splitext(entry.get_path())[0],
entry.name + "_base")
def __get_posix_path(self):
@@ -499,7 +499,7 @@ class Entry(Base):
return node.get_found_includes(env, scanner, target)
def scanner_key(self):
- return os.path.splitext(self.name)[1]
+ return SCons.Util.splitext(self.name)[1]
def get_contents(self):
"""Fetch the contents of the entry.
@@ -1154,7 +1154,7 @@ class File(Base):
return self.dir.root()
def scanner_key(self):
- return os.path.splitext(self.name)[1]
+ return SCons.Util.splitext(self.name)[1]
def get_contents(self):
if not self.rexists():
diff --git a/src/engine/SCons/Tool/gnulink.py b/src/engine/SCons/Tool/gnulink.py
index 4c14383..0f92b35 100644
--- a/src/engine/SCons/Tool/gnulink.py
+++ b/src/engine/SCons/Tool/gnulink.py
@@ -45,7 +45,7 @@ linkers = ['g++', 'gcc', 'c++', 'cc']
def cxxSource(sources):
for s in sources:
- if os.path.splitext(str(s))[1] in cc.CXXSuffixes:
+ if SCons.Util.splitext(str(s))[1] in cc.CXXSuffixes:
return 1
if cxxSource(s.sources):
return 1
diff --git a/src/engine/SCons/Tool/midl.py b/src/engine/SCons/Tool/midl.py
index 77769db..a1f079b 100644
--- a/src/engine/SCons/Tool/midl.py
+++ b/src/engine/SCons/Tool/midl.py
@@ -33,13 +33,15 @@ selection method.
__revision__ = "__REVISION__"
+import os.path
+
import SCons.Defaults
import SCons.Scanner.IDL
-import os.path
+import SCons.Util
def midl_emitter(target, source, env):
"""Produces a list of outputs from the MIDL compiler"""
- base, ext = os.path.splitext(str(source[0]))
+ base, ext = SCons.Util.splitext(str(source[0]))
tlb = base + '.tlb'
incl = base + '.h'
interface = base + '_i.c'
diff --git a/src/engine/SCons/Tool/msvc.py b/src/engine/SCons/Tool/msvc.py
index 3d6f3ab..2c8a004 100644
--- a/src/engine/SCons/Tool/msvc.py
+++ b/src/engine/SCons/Tool/msvc.py
@@ -327,13 +327,13 @@ def pch_emitter(target, source, env):
obj = None
for t in target:
- if os.path.splitext(str(t))[1] == '.pch':
+ if SCons.Util.splitext(str(t))[1] == '.pch':
pch = t
- if os.path.splitext(str(t))[1] == '.obj':
+ if SCons.Util.splitext(str(t))[1] == '.obj':
obj = t
if not obj:
- obj = os.path.splitext(str(pch))[0]+'.obj'
+ obj = SCons.Util.splitext(str(pch))[0]+'.obj'
target = [pch, obj] # pch must be first, and obj second for the PCHCOM to work
diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py
index 1a9a7bb..40361a1 100644
--- a/src/engine/SCons/Tool/msvs.py
+++ b/src/engine/SCons/Tool/msvs.py
@@ -126,7 +126,7 @@ class _DSPGenerator:
if self.env.has_key('name'):
self.name = self.env['name']
else:
- self.name = os.path.basename(os.path.splitext(self.dspfile)[0])
+ self.name = os.path.basename(SCons.Util.splitext(self.dspfile)[0])
print "Adding '" + self.name + ' - ' + self.config.variant + "' to Visual Studio Project '" + str(dspfile) + "'"
@@ -515,7 +515,7 @@ class _DSWGenerator:
if self.env.has_key('name'):
self.name = self.env['name']
else:
- self.name = os.path.basename(os.path.splitext(self.dspfile)[0])
+ self.name = os.path.basename(SCons.Util.splitext(self.dspfile)[0])
def Build(self):
pass
@@ -961,19 +961,19 @@ def projectEmitter(target, source, env):
source = []
# make sure the suffix is correct for the version of MSVS we're running.
- (base, suff) = os.path.splitext(str(target[0]))
+ (base, suff) = SCons.Util.splitext(str(target[0]))
suff = env['MSVSPROJECTSUFFIX']
target[0] = base + suff
dspfile = SCons.Node.FS.default_fs.File(target[0]).srcnode()
- dswfile = SCons.Node.FS.default_fs.File(os.path.splitext(str(dspfile))[0] + env['MSVSSOLUTIONSUFFIX'])
+ dswfile = SCons.Node.FS.default_fs.File(SCons.Util.splitext(str(dspfile))[0] + env['MSVSSOLUTIONSUFFIX'])
if not source:
source = [SCons.Script.SConscript.stack[-1].sconscript.srcnode()]
source[0].attributes.sconstruct = SCons.Script.SConscript.stack[0].sconscript
- bdswpath = os.path.splitext(str(target[0]))[0] + env['MSVSSOLUTIONSUFFIX']
+ bdswpath = SCons.Util.splitext(str(target[0]))[0] + env['MSVSSOLUTIONSUFFIX']
bdswfile = SCons.Node.FS.default_fs.File(bdswpath)
# only make these side effects if they're
diff --git a/src/engine/SCons/Tool/qt.py b/src/engine/SCons/Tool/qt.py
index 65e7649..d9f690a 100644
--- a/src/engine/SCons/Tool/qt.py
+++ b/src/engine/SCons/Tool/qt.py
@@ -36,8 +36,9 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os.path
import re
-import SCons.Tool
import SCons.Defaults
+import SCons.Tool
+import SCons.Util
header_extensions = (".h", ".H", ".hxx", ".hpp", ".hh")
@@ -71,17 +72,17 @@ class _Automoc:
# out_sources contains at least all sources for the Library or Prog
out_sources = source[:]
for s in source:
- prefix, suffix = os.path.splitext(str(s))
+ prefix, suffix = SCons.Util.splitext(str(s))
# Nodes for header (h) / moc file (moc_cpp) / cpp file (cpp)
# and ui.h file (ui_h)
cpp = s.sources[0]
ui = None
if cpp.sources != None and len(cpp.sources) > 0:
- src_src_suffix = os.path.splitext(str(cpp.sources[0]))[1]
+ src_src_suffix = SCons.Util.splitext(str(cpp.sources[0]))[1]
if src_src_suffix == env.subst('$QT_UISUFFIX'):
ui = cpp.sources[0]
- src_prefix, src_suffix = os.path.splitext(str(cpp.srcnode()))
+ src_prefix, src_suffix = SCons.Util.splitext(str(cpp.srcnode()))
h=None
for h_ext in header_extensions:
if os.path.exists(src_prefix + h_ext):
@@ -99,7 +100,7 @@ class _Automoc:
if (h and q_object_search.search(h.get_contents())) or ui:
# h file with the Q_OBJECT macro found -> add moc_cpp
dir,base = os.path.split(prefix)
- src_ext = os.path.splitext(str(h))[1]
+ src_ext = SCons.Util.splitext(str(h))[1]
moc_cpp = SCons.Node.FS.default_fs.File(os.path.join(dir,
env['QT_MOCNAMEGENERATOR'](base, src_ext, env)))
moc_o = self.objBuilder(source=moc_cpp)
@@ -111,7 +112,7 @@ class _Automoc:
# cpp file with Q_OBJECT macro found -> add moc
# (to be included in cpp)
dir,base = os.path.split(prefix)
- src_ext = os.path.splitext(str(cpp))[1]
+ src_ext = SCons.Util.splitext(str(cpp))[1]
moc = SCons.Node.FS.default_fs.File(os.path.join(dir,
env['QT_MOCNAMEGENERATOR'](base, src_ext, env)))
self.mocFromCppBld(env, moc, cpp)