Provide graceful failures when a source file doesn't exist and can't be build, and...
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 27 Nov 2002 02:02:36 +0000 (02:02 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 27 Nov 2002 02:02:36 +0000 (02:02 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@507 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/python10/main.sgml
src/CHANGES.txt
src/RELEASE.txt
src/engine/SCons/Errors.py
src/engine/SCons/Node/FS.py
src/engine/SCons/Node/FSTests.py
src/engine/SCons/Script/__init__.py
test/Environment.py
test/nonexistent.py
test/overrides.py
test/scan-once.py

index 889ef4dc7e434bff2d918c4b443c59d1fcc88292..26fcffb0aff60c5413f6b446c57c61d92ab3cf2b 100644 (file)
@@ -37,7 +37,6 @@
     <!ENTITY install SYSTEM "install.sgml">
     <!ENTITY intro SYSTEM "intro.sgml">
     <!ENTITY process SYSTEM "process.sgml">
-    <!ENTITY references SYSTEM "references.sgml">
 
 ]>
 
index 825d65745276da4851f4ecc7154f9f766004bf5d..626db729905eafc26a6eeffd553659e6cb174d23 100644 (file)
@@ -54,7 +54,9 @@ RELEASE 0.09 -
   - Add separate $SHOBJPREFIX and $SHOBJSUFFIX construction variables
     (by default, the same as $OBJPREFIX and $OBJSUFFIX).
 
-  - Add a Make-like message when asked to build a source file.
+  - Add Make-like error messages when asked to build a source file,
+    and before trying to build a file that doesn't have all its source
+    files (including when an invalid drive letter is used on WIN32).
 
  From Steven Knight and Anthony Roach:
 
index 5f8c89a2dcfc3a80f24f3f3c5dc3bb0a5c50e5ed..d35168c3102561dae7d5c4986c00d1a163e9544f 100644 (file)
@@ -20,9 +20,9 @@ more effectively, please sign up for the scons-users mailing list at:
 
 
 
-RELEASE 0.08 - Mon, 15 Jul 2002 12:08:51 -0500
+RELEASE 0.09 - XXX
 
-  This is the eighth alpha release of SCons.  Please consult the
+  This is the ninth alpha release of SCons.  Please consult the
   CHANGES.txt file for a list of specific changes since last release.
 
   Please note the following important changes since release 0.08:
@@ -30,7 +30,11 @@ RELEASE 0.08 - Mon, 15 Jul 2002 12:08:51 -0500
     - The SetCommandHandler() function has been superceded
       by the SPAWN, SHELL and ESCAPE construction variables.
 
-      XXX
+    - SCons now exits with an error message if any source files or
+      implicit dependency files for a target do not exist and have
+      no Builder.  SCons used to ignore these files, so builds that
+      formally succeeded despite the absence of a scanned file will now
+      fail unless the -k (keep going on error) flag is used.
 
   Please note the following important changes since release 0.07:
 
index 2640220862e8243df71c2a2338482e6c93bfa6cc..112a4c9d5d438adbf6765d488aaa7b9313c3c56f 100644 (file)
@@ -45,3 +45,7 @@ class InternalError(Exception):
 class UserError(Exception):
     def __init__(self, args=None):
         self.args = args
+
+class StopError(Exception):
+    def __init__(self, args=None):
+        self.args = args
index 59b8e636d5d707c948e69a0ba91af35152358b92..d5247f73838cd2d5913a2cd793743c9b73685f56 100644 (file)
@@ -43,7 +43,7 @@ import types
 import SCons.Node
 from UserDict import UserDict
 import sys
-from SCons.Errors import UserError
+import SCons.Errors
 import SCons.Warnings
 
 try:
@@ -296,7 +296,7 @@ class FS:
                 directory = self.Root[drive]
             except KeyError:
                 if not create:
-                    raise UserError
+                    raise SCons.Errors.UserError
                 dir = Dir(drive, ParentOfRoot(), self)
                 dir.path = dir.path + os.sep
                 dir.abspath = dir.abspath + os.sep
@@ -314,7 +314,7 @@ class FS:
                                               Dir)
             except KeyError:
                 if not create:
