-#!/usr/bin/env python
+#! /usr/bin/env python
import getopt
import os.path
import string
import sys
-
-def PrintUsage():
- print "Usage: scons [OPTION]... TARGET..."
- print "Build TARGET or multiple TARGET(s)"
- print " "
- print ' -f CONSCRIPT execute CONSCRIPT instead of "SConstruct"'
- print " -j N execute N parallel jobs"
- print " --help print this message and exit"
-
-try:
- opts, targets = getopt.getopt(sys.argv[1:], 'f:j:', ['help'])
-except getopt.GetoptError, x:
- print x
- PrintUsage()
- sys.exit()
-
-Scripts = []
-
-num_jobs = 1
-for o, a in opts:
- if o == '-f': Scripts.append(a)
-
- if o == '-j':
- try:
- num_jobs = int(a)
- except:
- PrintUsage()
- sys.exit(1)
-
- if num_jobs <= 0:
- PrintUsage()
- sys.exit(1)
-
- if o == '--help':
- PrintUsage()
- sys.exit(0)
-
-if not Scripts:
- Scripts.append('SConstruct')
-
-
-# XXX The commented-out code here adds any "scons" subdirs in anything
-# along sys.path to sys.path. This was an attempt at setting up things
-# so we can import "node.FS" instead of "scons.Node.FS". This doesn't
-# quite fit our testing methodology, though, so save it for now until
-# the right solutions pops up.
-#
-#dirlist = []
-#for dir in sys.path:
-# scons = os.path.join(dir, 'scons')
-# if os.path.isdir(scons):
-# dirlist = dirlist + [scons]
-# dirlist = dirlist + [dir]
-#
-#sys.path = dirlist
-
+import traceback
from scons.Node.FS import init, Dir, File, lookup
from scons.Environment import Environment
import scons.Job
from scons.Builder import Builder
-
-init()
-
-
-
-def Conscript(filename):
- Scripts.append(filename)
-
-
-
-while Scripts:
- file, Scripts = Scripts[0], Scripts[1:]
- execfile(file)
-
-
+from scons.Errors import *
class Task:
- "this is here only until the build engine is implemented"
+ "XXX: this is here only until the build engine is implemented"
def __init__(self, target):
self.target = target
class Taskmaster:
- "this is here only until the build engine is implemented"
+ "XXX: this is here only until the build engine is implemented"
def __init__(self, targets):
self.targets = targets
pass
-taskmaster = Taskmaster(map(lambda x: lookup(File, x), targets))
+# Global variables
+
+Scripts = []
+
+# utility functions
+
+def _scons_syntax_error(e):
+ """Handle syntax errors. Print out a message and show where the error
+ occurred.
+ """
+ etype, value, tb = sys.exc_info()
+ lines = traceback.format_exception_only(etype, value)
+ for line in lines:
+ sys.stderr.write(line+'\n')
+
+def _scons_user_error(e):
+ """Handle user errors. Print out a message and a description of the
+ error, along with the line number and routine where it occured.
+ """
+ print 'user error'
+ etype, value, tb = sys.exc_info()
+ while tb.tb_next is not None:
+ tb = tb.tb_next
+ lineno = traceback.tb_lineno(tb)
+ filename = tb.tb_frame.f_code.co_filename
+ routine = tb.tb_frame.f_code.co_name
+ sys.stderr.write("\nSCons error: %s\n" % value)
+ sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
+
+def _scons_other_errors():
+ """Handle all errors but user errors. Print out a message telling
+ the user what to do in this case and print a normal trace.
+ """
+ print 'other errors'
+ traceback.print_exc()
+
+
+def PrintUsage():
+ print "Usage: scons [OPTION]... TARGET..."
+ print "Build TARGET or multiple TARGET(s)"
+ print " "
+ print ' -f CONSCRIPT execute CONSCRIPT instead of "SConstruct"'
+ print " -j N execute N parallel jobs"
+ print " --help print this message and exit"
+
+def Conscript(filename):
+ Scripts.append(filename)
+
+def main():
+ global Scripts
+
+ try:
+ opts, targets = getopt.getopt(sys.argv[1:], 'f:j:', ['help'])
+ except getopt.GetoptError, x:
+ print x
+ PrintUsage()
+ sys.exit(1)
+
+ num_jobs = 1
+ for o, a in opts:
+ if o == '-f': Scripts.append(a)
-jobs = scons.Job.Jobs(num_jobs, taskmaster)
-jobs.start()
-jobs.wait()
+ if o == '-j':
+ try:
+ num_jobs = int(a)
+ except:
+ PrintUsage()
+ sys.exit(1)
+ if num_jobs <= 0:
+ PrintUsage()
+ sys.exit(1)
+ if o == '--help':
+ PrintUsage()
+ sys.exit(0)
+
+ if not Scripts:
+ Scripts.append('SConstruct')
+
+
+ # XXX The commented-out code here adds any "scons" subdirs in anything
+ # along sys.path to sys.path. This was an attempt at setting up things
+ # so we can import "node.FS" instead of "scons.Node.FS". This doesn't
+ # quite fit our testing methodology, though, so save it for now until
+ # the right solutions pops up.
+ #
+ #dirlist = []
+ #for dir in sys.path:
+ # scons = os.path.join(dir, 'scons')
+ # if os.path.isdir(scons):
+ # dirlist = dirlist + [scons]
+ # dirlist = dirlist + [dir]
+ #
+ #sys.path = dirlist
+
+ # initialize node factory
+ init()
+
+ while Scripts:
+ file, Scripts = Scripts[0], Scripts[1:]
+ execfile(file)
+
+ taskmaster = Taskmaster(map(lambda x: lookup(File, x), targets))
+
+ jobs = scons.Job.Jobs(num_jobs, taskmaster)
+ jobs.start()
+ jobs.wait()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ print "Build interrupted."
+ except SyntaxError, e:
+ _scons_syntax_error(e)
+ except UserError, e:
+ _scons_user_error(e)
+ except:
+ _scons_other_errors()
--- /dev/null
+#!/usr/bin/env python
+
+__revision__ = "test/t0003.py __REVISION__ __DATE__ __DEVELOPER__"
+
+from TestCmd import TestCmd
+
+test = TestCmd(program = 'scons.py',
+ workdir = '',
+ interpreter = 'python')
+
+test.write('SConstruct1', """
+a ! int(2.0)
+""")
+test.run(chdir = '.', arguments='-f SConstruct1')
+test.fail_test(test.stderr() != """ File "SConstruct1", line 2
+
+ a ! int(2.0)
+
+ ^
+
+SyntaxError: invalid syntax
+
+""")
+
+
+test.write('SConstruct2', """
+raise UserError, 'Depends() require both sources and targets.'
+""")
+test.run(chdir = '.', arguments='-f SConstruct2')
+test.fail_test(test.stderr() != """
+SCons error: Depends() require both sources and targets.
+File "SConstruct2", line 2, in ?
+""")
+
+
+import os
+sconspath = os.path.join(os.getcwd(), 'scons.py')
+
+test.write('SConstruct3', """
+raise InternalError, 'error inside'
+""")
+test.run(chdir = '.', arguments='-f SConstruct3')
+expect = r"""Traceback \((most recent call|innermost) last\):
+ File "%s", line 163, in \?
+ main\(\)
+ File "%s", line 153, in main
+ execfile\(file\)
+ File "SConstruct3", line 2, in \?
+ raise InternalError, 'error inside'
+InternalError: error inside
+""" % (sconspath, sconspath)
+test.fail_test(not test.match_re(test.stderr(), expect))
+
+test.pass_test()