Commits

Anonymous committed f768775

Provide an error message when a command isn't found.

  • Participants
  • Parent commits 2cd2c9c

Comments (0)

Files changed (4)

File src/CHANGES.txt

 
   - Fix to setup.py so it doesn't require a sys.argv[1] argument.
 
+  - Provide make-like warning message for "command not found" and
+    similar errors.
+
   From Charles Crain:
 
   - Added support for the Install method.

File src/engine/SCons/Builder.py

 import SCons.Node.FS
 from SCons.Util import PathList, scons_str2nodes, scons_subst, scons_subst_list, autogenerate
 import string
+import sys
 import types
 from UserList import UserList
 from UserDict import UserDict
         pass
 
 
+exitvalmap = {
+    2 : 127,
+    13 : 126,
+}
 
 if os.name == 'posix':
 
         pid = os.fork()
         if not pid:
             # Child process.
-            os.execvpe(cmd, args, env)
+            exitval = 127
+            try:
+                os.execvpe(cmd, args, env)
+            except OSError, e:
+                exitval = exitvalmap[e[0]]
+                sys.stderr.write("scons: %s: %s\n" % (cmd, e[1]))
+            os._exit(exitval)
         else:
             # Parent process.
             pid, stat = os.waitpid(pid, 0)
 
     def spawn(cmd, args, env):
         try:
-	    ret = os.spawnvpe(os.P_WAIT, cmd, args, env)
-	except AttributeError:
-	    cmd = pathsearch(cmd, env)
-	    ret = os.spawnve(os.P_WAIT, cmd, args, env)
+            try:
+                ret = os.spawnvpe(os.P_WAIT, cmd, args, env)
+            except AttributeError:
+                cmd = pathsearch(cmd, env)
+                ret = os.spawnve(os.P_WAIT, cmd, args, env)
+        except OSError, e:
+            ret = exitvalmap[e[0]]
+            sys.stderr.write("scons: %s: %s\n" % (cmd, e[1]))
         return ret
 
 

File src/engine/SCons/BuilderTests.py

 
 import TestCmd
 import SCons.Builder
