summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/man/scons.127
-rw-r--r--src/CHANGES.txt4
-rw-r--r--src/engine/SCons/Action.py7
-rw-r--r--src/engine/SCons/ActionTests.py23
-rw-r--r--src/engine/SCons/Defaults.py6
-rw-r--r--test/AS/AS.py (renamed from test/AS.py)0
-rw-r--r--test/AS/ASCOM.py81
-rw-r--r--test/AS/ASCOMSTR.py88
-rw-r--r--test/AS/ASFLAGS.py (renamed from test/ASFLAGS.py)0
-rw-r--r--test/CC/CC.py (renamed from test/CC.py)0
-rw-r--r--test/CC/CCCOM.py81
-rw-r--r--test/CC/CCCOMSTR.py86
-rw-r--r--test/CC/CCFLAGS.py (renamed from test/CCFLAGS.py)0
-rw-r--r--test/CXX/CXX.py (renamed from test/CXX.py)0
-rw-r--r--test/CXX/CXXCOM.py81
-rw-r--r--test/CXX/CXXCOMSTR.py86
-rw-r--r--test/CXX/CXXFILESUFFIX.py (renamed from test/CXXFILESUFFIX.py)0
17 files changed, 566 insertions, 4 deletions
diff --git a/doc/man/scons.1 b/doc/man/scons.1
index 59e0d62..b2ccd71 100644
--- a/doc/man/scons.1
+++ b/doc/man/scons.1
@@ -4441,6 +4441,15 @@ The assembler.
The command line used to generate an object file
from an assembly-language source file.
+.IP ASCOMSTR
+The string displayed when an object file
+is generated from an assembly-language source file.
+If this is not set, then $ASCOM (the command line) is displayed.
+
+.ES
+env = Environment(ASCOMSTR = "Assembling $TARGET")
+.EE
+
.IP ASFLAGS
General options passed to the assembler.
@@ -4518,6 +4527,15 @@ The command line used to compile a C source file to a (static) object file.
Any options specified in the $CCFLAGS and $CPPFLAGS construction variables
are included on this command line.
+.IP CCCOMSTR
+The string displayed when a C source file
+is compiled to a (static) object file.
+If this is not set, then $CCCOM (the command line) is displayed.
+
+.ES
+env = Environment(CCCOMSTR = "Compiling $TARGET")
+.EE
+
.IP CCFLAGS
General options that are passed to the C compiler.
@@ -4773,6 +4791,15 @@ The command line used to compile a C++ source file to an object file.
Any options specified in the $CXXFLAGS and $CPPFLAGS construction variables
are included on this command line.
+.IP CXXCOMSTR
+The string displayed when a C++ source file
+is compiled to a (static) object file.
+If this is not set, then $CXXCOM (the command line) is displayed.
+
+.ES
+env = Environment(CXXCOMSTR = "Compiling $TARGET")
+.EE
+
.IP CXXFLAGS
General options that are passed to the C++ compiler.
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 4755f18..b84f25a 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -130,6 +130,10 @@ RELEASE 0.97 - XXX
- Fix expansion of env.Command() overrides within target and
source file names.
+ - Support easier configurability of what's displayed by various default
+ actions through new construction variables: $ASCOMSTR, $CCCOMSTR,
+ $CXXCOMSTR.
+
From Wayne Lee:
- Avoid "maximum recursion limit" errors when removing $(-$) pairs
diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py
index a8e6c5b..545bd61 100644
--- a/src/engine/SCons/Action.py
+++ b/src/engine/SCons/Action.py
@@ -323,7 +323,7 @@ def _string_from_cmd_list(cmd_list):
class CommandAction(_ActionAction):
"""Class for command-execution actions."""
- def __init__(self, cmd, *args, **kw):
+ def __init__(self, cmd, cmdstr=None, *args, **kw):
# Cmd can actually be a list or a single item; if it's a
# single item it should be the command string to execute; if a
# list then it should be the words of the command string to
@@ -340,6 +340,7 @@ class CommandAction(_ActionAction):
raise TypeError, "CommandAction should be given only " \
"a single command"
self.cmd_list = cmd
+ self.cmdstr = cmdstr
def __str__(self):
if SCons.Util.is_List(self.cmd_list):
@@ -347,6 +348,10 @@ class CommandAction(_ActionAction):
return str(self.cmd_list)
def strfunction(self, target, source, env):
+ if not self.cmdstr is None:
+ c = env.subst(self.cmdstr, 0, target, source)
+ if c:
+ return c
cmd_list = env.subst_list(self.cmd_list, 0, target, source)
return _string_from_cmd_list(cmd_list[0])
diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py
index f52496a..315b1ac 100644
--- a/src/engine/SCons/ActionTests.py
+++ b/src/engine/SCons/ActionTests.py
@@ -674,6 +674,11 @@ class CommandActionTestCase(unittest.TestCase):
"""
a = SCons.Action.CommandAction(["xyzzy"])
assert a.cmd_list == [ "xyzzy" ], a.cmd_list
+ assert a.cmdstr is None, a.cmdstr
+
+ a = SCons.Action.CommandAction(["abra"], "cadabra")
+ assert a.cmd_list == [ "abra" ], a.cmd_list
+ assert a.cmdstr == "cadabra", a.cmdstr
def test___str__(self):
"""Test fetching the pre-substitution string for command Actions
@@ -744,6 +749,15 @@ class CommandActionTestCase(unittest.TestCase):
s = act.strfunction([t1, t2], [s1, s2], env)
assert s == 'xyzzy t1 s1', s
+ act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE',
+ 'cmdstr - $SOURCE - $TARGET -')
+ s = act.strfunction([], [], env)
+ assert s == 'cmdstr - - -', s
+ s = act.strfunction([t1], [s1], env)
+ assert s == 'cmdstr - s1 - t1 -', s
+ s = act.strfunction([t1, t2], [s1, s2], env)
+ assert s == 'cmdstr - s1 - t1 -', s
+
act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES')
s = act.strfunction([], [], env)
assert s == 'xyzzy', s
@@ -752,6 +766,15 @@ class CommandActionTestCase(unittest.TestCase):
s = act.strfunction([t1, t2], [s1, s2], env)
assert s == 'xyzzy t1 t2 s1 s2', s
+ act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES',
+ 'cmdstr = $SOURCES = $TARGETS =')
+ s = act.strfunction([], [], env)
+ assert s == 'cmdstr = = =', s
+ s = act.strfunction([t1], [s1], env)
+ assert s == 'cmdstr = s1 = t1 =', s
+ s = act.strfunction([t1, t2], [s1, s2], env)
+ assert s == 'cmdstr = s1 s2 = t1 t2 =', s
+
act = SCons.Action.CommandAction(['xyzzy',
'$TARGET', '$SOURCE',
'$TARGETS', '$SOURCES'])
diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py
index 8924455..05d0ad8 100644
--- a/src/engine/SCons/Defaults.py
+++ b/src/engine/SCons/Defaults.py
@@ -120,13 +120,13 @@ IDLSuffixes = [".idl", ".IDL"]
del suffix
# Actions for common languages.
-CAction = SCons.Action.Action("$CCCOM")
+CAction = SCons.Action.Action("$CCCOM", "$CCCOMSTR")
DAction = SCons.Action.Action("$DCOM")
ShCAction = SCons.Action.Action("$SHCCCOM")
-CXXAction = SCons.Action.Action("$CXXCOM")
+CXXAction = SCons.Action.Action("$CXXCOM", "$CXXCOMSTR")
ShCXXAction = SCons.Action.Action("$SHCXXCOM")
-ASAction = SCons.Action.Action("$ASCOM")
+ASAction = SCons.Action.Action("$ASCOM", "$ASCOMSTR")
ASPPAction = SCons.Action.Action("$ASPPCOM")
LinkAction = SCons.Action.Action("$LINKCOM")
diff --git a/test/AS.py b/test/AS/AS.py
index adace1e..adace1e 100644
--- a/test/AS.py
+++ b/test/AS/AS.py
diff --git a/test/AS/ASCOM.py b/test/AS/ASCOM.py
new file mode 100644
index 0000000..da66bca
--- /dev/null
+++ b/test/AS/ASCOM.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test the ability to configure the $ASCOM construction variable.
+"""
+
+import os
+import string
+import sys
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+
+
+test.write('myas.py', r"""
+import sys
+infile = open(sys.argv[2], 'rb')
+outfile = open(sys.argv[1], 'wb')
+for l in filter(lambda l: l != "#as\n", infile.readlines()):
+ outfile.write(l)
+sys.exit(0)
+""")
+
+if os.path.normcase('.s') == os.path.normcase('.S'):
+ alt_s_suffix = '.S'
+ alt_asm_suffix = '.ASM'
+else:
+ alt_s_suffix = '.s'
+ alt_asm_suffix = '.asm'
+
+test.write('SConstruct', """
+env = Environment(ASCOM = r'%(python)s myas.py $TARGET $SOURCE',
+ OBJSUFFIX = '.obj')
+env.Object(target = 'test1', source = 'test1.s')
+env.Object(target = 'test2', source = 'test2%(alt_s_suffix)s')
+env.Object(target = 'test3', source = 'test3.asm')
+env.Object(target = 'test4', source = 'test4%(alt_asm_suffix)s')
+""" % locals())
+
+test.write('test1.s', "test1.s\n#as\n")
+test.write('test2'+alt_s_suffix, "test2.S\n#as\n")
+test.write('test3.asm', "test3.asm\n#as\n")
+test.write('test4'+alt_asm_suffix, "test4.ASM\n#as\n")
+
+test.run(arguments = '.')
+
+test.fail_test(test.read('test1.obj') != "test1.s\n")
+test.fail_test(test.read('test2.obj') != "test2.S\n")
+test.fail_test(test.read('test3.obj') != "test3.asm\n")
+test.fail_test(test.read('test4.obj') != "test4.ASM\n")
+
+
+
+test.pass_test()
diff --git a/test/AS/ASCOMSTR.py b/test/AS/ASCOMSTR.py
new file mode 100644
index 0000000..c8eed62
--- /dev/null
+++ b/test/AS/ASCOMSTR.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test that the $ASCOMSTR construction variable allows you to configure
+the assembly output.
+"""
+
+import os
+import string
+import sys
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+
+
+test.write('myas.py', r"""
+import sys
+infile = open(sys.argv[2], 'rb')
+outfile = open(sys.argv[1], 'wb')
+for l in filter(lambda l: l != "#as\n", infile.readlines()):
+ outfile.write(l)
+sys.exit(0)
+""")
+
+if os.path.normcase('.s') == os.path.normcase('.S'):
+ alt_s_suffix = '.S'
+ alt_asm_suffix = '.ASM'
+else:
+ alt_s_suffix = '.s'
+ alt_asm_suffix = '.asm'
+
+test.write('SConstruct', """
+env = Environment(ASCOM = r'%(python)s myas.py $TARGET $SOURCE',
+ ASCOMSTR = 'Assembling $TARGET from $SOURCE',
+ OBJSUFFIX = '.obj')
+env.Object(target = 'test1', source = 'test1.s')
+env.Object(target = 'test2', source = 'test2%(alt_s_suffix)s')
+env.Object(target = 'test3', source = 'test3.asm')
+env.Object(target = 'test4', source = 'test4%(alt_asm_suffix)s')
+""" % locals())
+
+test.write('test1.s', "test1.s\n#as\n")
+test.write('test2'+alt_s_suffix, "test2.S\n#as\n")
+test.write('test3.asm', "test3.asm\n#as\n")
+test.write('test4'+alt_asm_suffix, "test4.ASM\n#as\n")
+
+test.run(stdout = test.wrap_stdout("""\
+Assembling test1.obj from test1.s
+Assembling test2.obj from test2%(alt_s_suffix)s
+Assembling test3.obj from test3.asm
+Assembling test4.obj from test4%(alt_asm_suffix)s
+""" % locals()))
+
+test.fail_test(test.read('test1.obj') != "test1.s\n")
+test.fail_test(test.read('test2.obj') != "test2.S\n")
+test.fail_test(test.read('test3.obj') != "test3.asm\n")
+test.fail_test(test.read('test4.obj') != "test4.ASM\n")
+
+
+
+test.pass_test()
diff --git a/test/ASFLAGS.py b/test/AS/ASFLAGS.py
index 6396c45..6396c45 100644
--- a/test/ASFLAGS.py
+++ b/test/AS/ASFLAGS.py
diff --git a/test/CC.py b/test/CC/CC.py
index e7795d3..e7795d3 100644
--- a/test/CC.py
+++ b/test/CC/CC.py
diff --git a/test/CC/CCCOM.py b/test/CC/CCCOM.py
new file mode 100644
index 0000000..1be89a3
--- /dev/null
+++ b/test/CC/CCCOM.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test the ability to configure the $CCCOM construction variable.
+"""
+
+import os
+import string
+import sys
+import TestSCons
+
+python = TestSCons.python
+_exe = TestSCons._exe
+
+test = TestSCons.TestSCons()
+
+
+
+test.write('mycc.py', r"""
+import sys
+outfile = open(sys.argv[1], 'wb')
+infile = open(sys.argv[2], 'rb')
+for l in filter(lambda l: l[:6] != '/*cc*/', infile.readlines()):
+ outfile.write(l)
+sys.exit(0)
+""")
+
+if os.path.normcase('.c') == os.path.normcase('.C'):
+ alt_c_suffix = '.C'
+else:
+ alt_c_suffix = '.c'
+
+test.write('SConstruct', """
+env = Environment(CCCOM = r'%(python)s mycc.py $TARGET $SOURCE',
+ OBJSUFFIX='.obj')
+env.Object(target = 'test1', source = 'test1.c')
+env.Object(target = 'test2', source = 'test2%(alt_c_suffix)s')
+""" % locals())
+
+test.write('test1.c', """\
+test1.c
+/*cc*/
+""")
+
+test.write('test2'+alt_c_suffix, """\
+test2.C
+/*cc*/
+""")
+
+test.run()
+
+test.must_match('test1.obj', "test1.c\n")
+test.must_match('test2.obj', "test2.C\n")
+
+
+
+test.pass_test()
diff --git a/test/CC/CCCOMSTR.py b/test/CC/CCCOMSTR.py
new file mode 100644
index 0000000..1dd6a57
--- /dev/null
+++ b/test/CC/CCCOMSTR.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test that the $CCCOMSTR construction variable allows you to configure
+the C compilation output.
+"""
+
+import os
+import string
+import sys
+import TestSCons
+
+python = TestSCons.python
+_exe = TestSCons._exe
+
+test = TestSCons.TestSCons()
+
+
+
+test.write('mycc.py', r"""
+import sys
+outfile = open(sys.argv[1], 'wb')
+infile = open(sys.argv[2], 'rb')
+for l in filter(lambda l: l[:6] != '/*cc*/', infile.readlines()):
+ outfile.write(l)
+sys.exit(0)
+""")
+
+if os.path.normcase('.c') == os.path.normcase('.C'):
+ alt_c_suffix = '.C'
+else:
+ alt_c_suffix = '.c'
+
+test.write('SConstruct', """
+env = Environment(CCCOM = r'%(python)s mycc.py $TARGET $SOURCE',
+ CCCOMSTR = 'Building $TARGET from $SOURCE',
+ OBJSUFFIX='.obj')
+env.Object(target = 'test1', source = 'test1.c')
+env.Object(target = 'test2', source = 'test2%(alt_c_suffix)s')
+""" % locals())
+
+test.write('test1.c', """\
+test1.c
+/*cc*/
+""")
+
+test.write('test2'+alt_c_suffix, """\
+test2.C
+/*cc*/
+""")
+
+test.run(stdout = test.wrap_stdout("""\
+Building test1.obj from test1.c
+Building test2.obj from test2%(alt_c_suffix)s
+""" % locals()))
+
+test.must_match('test1.obj', "test1.c\n")
+test.must_match('test2.obj', "test2.C\n")
+
+
+
+test.pass_test()
diff --git a/test/CCFLAGS.py b/test/CC/CCFLAGS.py
index 6664010..6664010 100644
--- a/test/CCFLAGS.py
+++ b/test/CC/CCFLAGS.py
diff --git a/test/CXX.py b/test/CXX/CXX.py
index 6f9f0ce..6f9f0ce 100644
--- a/test/CXX.py
+++ b/test/CXX/CXX.py
diff --git a/test/CXX/CXXCOM.py b/test/CXX/CXXCOM.py
new file mode 100644
index 0000000..4641473
--- /dev/null
+++ b/test/CXX/CXXCOM.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test the ability to configure the $CXXCOM construction variable.
+"""
+
+import os
+import string
+import sys
+import TestSCons
+
+python = TestSCons.python
+_exe = TestSCons._exe
+
+test = TestSCons.TestSCons()
+
+
+
+test.write('mycc.py', r"""
+import sys
+outfile = open(sys.argv[1], 'wb')
+infile = open(sys.argv[2], 'rb')
+for l in filter(lambda l: l[:7] != '/*c++*/', infile.readlines()):
+ outfile.write(l)
+sys.exit(0)
+""")
+
+if os.path.normcase('.c') == os.path.normcase('.C'):
+ alt_cc_suffix = '.CC'
+else:
+ alt_cc_suffix = '.cc'
+
+test.write('SConstruct', """
+env = Environment(CXXCOM = r'%(python)s mycc.py $TARGET $SOURCE',
+ OBJSUFFIX='.obj')
+env.Object(target = 'test1', source = 'test1.cc')
+env.Object(target = 'test2', source = 'test2%(alt_cc_suffix)s')
+""" % locals())
+
+test.write('test1.cc', """\
+test1.cc
+/*c++*/
+""")
+
+test.write('test2'+alt_cc_suffix, """\
+test2.CC
+/*c++*/
+""")
+
+test.run()
+
+test.must_match('test1.obj', "test1.cc\n")
+test.must_match('test2.obj', "test2.CC\n")
+
+
+
+test.pass_test()
diff --git a/test/CXX/CXXCOMSTR.py b/test/CXX/CXXCOMSTR.py
new file mode 100644
index 0000000..0a2dce6
--- /dev/null
+++ b/test/CXX/CXXCOMSTR.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test that the $CXXCOMSTR construction variable allows you to configure
+the C++ compilation output.
+"""
+
+import os
+import string
+import sys
+import TestSCons
+
+python = TestSCons.python
+_exe = TestSCons._exe
+
+test = TestSCons.TestSCons()
+
+
+
+test.write('mycc.py', r"""
+import sys
+outfile = open(sys.argv[1], 'wb')
+infile = open(sys.argv[2], 'rb')
+for l in filter(lambda l: l[:6] != '/*cc*/', infile.readlines()):
+ outfile.write(l)
+sys.exit(0)
+""")
+
+if os.path.normcase('.c') == os.path.normcase('.C'):
+ alt_cc_suffix = '.CC'
+else:
+ alt_cc_suffix = '.cc'
+
+test.write('SConstruct', """
+env = Environment(CXXCOM = r'%(python)s mycc.py $TARGET $SOURCE',
+ CXXCOMSTR = 'Building $TARGET from $SOURCE',
+ OBJSUFFIX='.obj')
+env.Object(target = 'test1', source = 'test1.cc')
+env.Object(target = 'test2', source = 'test2%(alt_cc_suffix)s')
+""" % locals())
+
+test.write('test1.cc', """\
+test1.cc
+/*cc*/
+""")
+
+test.write('test2'+alt_cc_suffix, """\
+test2.CC
+/*cc*/
+""")
+
+test.run(stdout = test.wrap_stdout("""\
+Building test1.obj from test1.cc
+Building test2.obj from test2%(alt_cc_suffix)s
+""" % locals()))
+
+test.must_match('test1.obj', "test1.cc\n")
+test.must_match('test2.obj', "test2.CC\n")
+
+
+
+test.pass_test()
diff --git a/test/CXXFILESUFFIX.py b/test/CXX/CXXFILESUFFIX.py
index d729076..d729076 100644
--- a/test/CXXFILESUFFIX.py
+++ b/test/CXX/CXXFILESUFFIX.py