Add a configurable function for command-line printing. (Gary Oberbrunner)
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sun, 5 Sep 2004 12:01:20 +0000 (12:01 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sun, 5 Sep 2004 12:01:20 +0000 (12:01 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@1058 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/man/scons.1
src/CHANGES.txt
src/engine/SCons/Action.py
src/engine/SCons/ActionTests.py
src/engine/SCons/BuilderTests.py
test/PRINT_CMD_LINE_FUNC.py [new file with mode: 0644]

index 43cc3180bea8770892e20d2545b8127de0e001ee..37013ea66252f92e6dcc87fd9a0d75e2b650f0cf 100644 (file)
@@ -5684,6 +5684,45 @@ else:
     Tool('msvc')(env)
 .EE
 
+.IP PRINT_CMD_LINE_FUNC
+A Python function used to print the command lines as they are executed
+(assuming command printing is not disabled by the
+.B -q
+or
+.B -s
+options or their equivalents).
+The function should take four arguments:
+.IR s ,
+the command being executed (a string),
+.IR target ,
+the target being built (file node, list, or string name(s)),
+.IR source ,
+the source(s) used (file node, list, or string name(s)), and
+.IR env ,
+the environment being used.
+
+The function must do the printing itself.  The default implementation,
+used if this variable is not set or is None, is:
+.ES
+def print_cmd_line(s, target, source, env):
+  sys.stdout.write(s + "\n")
+.EE
+
+Here's an example of a more interesting function:
+.ES
+def print_cmd_line(s, target, source, env):
+   sys.stdout.write("Building %s -> %s...\n" %
+    (' and '.join([str(x) for x in source]),
+     ' and '.join([str(x) for x in target])))
+env=Environment(PRINT_CMD_LINE_FUNC=print_cmd_line)
+env.Program('foo', 'foo.c')
+.EE
+
+This just prints "Building <targetname> from <sourcename>..." instead
+of the actual commands.
+Such a function could also log the actual commands to a log file,
+for example.
+
 .IP PROGPREFIX
 The prefix used for executable file names.
 
index ad6990771cb2c4314e29cb9af5b533422dfffda7..eec33a5da12862020f16f93017ab6c5338fddd04 100644 (file)
@@ -38,6 +38,9 @@ RELEASE 0.97 - XXX
 
   - Add ParseConfig() support for the -framework GNU linker option.
 
+  - Add a PRINT_CMD_LINE_FUNC construction variable to allow people
+    to filter (or log) command-line output.
+
   From Kevin Quick:
 
   - Fix the Builder name returned from ListBuilders and other instances
index ec6a3b093b9e13100028b7e4d5f0bc4379c365db..2cd23f4bb5d6d590e6a02da3a2f370c38a78221d 100644 (file)
@@ -218,6 +218,9 @@ class ActionBase:
     def __cmp__(self, other):
         return cmp(self.__dict__, other.__dict__)
 
+    def print_cmd_line(self, s, target, source, env):
+        sys.stdout.write(s + "\n")
+
     def __call__(self, target, source, env,
                                errfunc=None,
                                presub=_null,
@@ -238,7 +241,15 @@ class ActionBase:
         if show and self.strfunction:
             s = self.strfunction(target, source, env)
             if s:
-                sys.stdout.write(s + '\n')
+                try:
+                    get = env.get
+                except AttributeError:
+                    print_func = self.print_cmd_line
+                else:
+                    print_func = get('PRINT_CMD_LINE_FUNC')
+                    if not print_func:
+                        print_func = self.print_cmd_line
+                print_func(s, target, source, env)
         if execute:
             stat = self.execute(target, source, env)
             if stat and errfunc:
index fa2bfe71522eee1ddd77ea0f9c70eab99dca6482..c6201e2e8d7352701d5b972457f13c0df5491ab3 100644 (file)
@@ -139,7 +139,7 @@ class Environment:
         self.d[item] = value
     def has_key(self, item):
         return self.d.has_key(item)
-    def get(self, key, value):
+    def get(self, key, value=None):
         return self.d.get(key, value)
     def items(self):
         return self.d.items()
@@ -350,6 +350,25 @@ class ActionBaseTestCase(unittest.TestCase):
         assert a1 != a3
         assert a2 != a3
 
+    def test_print_cmd_lines(self):
+        """Test the print_cmd_lines() method
+        """
+        save_stdout = sys.stdout
+
+        try:
+            def execfunc(target, source, env):
+                pass
+            a = SCons.Action.Action(execfunc)
+
+            sio = StringIO.StringIO()
+            sys.stdout = sio
+            a.print_cmd_line("foo bar", None, None, None)
+            s = sio.getvalue()
+            assert s == "foo bar\n", s
+
+        finally:
+            sys.stdout = save_stdout
+
     def test___call__(self):
         """Test calling an Action
         """
@@ -438,6 +457,14 @@ class ActionBaseTestCase(unittest.TestCase):
             assert result == 7, result
             assert errfunc_result == [7], errfunc_result
 
+            result = []
+            def my_print_cmd_line(s, target, source, env, result=result):
+                result.append(s)
+            env['PRINT_CMD_LINE_FUNC'] = my_print_cmd_line
+            a("output", "input", env)
+            assert result == ['execfunc(["output"], ["input"])'], result
+            
+
         finally:
             sys.stdout = save_stdout
             SCons.Action.print_actions = save_print_actions
index bbff6273e86810b7e925dffddc24713a5ef4167f..d7d7747d2484464fc389082f8e3324596f30b236 100644 (file)
@@ -107,7 +107,7 @@ class Environment:
         return self.d.has_key(item)
     def keys(self):
         return self.d.keys()
-    def get(self, key, value):
+    def get(self, key, value=None):
         return self.d.get(key, value)
     def Override(self, overrides):
         env = apply(Environment, (), self.d)
diff --git a/test/PRINT_CMD_LINE_FUNC.py b/test/PRINT_CMD_LINE_FUNC.py
new file mode 100644 (file)
index 0000000..cc6929a
--- /dev/null
@@ -0,0 +1,68 @@
+#!/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 PRINT_CMD_LINE_FUNC construction variable.
+"""
+
+import sys
+import TestCmd
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestCmd.match_re)
+
+
+test.write('SConstruct', r"""
+import sys
+def print_cmd_line(s, target, source, env):
+    sys.stdout.write("BUILDING %s from %s with %s\n"%
+                     (str(target[0]), str(source[0]), s))
+
+e = Environment(PRINT_CMD_LINE_FUNC=print_cmd_line)
+e.Program(target = 'prog', source = 'prog.c')
+""")
+
+test.write('prog.c', r"""
+int main(int argc, char *argv[]) { return 0; }
+""")
+
+test.run(arguments = '-Q .', stdout = """\
+BUILDING prog.o from prog.c with .*
+BUILDING prog from prog.o with .*
+""")
+
+test.run(arguments = '-c .')
+
+# Just make sure it doesn't blow up when PRINT_CMD_LINE_FUNC
+# is explicity initialized to None.
+test.write('SConstruct', r"""
+e = Environment(PRINT_CMD_LINE_FUNC=None)
+e.Program(target = 'prog', source = 'prog.c')
+""")
+
+test.run(arguments = '-Q .')
+
+test.pass_test()