+import SCons.Errors
 
 # Initial setup of the common environment for all tests,
 # a temporary working directory containing a
 	containing one of each.
 	"""
 
+        def MyBuilder(**kw):
+            builder = apply(SCons.Builder.Builder, (), kw)
+            def no_show(str):
+                pass
+            builder.action.show = no_show
+            return builder
+
 	python = sys.executable
 
 	cmd1 = r'%s %s %s xyzzy' % (python, act_py, outfile)
 
-	builder = SCons.Builder.Builder(action = cmd1)
+        builder = MyBuilder(action = cmd1)
 	r = builder.execute()
 	assert r == 0
 	c = test.read(outfile, 'r')
 
 	cmd2 = r'%s %s %s $TARGET' % (python, act_py, outfile)
 
-	builder = SCons.Builder.Builder(action = cmd2)
+        builder = MyBuilder(action = cmd2)
 	r = builder.execute(target = 'foo')
 	assert r == 0
 	c = test.read(outfile, 'r')
 
 	cmd3 = r'%s %s %s ${TARGETS}' % (python, act_py, outfile)
 
-	builder = SCons.Builder.Builder(action = cmd3)
+        builder = MyBuilder(action = cmd3)
 	r = builder.execute(target = ['aaa', 'bbb'])
 	assert r == 0
 	c = test.read(outfile, 'r')
 
 	cmd4 = r'%s %s %s $SOURCES' % (python, act_py, outfile)
 
-	builder = SCons.Builder.Builder(action = cmd4)
+        builder = MyBuilder(action = cmd4)
 	r = builder.execute(source = ['one', 'two'])
 	assert r == 0
 	c = test.read(outfile, 'r')
 
 	cmd4 = r'%s %s %s ${SOURCES[:2]}' % (python, act_py, outfile)
 
-	builder = SCons.Builder.Builder(action = cmd4)
+        builder = MyBuilder(action = cmd4)
 	r = builder.execute(source = ['three', 'four', 'five'])
 	assert r == 0
 	c = test.read(outfile, 'r')
 
 	cmd5 = r'%s %s %s $TARGET XYZZY' % (python, act_py, outfile)
 
-	builder = SCons.Builder.Builder(action = cmd5)
+        builder = MyBuilder(action = cmd5)
 	r = builder.execute(target = 'out5', env = {'ENV' : {'XYZZY' : 'xyzzy'}})
 	assert r == 0
 	c = test.read(outfile, 'r')
 
         cmd6 = r'%s %s %s ${TARGETS[1]} $TARGET ${SOURCES[:2]}' % (python, act_py, outfile)
 
-        builder = SCons.Builder.Builder(action = cmd6)
+        builder = MyBuilder(action = cmd6)
         r = builder.execute(target = [Obj('111'), Obj('222')],
                             source = [Obj('333'), Obj('444'), Obj('555')])
         assert r == 0
         expect7 = '%s %s %s one\n%s %s %s two\n' % (python, act_py, outfile,
                                                     python, act_py, outfile)
 
-        builder = SCons.Builder.Builder(action = cmd7)
+        builder = MyBuilder(action = cmd7)
 
         global show_string
         show_string = ""
 	    open(kw['target'], 'w').write("function1\n")
 	    return 1
 
-	builder = SCons.Builder.Builder(action = function1)
+	builder = MyBuilder(action = function1)
 	r = builder.execute(target = outfile)
 	assert r == 1
 	c = test.read(outfile, 'r')
 	    def __init__(self, **kw):
 		open(kw['out'], 'w').write("class1a\n")
 
-	builder = SCons.Builder.Builder(action = class1a)
+	builder = MyBuilder(action = class1a)
 	r = builder.execute(out = outfile)
 	assert r.__class__ == class1a
 	c = test.read(outfile, 'r')
 		open(kw['out'], 'w').write("class1b\n")
 		return 2
 
-	builder = SCons.Builder.Builder(action = class1b())
+	builder = MyBuilder(action = class1b())
 	r = builder.execute(out = outfile)
 	assert r == 2
 	c = test.read(outfile, 'r')
 	    def __init__(self, **kw):
 		open(kw['out'], 'a').write("class2b\n")
 
-	builder = SCons.Builder.Builder(action = [cmd2, function2, class2a(), class2b])
+	builder = MyBuilder(action = [cmd2, function2, class2a(), class2b])
 	r = builder.execute(out = outfile)
 	assert r.__class__ == class2b
 	c = test.read(outfile, 'r')
         assert c == "act.py: 'syzygy'\nfunction2\nclass2a\nclass2b\n", c
 
+        # Test that a nonexistent command returns 127
+        builder = MyBuilder(action = python + "_XyZzY_")
+        r = builder.execute(out = outfile)
+        assert r == 127, "r == %d" % r
+
+        if os.name == 'nt':
+            # NT treats execs of directories and non-executable files
+            # as "file not found" errors
+            expect = 127
+        else:
+            expect = 126
+
+        # Test that trying to execute a directory returns 126
+        dir, tail = os.path.split(python)
+        builder = MyBuilder(action = dir)
+        r = builder.execute(out = outfile)
+        assert r == expect, "r == %d" % r
+
+        # Test that trying to execute a non-executable file returns 126
+        builder = MyBuilder(action = outfile)
+        r = builder.execute(out = outfile)
+        assert r == expect, "r == %d" % r
+
     def test_get_contents(self):
         """Test returning the signature contents of a Builder
         """

File test/build-errors.py

+#!/usr/bin/env python
+#
+# Copyright (c) 2001 Steven Knight
+#
+# 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__"
+
+import os
+import os.path
+import TestCmd
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+no_such_file = test.workpath("no_such_file")
+not_executable = test.workpath("not_executable")
+
+test.write(not_executable, "\n")
+
+test.write("f1.in", "\n")
+test.write("f2.in", "\n")
+test.write("f3.in", "\n")
+
+test.write('SConstruct1', r"""
+bld = Builder(name = 'bld', action = '%s $SOURCES $TARGET')
+env = Environment(BUILDERS = [bld])
+env.bld(target = 'f1', source = 'f1.in')
+""" % os.path.normpath(no_such_file))
+
+test.run(arguments='-f SConstruct1 .',
+	 stdout = "%s f1.in f1\n" % no_such_file,
+	 stderr = """scons: %s: No such file or directory
+scons: *** [f1] Error 127
+""" % no_such_file)
+
+test.write('SConstruct2', r"""
+bld = Builder(name = 'bld', action = '%s $SOURCES $TARGET')
+env = Environment(BUILDERS = [bld])
+env.bld(target = 'f2', source = 'f2.in')
+""" % os.path.normpath(not_executable))
+
+if os.name == 'nt':
+    expect = """scons: %s: No such file or directory
+scons: *** [f2] Error 127
+""" % not_executable
+else:
+    expect = """scons: %s: Permission denied
+scons: *** [f2] Error 126
+""" % not_executable
+
+test.run(arguments='-f SConstruct2 .',
+	 stdout = "%s f2.in f2\n" % not_executable,
+	 stderr = expect)
+
+test.write('SConstruct3', r"""
+bld = Builder(name = 'bld', action = '%s $SOURCES $TARGET')
+env = Environment(BUILDERS = [bld])
+env.bld(target = 'f3', source = 'f3.in')
+""" % os.path.normpath(test.workdir))
+
+test.run(arguments='-f SConstruct3 .',
+	 stdout = "%s f3.in f3\n" % test.workdir,
+	 stderr = """scons: %s: Permission denied
+scons: *** [f3] Error 126
+""" % test.workdir)
+
+test.pass_test()