-                    raise UserError
+                    raise SCons.Errors.UserError
 
                 # look at the actual filesystem and make sure there isn't
                 # a file already there
@@ -332,7 +332,7 @@ class FS:
             ret = self.__checkClass(directory.entries[file_name], fsclass)
         except KeyError:
             if not create:
-                raise UserError
+                raise SCons.Errors.UserError
 
             # make sure we don't create File nodes when there is actually
             # a directory at that path on the disk, and vice versa
@@ -436,9 +436,9 @@ class FS:
         if not isinstance(build_dir, SCons.Node.Node):
             build_dir = self.Dir(build_dir)
         if not src_dir.is_under(self.Top):
-            raise UserError, "Source directory must be under top of build tree."
+            raise SCons.Errors.UserError, "Source directory must be under top of build tree."
         if src_dir.is_under(build_dir):
-            raise UserError, "Source directory cannot be under build directory."
+            raise SCons.Errors.UserError, "Source directory cannot be under build directory."
         build_dir.link(src_dir, duplicate)
 
     def Repository(self, *dirs):
@@ -848,6 +848,14 @@ class File(Entry):
 
     def prepare(self):
         """Prepare for this file to be created."""
+
+        def missing(node):
+            return not node.builder and not node.rexists()
+        missing_sources = filter(missing, self.children())
+        if missing_sources:
+            desc = "No Builder for target `%s', needed by `%s'." % (missing_sources[0], self)
+            raise SCons.Errors.StopError, desc
+
         if self.exists():
             if self.builder and not self.precious:
                 os.unlink(self.path)
index c817408e17af77397c089d7a552e584c2a9f3c90..5d328739f3bd0e7b039fae27a5afa28f9eb04dc8 100644 (file)
@@ -628,6 +628,7 @@ class FSTestCase(unittest.TestCase):
         assert os.path.exists(test.workpath("remove_me"))
         f1 = fs.File(test.workpath("remove_me"))
         f1.builder = 1
+        f1.env_set(Environment())
         f1.prepare()
         assert not os.path.exists(test.workpath("remove_me"))
 
index 814d147ce85490abc262d715ebba160696866a11..dd44621e144b30cea72f6677157a880dad43ae1a 100644 (file)
@@ -99,6 +99,12 @@ class BuildTask(SCons.Taskmaster.Task):
                 # don't try to walk the stack, just print the error.
                 sys.stderr.write("\nSCons error: %s\n" % e)
                 raise
+            except StopError, e:
+                s = str(e)
+                if not keep_going_on_error:
+                    s = s + '  Stop.'
+                sys.stderr.write("scons: *** %s\n" % s)
+                raise
             except:
                 sys.stderr.write("scons: *** %s\n" % sys.exc_value)
                 raise
index ea42e5d45e4527df6f3673eb5e45f8348dea6890..0f3ab8a7ce941285a66e85dc7a892a8a3e0a728c 100644 (file)
@@ -48,6 +48,8 @@ assert sys.argv[3] == 'bar.in', sys.argv[3]
 assert sys.argv[4] == 'blat blat', sys.argv[4]
 """)
 
+test.write('foo.in', "foo.in\n")
+
 test.run(arguments='foo.out')
 
 test.pass_test()
index 8f2c63ebf8cadaee9ce1a28e453061e675e6dee0..3604a295cfb7ba56954c416b7f9cdf5df1baf0ff 100644 (file)
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #
 
+"""
+This test verifies that we fail gracefully and provide informative
+messages if someone tries to build a target that hasn't been defined
+or uses a nonexistent source file.  On Windows systems, it checks
+to make sure that this applies to invalid drive letters as well.
+"""
+
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
+import os
+import os.path
+import string
 import sys
+
 import TestSCons
 
 test = TestSCons.TestSCons()
 
-test.write('SConstruct', "")
+test.write('SConstruct', """
+env = Environment()
+env.Command("aaa.out", "aaa.in", "should never get executed")
+env.Command("bbb.out", "bbb.in", "should never get executed")
+""")
 
 test.run(arguments = 'foo',
          stderr = "scons: *** Do not know how to make target `foo'.  Stop.\n",
@@ -41,4 +56,62 @@ scons: *** Do not know how to make target `foo'.
 """,
          status = 2)
 
+test.run(arguments = "aaa.out",
+         stderr = "scons: *** No Builder for target `aaa.in', needed by `aaa.out'.  Stop.\n",
+         status = 2)
+
+test.run(arguments = "-k bbb.out aaa.out",
+         stderr = """scons: *** No Builder for target `bbb.in', needed by `bbb.out'.
+scons: *** No Builder for target `aaa.in', needed by `aaa.out'.
+""",
+         status = 2)
+
+if sys.platform == 'win32':
+    bad_drive = None
+    for i in range(len(string.uppercase)-1, -1, -1):
+        d = string.uppercase[i]
+        if not os.path.isdir(d + ':' + os.sep):
+            bad_drive = d + ':' + '\\' + os.sep
+            break
+
+    if bad_drive is None:
+        print "All drive letters appear to be in use."
+        print "Cannot test SCons handling of invalid Win32 drive letters."
+        test.no_result(1);
+
+    test.write('SConstruct', """
+def cat(env, source, target):
+    target = str(target[0])
+    source = map(str, source)
+    print 'cat(%%s) > %%s' %% (source, target)
+    f = open(target, "wb")
+    for src in source:
+        f.write(open(src, "rb").read())
+    f.close()
+
+bad_drive = '%s'
+env = Environment(BUILDERS={'Build':Builder(action=cat)})
+env.Build('aaa.out', 'aaa.in')
+env.Build(bad_drive + 'no_target', 'bbb.in')
+env.Build('ccc.out', bad_drive + 'no_source')
+""" % bad_drive)
+
+    test.write("aaa.in", "aaa.in\n")
+
+    test.write("no_target", "no_target\n")
+
+    test.write("no_source", "no_source\n")
+
+    test.run(arguments = 'aaa.out')
+
+    test.fail_test(test.read('aaa.out') != "aaa.in\n")
+
+    test.run(arguments = bad_drive + 'no_target',
+             stderr = "scons: *** Do not know how to make target `%sno_target'.  Stop.\n" % bad_drive,
+             status = 2)
+
+    test.run(arguments = 'ccc.out',
+             stderr = "scons: *** No Builder for target `%sno_source', needed by `ccc.out'.  Stop.\n" % bad_drive,
+             status = 2)
+
 test.pass_test()
index 0ec38745bb4ff356ae92e9064416dd11cbb54afe..f535c9757f2c24014590360ec1cd7a81a97710f0 100644 (file)
@@ -44,6 +44,8 @@ env['BUILDERS']['Build'] = builder
 Default(env.Build('foo', 'bar', CC='mycc', LIBS = env['LIBS']+['b']))
 """)
 
+test.write('bar', "bar\n")
+
 test.run()
 
 test.write('SConstruct', """
index 7ddf9c9d2bd296e24d01039ef793d4862425ebcd..19cb495a4dcf9ef9350b72f5c1de5565841f752b 100644 (file)
@@ -60,12 +60,6 @@ f3 = env.Echo(source=['file3'], target=['file4'])
 Default(f3)
 """)
 
-test.run(arguments = '.',
-         stdout = test.wrap_stdout("""create file2.s from file1.s
-create file3.s from file2.s
-create file4.s from file3.s
-"""))
-
 test.write('file1.s', 'file1.s\n')
 
 test.run(arguments = '.',