summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Script/__init__.py
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2005-01-08 22:38:53 (GMT)
committerSteven Knight <knight@baldmt.com>2005-01-08 22:38:53 (GMT)
commit69e3c442cdfb846cbcba7702d500e237b66be71e (patch)
tree7efb9d5d344c6d7cd76ae432a075d5ac4276aace /src/engine/SCons/Script/__init__.py
parent3c23f9969cea7931a8dea998a33b15ab51fe1a5f (diff)
downloadSCons-69e3c442cdfb846cbcba7702d500e237b66be71e.zip
SCons-69e3c442cdfb846cbcba7702d500e237b66be71e.tar.gz
SCons-69e3c442cdfb846cbcba7702d500e237b66be71e.tar.bz2
Support 'from SConsScript import *' to allow Python modules imported by SConscript files to get at the global builders and functions more easily.
Diffstat (limited to 'src/engine/SCons/Script/__init__.py')
-rw-r--r--src/engine/SCons/Script/__init__.py1285
1 files changed, 190 insertions, 1095 deletions
diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py
index 71c2f03..d6d4912 100644
--- a/src/engine/SCons/Script/__init__.py
+++ b/src/engine/SCons/Script/__init__.py
@@ -39,1114 +39,209 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import time
start_time = time.time()
-import os
-import os.path
-import random
import string
-import sys
-import traceback
+import UserList
-# Strip the script directory from sys.path() so on case-insensitive
-# (WIN32) systems Python doesn't think that the "scons" script is the
-# "SCons" package. Replace it with our own version directory so, if
-# if they're there, we pick up the right version of the build engine
-# modules.
-#sys.path = [os.path.join(sys.prefix,
-# 'lib',
-# 'scons-%d' % SCons.__version__)] + sys.path[1:]
-
-import SCons.Debug
-import SCons.Defaults
+import SCons.Action
+import SCons.Builder
import SCons.Environment
-import SCons.Errors
-import SCons.Job
-import SCons.Node
-import SCons.Node.FS
-from SCons.Optik import OptionParser, SUPPRESS_HELP, OptionValueError
-import SCons.Script.SConscript
-import SCons.Sig
-import SCons.Taskmaster
+import SCons.Options
+import SCons.Platform
+import SCons.Scanner
+import SCons.SConf
+import SCons.Tool
import SCons.Util
-import SCons.Warnings
-
-#
-display = SCons.Util.display
-progress_display = SCons.Util.DisplayEngine()
-
-# Task control.
-#
-class BuildTask(SCons.Taskmaster.Task):
- """An SCons build task."""
- def display(self, message):
- display('scons: ' + message)
-
- def execute(self):
- target = self.targets[0]
- if target.get_state() == SCons.Node.up_to_date:
- if self.top and target.has_builder():
- display("scons: `%s' is up to date." % str(self.node))
- elif target.has_builder() and not hasattr(target.builder, 'status'):
- if print_time:
- start_time = time.time()
- SCons.Taskmaster.Task.execute(self)
- if print_time:
- finish_time = time.time()
- global command_time
- command_time = command_time+finish_time-start_time
- print "Command execution time: %f seconds"%(finish_time-start_time)
-
- def do_failed(self, status=2):
- global exit_status
- if ignore_errors:
- SCons.Taskmaster.Task.executed(self)
- elif keep_going_on_error:
- SCons.Taskmaster.Task.fail_continue(self)
- exit_status = status
- else:
- SCons.Taskmaster.Task.fail_stop(self)
- exit_status = status
-
- def executed(self):
- t = self.targets[0]
- if self.top and not t.has_builder() and not t.side_effect:
- if not t.exists():
- sys.stderr.write("scons: *** Do not know how to make target `%s'." % t)
- if not keep_going_on_error:
- sys.stderr.write(" Stop.")
- sys.stderr.write("\n")
- self.do_failed()
- else:
- print "scons: Nothing to be done for `%s'." % t
- SCons.Taskmaster.Task.executed(self)
- else:
- SCons.Taskmaster.Task.executed(self)
-
- def failed(self):
- # Handle the failure of a build task. The primary purpose here
- # is to display the various types of Errors and Exceptions
- # appropriately.
- status = 2
- exc_info = self.exc_info()
- try:
- t, e, tb = exc_info
- except ValueError:
- t, e = exc_info
- tb = None
- if t is None:
- # The Taskmaster didn't record an exception for this Task;
- # see if the sys module has one.
- t, e = sys.exc_info()[:2]
-
- if t == SCons.Errors.BuildError:
- fname = e.node
- if SCons.Util.is_List(e.node):
- fname = string.join(map(str, e.node), ', ')
- sys.stderr.write("scons: *** [%s] %s\n" % (fname, e.errstr))
- if e.errstr == 'Exception':
- traceback.print_exception(e.args[0], e.args[1], e.args[2])
- elif t == SCons.Errors.ExplicitExit:
- status = e.status
- sys.stderr.write("scons: *** [%s] Explicit exit, status %s\n" % (e.node, e.status))
- else:
- if e is None:
- e = t
- s = str(e)
- if t == SCons.Errors.StopError and not keep_going_on_error:
- s = s + ' Stop.'
- sys.stderr.write("scons: *** %s\n" % s)
-
- if tb and print_stacktrace:
- sys.stderr.write("scons: internal stack trace:\n")
- traceback.print_tb(tb, file=sys.stderr)
-
- self.do_failed(status)
-
- self.exc_clear()
-
- def postprocess(self):
- if self.top:
- t = self.targets[0]
- if print_tree:
- print
- SCons.Util.print_tree(t, get_all_children)
- if print_stree:
- print
- SCons.Util.print_tree(t, get_all_children, showtags=2)
- if print_dtree:
- print
- SCons.Util.print_tree(t, get_derived_children)
- if print_includes:
- tree = t.render_include_tree()
- if tree:
- print
- print tree
- SCons.Taskmaster.Task.postprocess(self)
-
- def make_ready(self):
- """Make a task ready for execution"""
- SCons.Taskmaster.Task.make_ready(self)
- if self.out_of_date and print_explanations:
- explanation = self.out_of_date[0].explain()
- if explanation:
- sys.stdout.write("scons: " + explanation)
-
-class CleanTask(SCons.Taskmaster.Task):
- """An SCons clean task."""
- def show(self):
- if (self.targets[0].has_builder() or self.targets[0].side_effect) \
- and not os.path.isdir(str(self.targets[0])):
- display("Removed " + str(self.targets[0]))
- if SCons.Environment.CleanTargets.has_key(self.targets[0]):
- files = SCons.Environment.CleanTargets[self.targets[0]]
- for f in files:
- SCons.Util.fs_delete(str(f), 0)
-
- def remove(self):
- if self.targets[0].has_builder() or self.targets[0].side_effect:
- for t in self.targets:
- try:
- removed = t.remove()
- except OSError, e:
- print "scons: Could not remove '%s':" % str(t), e.strerror
- else:
- if removed:
- display("Removed " + str(t))
- if SCons.Environment.CleanTargets.has_key(self.targets[0]):
- files = SCons.Environment.CleanTargets[self.targets[0]]
- for f in files:
- SCons.Util.fs_delete(str(f))
-
- execute = remove
-
- # Have the taskmaster arrange to "execute" all of the targets, because
- # we'll figure out ourselves (in remove() or show() above) whether
- # anything really needs to be done.
- make_ready = SCons.Taskmaster.Task.make_ready_all
-
- def prepare(self):
- pass
-
-class QuestionTask(SCons.Taskmaster.Task):
- """An SCons task for the -q (question) option."""
- def prepare(self):
- pass
-
- def execute(self):
- if self.targets[0].get_state() != SCons.Node.up_to_date:
- global exit_status
- exit_status = 1
- self.tm.stop()
-
- def executed(self):
- pass
-
-# Global variables
-
-keep_going_on_error = 0
-print_count = 0
-print_dtree = 0
-print_explanations = 0
-print_includes = 0
-print_objects = 0
-print_stacktrace = 0
-print_stree = 0
-print_time = 0
-print_tree = 0
-memory_stats = None
-ignore_errors = 0
-sconscript_time = 0
-command_time = 0
-exit_status = 0 # exit status, assume success by default
-profiling = 0
-repositories = []
-num_jobs = 1 # this is modifed by SConscript.SetJobs()
-
-# utility functions
-
-def get_all_children(node): return node.all_children()
-
-def get_derived_children(node):
- children = node.all_children(None)
- return filter(lambda x: x.has_builder(), children)
-
-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')
- sys.exit(2)
-
-def find_deepest_user_frame(tb):
- """
- Find the deepest stack frame that is not part of SCons.
-
- Input is a "pre-processed" stack trace in the form
- returned by traceback.extract_tb() or traceback.extract_stack()
- """
-
- tb.reverse()
-
- # find the deepest traceback frame that is not part
- # of SCons:
- for frame in tb:
- filename = frame[0]
- if string.find(filename, os.sep+'SCons'+os.sep) == -1:
- return frame
- return tb[0]
-
-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.
- The file and line number will be the deepest stack frame that is
- not part of SCons itself.
- """
- etype, value, tb = sys.exc_info()
- filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
- sys.stderr.write("\nscons: *** %s\n" % value)
- sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
- sys.exit(2)
-
-def _scons_user_warning(e):
- """Handle user warnings. Print out a message and a description of
- the warning, along with the line number and routine where it occured.
- The file and line number will be the deepest stack frame that is
- not part of SCons itself.
- """
- etype, value, tb = sys.exc_info()
- filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb))
- sys.stderr.write("\nscons: warning: %s\n" % e)
- sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
-
-def _scons_internal_warning(e):
- """Slightly different from _scons_user_warning in that we use the
- *current call stack* rather than sys.exc_info() to get our stack trace.
- This is used by the warnings framework to print warnings."""
- filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_stack())
- sys.stderr.write("\nscons: warning: %s\n" % e[0])
- sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine))
-
-def _scons_internal_error():
- """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 'internal error'
- traceback.print_exc()
- sys.exit(2)
-
-def _varargs(option, parser):
- value = None
- if parser.rargs:
- arg = parser.rargs[0]
- if arg[0] != "-":
- value = arg
- del parser.rargs[0]
- return value
-
-def _setup_warn(arg):
- """The --warn option. An argument to this option
- should be of the form <warning-class> or no-<warning-class>.
- The warning class is munged in order to get an actual class
- name from the SCons.Warnings module to enable or disable.
- The supplied <warning-class> is split on hyphens, each element
- is captialized, then smushed back together. Then the string
- "SCons.Warnings." is added to the front and "Warning" is added
- to the back to get the fully qualified class name.
-
- For example, --warn=deprecated will enable the
- SCons.Warnings.DeprecatedWarning class.
-
- --warn=no-dependency will disable the
- SCons.Warnings.DependencyWarning class.
-
- As a special case, --warn=all and --warn=no-all
- will enable or disable (respectively) the base
- class of all warnings, which is SCons.Warning.Warning."""
-
- elems = string.split(string.lower(arg), '-')
- enable = 1
- if elems[0] == 'no':
- enable = 0
- del elems[0]
-
- if len(elems) == 1 and elems[0] == 'all':
- class_name = "Warning"
- else:
- def _capitalize(s):
- if s[:5] == "scons":
- return "SCons" + s[5:]
- else:
- return string.capitalize(s)
- class_name = string.join(map(_capitalize, elems), '') + "Warning"
- try:
- clazz = getattr(SCons.Warnings, class_name)
- except AttributeError:
- sys.stderr.write("No warning type: '%s'\n" % arg)
- else:
- if enable:
- SCons.Warnings.enableWarningClass(clazz)
- else:
- SCons.Warnings.suppressWarningClass(clazz)
-
-def _SConstruct_exists(dirname=''):
- """This function checks that an SConstruct file exists in a directory.
- If so, it returns the path of the file. By default, it checks the
- current directory.
- """
- global repositories
- for file in ['SConstruct', 'Sconstruct', 'sconstruct']:
- sfile = os.path.join(dirname, file)
- if os.path.isfile(sfile):
- return sfile
- if not os.path.isabs(sfile):
- for rep in repositories:
- if os.path.isfile(os.path.join(rep, sfile)):
- return sfile
- return None
-
-def _set_globals(options):
- global repositories, keep_going_on_error, ignore_errors
- global print_count, print_dtree
- global print_explanations, print_includes
- global print_objects, print_stacktrace, print_stree
- global print_time, print_tree
- global memory_outf, memory_stats
-
- if options.repository:
- repositories.extend(options.repository)
- keep_going_on_error = options.keep_going
- try:
- if options.debug:
- if options.debug == "count":
- print_count = 1
- elif options.debug == "dtree":
- print_dtree = 1
- elif options.debug == "explain":
- print_explanations = 1
- elif options.debug == "findlibs":
- SCons.Scanner.Prog.print_find_libs = "findlibs"
- elif options.debug == "includes":
- print_includes = 1
- elif options.debug == "memory":
- memory_stats = []
- memory_outf = sys.stdout
- elif options.debug == "objects":
- print_objects = 1
- elif options.debug == "presub":
- SCons.Action.print_actions_presub = 1
- elif options.debug == "stacktrace":
- print_stacktrace = 1
- elif options.debug == "stree":
- print_stree = 1
- elif options.debug == "time":
- print_time = 1
- elif options.debug == "tree":
- print_tree = 1
- except AttributeError:
- pass
- ignore_errors = options.ignore_errors
-
-def _create_path(plist):
- path = '.'
- for d in plist:
- if os.path.isabs(d):
- path = d
- else:
- path = path + '/' + d
- return path
-
-
-class OptParser(OptionParser):
- def __init__(self):
- import __main__
- import SCons
- parts = ["SCons by Steven Knight et al.:\n"]
- try:
- parts.append("\tscript: v%s.%s, %s, by %s on %s\n" % (__main__.__version__,
- __main__.__build__,
- __main__.__date__,
- __main__.__developer__,
- __main__.__buildsys__))
- except KeyboardInterrupt:
- raise
- except:
- # On win32 there is no scons.py, so there is no __main__.__version__,
- # hence there is no script version.
- pass
- parts.append("\tengine: v%s.%s, %s, by %s on %s\n" % (SCons.__version__,
- SCons.__build__,
- SCons.__date__,
- SCons.__developer__,
- SCons.__buildsys__))
- parts.append("__COPYRIGHT__")
- OptionParser.__init__(self, version=string.join(parts, ''),
- usage="usage: scons [OPTION] [TARGET] ...")
-
- # options ignored for compatibility
- def opt_ignore(option, opt, value, parser):
- sys.stderr.write("Warning: ignoring %s option\n" % opt)
- self.add_option("-b", "-m", "-S", "-t", "--no-keep-going", "--stop",
- "--touch", action="callback", callback=opt_ignore,
- help="Ignored for compatibility.")
-
- self.add_option('-c', '--clean', '--remove', action="store_true",
- dest="clean",
- help="Remove specified targets and dependencies.")
-
- self.add_option('-C', '--directory', type="string", action = "append",
- metavar="DIR",
- help="Change to DIR before doing anything.")
-
- self.add_option('--cache-disable', '--no-cache',
- action="store_true", dest='cache_disable', default=0,
- help="Do not retrieve built targets from CacheDir.")
-
- self.add_option('--cache-force', '--cache-populate',
- action="store_true", dest='cache_force', default=0,
- help="Copy already-built targets into the CacheDir.")
-
- self.add_option('--cache-show',
- action="store_true", dest='cache_show', default=0,
- help="Print build actions for files from CacheDir.")
-
- config_options = ["auto", "force" ,"cache"]
-
- def opt_config(option, opt, value, parser, c_options=config_options):
- if value in c_options:
- parser.values.config = value
- else:
- raise OptionValueError("Warning: %s is not a valid config type" % value)
- self.add_option('--config', action="callback", type="string",
- callback=opt_config, nargs=1, dest="config",
- metavar="MODE", default="auto",
- help="Controls Configure subsystem: "
- "%s." % string.join(config_options, ", "))
-
- def opt_not_yet(option, opt, value, parser):
- sys.stderr.write("Warning: the %s option is not yet implemented\n" % opt)
- sys.exit(0)
- self.add_option('-d', action="callback",
- callback=opt_not_yet,
- help = "Print file dependency information.")
-
- self.add_option('-D', action="store_const", const=2, dest="climb_up",
- help="Search up directory tree for SConstruct, "
- "build all Default() targets.")
-
- debug_options = ["count", "dtree", "explain", "findlibs",
- "includes", "memory", "objects",
- "pdb", "presub", "stacktrace", "stree",
- "time", "tree"]
-
- def opt_debug(option, opt, value, parser, debug_options=debug_options):
- if value in debug_options:
- parser.values.debug = value
- else:
- raise OptionValueError("Warning: %s is not a valid debug type" % value)
- self.add_option('--debug', action="callback", type="string",
- callback=opt_debug, nargs=1, dest="debug",
- metavar="TYPE",
- help="Print various types of debugging information: "
- "%s." % string.join(debug_options, ", "))
-
- def opt_duplicate(option, opt, value, parser):
- if not value in SCons.Node.FS.Valid_Duplicates:
- raise OptionValueError("`%s' is not a valid duplication style." % value)
- parser.values.duplicate = value
- # Set the duplicate style right away so it can affect linking
- # of SConscript files.
- SCons.Node.FS.set_duplicate(value)
- self.add_option('--duplicate', action="callback", type="string",
- callback=opt_duplicate, nargs=1, dest="duplicate",
- help="Set the preferred duplication methods. Must be one of "
- + string.join(SCons.Node.FS.Valid_Duplicates, ", "))
-
- self.add_option('-f', '--file', '--makefile', '--sconstruct',
- action="append", nargs=1,
- help="Read FILE as the top-level SConstruct file.")
-
- self.add_option('-h', '--help', action="store_true", default=0,
- dest="help_msg",
- help="Print defined help message, or this one.")
-
- self.add_option("-H", "--help-options",
- action="help",
- help="Print this message and exit.")
-
- self.add_option('-i', '--ignore-errors', action="store_true",
- default=0, dest='ignore_errors',
- help="Ignore errors from build actions.")
-
- self.add_option('-I', '--include-dir', action="append",
- dest='include_dir', metavar="DIR",
- help="Search DIR for imported Python modules.")
-
- self.add_option('--implicit-cache', action="store_true",
- dest='implicit_cache',
- help="Cache implicit dependencies")
-
- self.add_option('--implicit-deps-changed', action="store_true",
- default=0, dest='implicit_deps_changed',
- help="Ignore cached implicit dependencies.")
- self.add_option('--implicit-deps-unchanged', action="store_true",
- default=0, dest='implicit_deps_unchanged',
- help="Ignore changes in implicit dependencies.")
-
- def opt_j(option, opt, value, parser):
- value = int(value)
- parser.values.num_jobs = value
- self.add_option('-j', '--jobs', action="callback", type="int",
- callback=opt_j, metavar="N",
- help="Allow N jobs at once.")
-
- self.add_option('-k', '--keep-going', action="store_true", default=0,
- dest='keep_going',
- help="Keep going when a target can't be made.")
-
- self.add_option('--max-drift', type="int", action="store",
- dest='max_drift', metavar="N",
- help="Set maximum system clock drift to N seconds.")
-
- self.add_option('-n', '--no-exec', '--just-print', '--dry-run',
- '--recon', action="store_true", dest='noexec',
- default=0, help="Don't build; just print commands.")
-
- def opt_profile(option, opt, value, parser):
- global profiling
- if not profiling:
- profiling = 1
- import profile
- profile.run('SCons.Script.main()', value)
- sys.exit(exit_status)
- self.add_option('--profile', nargs=1, action="callback",
- callback=opt_profile, type="string", dest="profile",
- metavar="FILE",
- help="Profile SCons and put results in FILE.")
-
- self.add_option('-q', '--question', action="store_true", default=0,
- help="Don't build; exit status says if up to date.")
-
- self.add_option('-Q', dest='no_progress', action="store_true",
- default=0,
- help="Suppress \"Reading/Building\" progress messages.")
-
- self.add_option('--random', dest="random", action="store_true",
- default=0, help="Build dependencies in random order.")
-
- self.add_option('-s', '--silent', '--quiet', action="store_true",
- default=0, help="Don't print commands.")
-
- self.add_option('-u', '--up', '--search-up', action="store_const",
- dest="climb_up", default=0, const=1,
- help="Search up directory tree for SConstruct, "
- "build targets at or below current directory.")
- self.add_option('-U', action="store_const", dest="climb_up",
- default=0, const=3,
- help="Search up directory tree for SConstruct, "
- "build Default() targets from local SConscript.")
-
- self.add_option("-v", "--version",
- action="version",
- help="Print the SCons version number and exit.")
-
- self.add_option('--warn', '--warning', nargs=1, action="store",
- metavar="WARNING-SPEC",
- help="Enable or disable warnings.")
-
- self.add_option('-Y', '--repository', nargs=1, action="append",
- help="Search REPOSITORY for source and target files.")
-
- self.add_option('-e', '--environment-overrides', action="callback",
- callback=opt_not_yet,
- # help="Environment variables override makefiles."
- help=SUPPRESS_HELP)
- self.add_option('-l', '--load-average', '--max-load', action="callback",
- callback=opt_not_yet, type="int", dest="load_average",
- # action="store",
- # help="Don't start multiple jobs unless load is below "
- # "LOAD-AVERAGE."
- # type="int",
- help=SUPPRESS_HELP)
- self.add_option('--list-derived', action="callback",
- callback=opt_not_yet,
- # help="Don't build; list files that would be built."
- help=SUPPRESS_HELP)
- self.add_option('--list-actions', action="callback",
- callback=opt_not_yet,
- # help="Don't build; list files and build actions."
- help=SUPPRESS_HELP)
- self.add_option('--list-where', action="callback",
- callback=opt_not_yet,
- # help="Don't build; list files and where defined."
- help=SUPPRESS_HELP)
- self.add_option('-o', '--old-file', '--assume-old', action="callback",
- callback=opt_not_yet, type="string", dest="old_file",
- # help = "Consider FILE to be old; don't rebuild it."
- help=SUPPRESS_HELP)
- self.add_option('--override', action="callback", dest="override",
- callback=opt_not_yet, type="string",
- # help="Override variables as specified in FILE."
- help=SUPPRESS_HELP)
- self.add_option('-p', action="callback",
- callback=opt_not_yet,
- # help="Print internal environments/objects."
- help=SUPPRESS_HELP)
- self.add_option('-r', '-R', '--no-builtin-rules',
- '--no-builtin-variables', action="callback",
- callback=opt_not_yet,
- # help="Clear default environments and variables."
- help=SUPPRESS_HELP)
- self.add_option('-w', '--print-directory', action="callback",
- callback=opt_not_yet,
- # help="Print the current directory."
- help=SUPPRESS_HELP)
- self.add_option('--no-print-directory', action="callback",
- callback=opt_not_yet,
- # help="Turn off -w, even if it was turned on implicitly."
- help=SUPPRESS_HELP)
- self.add_option('--write-filenames', action="callback",
- callback=opt_not_yet, type="string", dest="write_filenames",
- # help="Write all filenames examined into FILE."
- help=SUPPRESS_HELP)
- self.add_option('-W', '--what-if', '--new-file', '--assume-new',
- dest="new_file",
- action="callback", callback=opt_not_yet, type="string",
- # help="Consider FILE to be changed."
- help=SUPPRESS_HELP)
- self.add_option('--warn-undefined-variables', action="callback",
- callback=opt_not_yet,
- # help="Warn when an undefined variable is referenced."
- help=SUPPRESS_HELP)
-
- def parse_args(self, args=None, values=None):
- opt, arglist = OptionParser.parse_args(self, args, values)
- if opt.implicit_deps_changed or opt.implicit_deps_unchanged:
- opt.implicit_cache = 1
- return opt, arglist
-
-class SConscriptSettableOptions:
- """This class wraps an OptParser instance and provides
- uniform access to options that can be either set on the command
- line or from a SConscript file. A value specified on the command
- line always overrides a value set in a SConscript file.
- Not all command line options are SConscript settable, and the ones
- that are must be explicitly added to settable dictionary and optionally
- validated and coerced in the set() method."""
-
- def __init__(self, options):
- self.options = options
-
- # This dictionary stores the defaults for all the SConscript
- # settable options, as well as indicating which options
- # are SConscript settable.
- self.settable = {'num_jobs':1,
- 'max_drift':SCons.Sig.default_max_drift,
- 'implicit_cache':0,
- 'clean':0,
- 'duplicate':'hard-soft-copy'}
-
- def get(self, name):
- if not self.settable.has_key(name):
- raise SCons.Error.UserError, "This option is not settable from a SConscript file: %s"%name
- if hasattr(self.options, name) and getattr(self.options, name) is not None:
- return getattr(self.options, name)
- else:
- return self.settable[name]
-
- def set(self, name, value):
- if not self.settable.has_key(name):
- raise SCons.Error.UserError, "This option is not settable from a SConscript file: %s"%name
-
- if name == 'num_jobs':
- try:
- value = int(value)
- if value < 1:
- raise ValueError
- except ValueError:
- raise SCons.Errors.UserError, "A positive integer is required: %s"%repr(value)
- elif name == 'max_drift':
- try:
- value = int(value)
- except ValueError:
- raise SCons.Errors.UserError, "An integer is required: %s"%repr(value)
- elif name == 'duplicate':
- try:
- value = str(value)
- except ValueError:
- raise SCons.Errors.UserError, "A string is required: %s"%repr(value)
- if not value in SCons.Node.FS.Valid_Duplicates:
- raise SCons.Errors.UserError, "Not a valid duplication style: %s" % value
- # Set the duplicate stye right away so it can affect linking
- # of SConscript files.
- SCons.Node.FS.set_duplicate(value)
-
- self.settable[name] = value
-
-
-def _main(args, parser):
- targets = []
- fs = SCons.Node.FS.default_fs
-
- # Enable deprecated warnings by default.
- SCons.Warnings._warningOut = _scons_internal_warning
- SCons.Warnings.enableWarningClass(SCons.Warnings.CorruptSConsignWarning)
- SCons.Warnings.enableWarningClass(SCons.Warnings.DeprecatedWarning)
- SCons.Warnings.enableWarningClass(SCons.Warnings.DuplicateEnvironmentWarning)
- SCons.Warnings.enableWarningClass(SCons.Warnings.MissingSConscriptWarning)
- SCons.Warnings.enableWarningClass(SCons.Warnings.NoParallelSupportWarning)
- # This is good for newbies, and hopefully most everyone else too.
- SCons.Warnings.enableWarningClass(SCons.Warnings.MisleadingKeywordsWarning)
-
- global ssoptions
- ssoptions = SConscriptSettableOptions(options)
-
- _set_globals(options)
- SCons.Node.implicit_cache = options.implicit_cache
- SCons.Node.implicit_deps_changed = options.implicit_deps_changed
- SCons.Node.implicit_deps_unchanged = options.implicit_deps_unchanged
- if options.warn:
- _setup_warn(options.warn)
- if options.noexec:
- SCons.SConf.dryrun = 1
- SCons.Action.execute_actions = None
- CleanTask.execute = CleanTask.show
- if options.question:
- SCons.SConf.dryrun = 1
- SCons.SConf.SetCacheMode(options.config)
- SCons.SConf.SetProgressDisplay(progress_display)
-
- if options.no_progress or options.silent:
- progress_display.set_mode(0)
- if options.silent:
- display.set_mode(0)
- if options.silent:
- SCons.Action.print_actions = None
- if options.cache_disable:
- def disable(self): pass
- fs.CacheDir = disable
- if options.cache_force:
- fs.cache_force = 1
- if options.cache_show:
- fs.cache_show = 1
- if options.directory:
- cdir = _create_path(options.directory)
- try:
- os.chdir(cdir)
- except OSError:
- sys.stderr.write("Could not change directory to %s\n" % cdir)
-
- xmit_args = []
- for a in args:
- if '=' in a:
- xmit_args.append(a)
- else:
- targets.append(a)
- SCons.Script.SConscript._scons_add_args(xmit_args)
- SCons.Script.SConscript._scons_add_targets(targets)
-
- target_top = None
- if options.climb_up:
- target_top = '.' # directory to prepend to targets
- script_dir = os.getcwd() # location of script
- while script_dir and not _SConstruct_exists(script_dir):
- script_dir, last_part = os.path.split(script_dir)
- if last_part:
- target_top = os.path.join(last_part, target_top)
- else:
- script_dir = ''
- if script_dir:
- display("scons: Entering directory `%s'" % script_dir)
- os.chdir(script_dir)
- else:
- raise SCons.Errors.UserError, "No SConstruct file found."
-
- fs.set_toplevel_dir(os.getcwd())
-
- scripts = []
- if options.file:
- scripts.extend(options.file)
- if not scripts:
- sfile = _SConstruct_exists()
- if sfile:
- scripts.append(sfile)
-
- if options.help_msg:
- if not scripts:
- # There's no SConstruct, but they specified -h.
- # Give them the options usage now, before we fail
- # trying to read a non-existent SConstruct file.
- parser.print_help()
- sys.exit(0)
- SCons.Script.SConscript.print_help = 1
-
- if not scripts:
- raise SCons.Errors.UserError, "No SConstruct file found."
-
- if scripts[0] == "-":
- d = fs.getcwd()
- else:
- d = fs.File(scripts[0]).dir
- fs.set_SConstruct_dir(d)
-
- class Unbuffered:
- def __init__(self, file):
- self.file = file
- def write(self, arg):
- self.file.write(arg)
- self.file.flush()
- def __getattr__(self, attr):
- return getattr(self.file, attr)
-
- sys.stdout = Unbuffered(sys.stdout)
-
- if options.include_dir:
- sys.path = options.include_dir + sys.path
-
- global repositories
- for rep in repositories:
- fs.Repository(rep)
-
- if not memory_stats is None: memory_stats.append(SCons.Debug.memory())
-
- progress_display("scons: Reading SConscript files ...")
-
- start_time = time.time()
- try:
- for script in scripts:
- SCons.Script.SConscript._SConscript(fs, script)
- except SCons.Errors.StopError, e:
- # We had problems reading an SConscript file, such as it
- # couldn't be copied in to the BuildDir. Since we're just
- # reading SConscript files and haven't started building
- # things yet, stop regardless of whether they used -i or -k
- # or anything else.
- global exit_status
- sys.stderr.write("scons: *** %s Stop.\n" % e)
- exit_status = 2
- sys.exit(exit_status)
- global sconscript_time
- sconscript_time = time.time() - start_time
- SCons.SConf.CreateConfigHBuilder(SCons.Defaults.DefaultEnvironment())
- progress_display("scons: done reading SConscript files.")
-
- # Tell the Node.FS subsystem that we're all done reading the
- # SConscript files and calling Repository() and BuildDir() and the
- # like, so it can go ahead and start memoizing the string values of
- # file system nodes.
- SCons.Node.FS.save_strings(1)
-
- if not memory_stats is None: memory_stats.append(SCons.Debug.memory())
-
- fs.chdir(fs.Top)
-
- if options.help_msg:
- if SCons.Script.SConscript.help_text is None:
- # They specified -h, but there was no Help() inside the
- # SConscript files. Give them the options usage.
- parser.print_help(sys.stdout)
- else:
- print SCons.Script.SConscript.help_text
- print "Use scons -H for help about command-line options."
- sys.exit(0)
-
- # Now that we've read the SConscripts we can set the options
- # that are SConscript settable:
- SCons.Node.implicit_cache = ssoptions.get('implicit_cache')
- SCons.Node.FS.set_duplicate(ssoptions.get('duplicate'))
-
- lookup_top = None
- if targets:
- # They specified targets on the command line, so if they
- # used -u, -U or -D, we have to look up targets relative
- # to the top, but we build whatever they specified.
- if target_top:
- lookup_top = fs.Dir(target_top)
- target_top = None
- else:
- # There are no targets specified on the command line,
- # so if they used -u, -U or -D, we may have to restrict
- # what actually gets built.
- d = None
- if target_top:
- if options.climb_up == 1:
- # -u, local directory and below
- target_top = fs.Dir(target_top)
- lookup_top = target_top
- elif options.climb_up == 2:
- # -D, all Default() targets
- target_top = None
- lookup_top = None
- elif options.climb_up == 3:
- # -U, local SConscript Default() targets
- target_top = fs.Dir(target_top)
- def check_dir(x, target_top=target_top):
- if hasattr(x, 'cwd') and not x.cwd is None:
- cwd = x.cwd.srcnode()
- return cwd == target_top
- else:
- # x doesn't have a cwd, so it's either not a target,
- # or not a file, so go ahead and keep it as a default
- # target and let the engine sort it out:
- return 1
- d = filter(check_dir, SCons.Script.SConscript.DefaultTargets)
- SCons.Script.SConscript.DefaultTargets[:] = d
- target_top = None
- lookup_top = None
-
- if SCons.Script.SConscript.DefaultCalled:
- targets = SCons.Script.SConscript.DefaultTargets
- else:
- if d is None:
- d = [fs.Dir('.')]
- targets = d
+import SCons.Defaults
+import Main
- if not targets:
- sys.stderr.write("scons: *** No targets specified and no Default() targets found. Stop.\n")
- sys.exit(2)
+main = Main.main
- def Entry(x, ltop=lookup_top, ttop=target_top, fs=fs):
- if isinstance(x, SCons.Node.Node):
- node = x
- else:
- node = SCons.Node.Alias.default_ans.lookup(x)
- if node is None:
- node = fs.Entry(x, directory=ltop, create=1)
- if ttop and not node.is_under(ttop):
- if isinstance(node, SCons.Node.FS.Dir) and ttop.is_under(node):
- node = ttop
- else:
- node = None
- return node
+import SConscript
+_SConscript = SConscript
- nodes = filter(lambda x: x is not None, map(Entry, targets))
+call_stack = _SConscript.call_stack
- task_class = BuildTask # default action is to build targets
- opening_message = "Building targets ..."
- closing_message = "done building targets."
- if keep_going_on_error:
- failure_message = "done building targets (errors occurred during build)."
- else:
- failure_message = "building terminated because of errors."
- if options.question:
- task_class = QuestionTask
- try:
- if ssoptions.get('clean'):
- task_class = CleanTask
- opening_message = "Cleaning targets ..."
- closing_message = "done cleaning targets."
- if keep_going_on_error:
- closing_message = "done cleaning targets (errors occurred during clean)."
- else:
- failure_message = "cleaning terminated because of errors."
- except AttributeError:
+#
+Action = SCons.Action.Action
+BoolOption = SCons.Options.BoolOption
+Builder = SCons.Builder.Builder
+Configure = _SConscript.Configure
+EnumOption = SCons.Options.EnumOption
+Environment = SCons.Environment.Environment
+ListOption = SCons.Options.ListOption
+PackageOption = SCons.Options.PackageOption
+PathOption = SCons.Options.PathOption
+Platform = SCons.Platform.Platform
+Return = _SConscript.Return
+Scanner = SCons.Scanner.Base
+Tool = SCons.Tool.Tool
+WhereIs = SCons.Util.WhereIs
+
+# Action factories.
+Chmod = SCons.Defaults.Chmod
+Copy = SCons.Defaults.Copy
+Delete = SCons.Defaults.Delete
+Mkdir = SCons.Defaults.Mkdir
+Move = SCons.Defaults.Move
+Touch = SCons.Defaults.Touch
+
+# Functions we might still convert to Environment methods.
+CScan = SCons.Defaults.CScan
+DefaultEnvironment = SCons.Defaults.DefaultEnvironment
+
+# Other variables we provide.
+class TargetList(UserList.UserList):
+ def _do_nothing(self, *args, **kw):
pass
-
- SCons.Environment.CalculatorArgs['max_drift'] = ssoptions.get('max_drift')
-
- if options.random:
- def order(dependencies):
- """Randomize the dependencies."""
- # This is cribbed from the implementation of
- # random.shuffle() in Python 2.X.
- d = dependencies
- for i in xrange(len(d)-1, 0, -1):
- j = int(random.random() * (i+1))
- d[i], d[j] = d[j], d[i]
- return d
- else:
- def order(dependencies):
- """Leave the order of dependencies alone."""
- return dependencies
-
- progress_display("scons: " + opening_message)
- taskmaster = SCons.Taskmaster.Taskmaster(nodes, task_class, order)
-
- nj = ssoptions.get('num_jobs')
- jobs = SCons.Job.Jobs(nj, taskmaster)
- if nj > 1 and jobs.num_jobs == 1:
- msg = "parallel builds are unsupported by this version of Python;\n" + \
- "\tignoring -j or num_jobs option.\n"
- SCons.Warnings.warn(SCons.Warnings.NoParallelSupportWarning, msg)
-
- if not memory_stats is None: memory_stats.append(SCons.Debug.memory())
-
- try:
- jobs.run()
- finally:
- if exit_status:
- progress_display("scons: " + failure_message)
+ def _add_Default(self, list):
+ self.extend(list)
+ def _clear(self):
+ del self[:]
+
+ARGUMENTS = {}
+ARGLIST = []
+BUILD_TARGETS = TargetList()
+COMMAND_LINE_TARGETS = []
+DEFAULT_TARGETS = []
+
+def _Add_Arguments(alist):
+ for arg in alist:
+ a, b = string.split(arg, '=', 1)
+ ARGUMENTS[a] = b
+ ARGLIST.append((a, b))
+
+def _Add_Targets(tlist):
+ if tlist:
+ COMMAND_LINE_TARGETS.extend(tlist)
+ BUILD_TARGETS.extend(tlist)
+ BUILD_TARGETS._add_Default = BUILD_TARGETS._do_nothing
+ BUILD_TARGETS._clear = BUILD_TARGETS._do_nothing
+
+def _Set_Default_Targets_Has_Been_Called(d, fs):
+ return DEFAULT_TARGETS
+
+def _Set_Default_Targets_Has_Not_Been_Called(d, fs):
+ if d is None:
+ d = [fs.Dir('.')]
+ return d
+
+_Get_Default_Targets = _Set_Default_Targets_Has_Not_Been_Called
+
+def _Set_Default_Targets(env, tlist):
+ global DEFAULT_TARGETS
+ global _Get_Default_Targets
+ _Get_Default_Targets = _Set_Default_Targets_Has_Been_Called
+ for t in tlist:
+ if t is None:
+ # Delete the elements from the list in-place, don't
+ # reassign an empty list to DEFAULT_TARGETS, so that the
+ # variables will still point to the same object we point to.
+ del DEFAULT_TARGETS[:]
+ BUILD_TARGETS._clear()
+ elif isinstance(t, SCons.Node.Node):
+ DEFAULT_TARGETS.append(t)
+ BUILD_TARGETS._add_Default([t])
else:
- progress_display("scons: " + closing_message)
- if not options.noexec:
- SCons.SConsign.write()
-
- if not memory_stats is None:
- memory_stats.append(SCons.Debug.memory())
- when = [
- 'before SConscript files',
- 'after SConscript files',
- 'before building',
- 'after building',
- ]
- for i in xrange(len(when)):
- memory_outf.write('Memory %s: %d\n' % (when[i], memory_stats[i]))
-
- if print_count:
- SCons.Debug.countLoggedInstances('*')
+ nodes = env.arg2nodes(t, env.fs.Entry)
+ DEFAULT_TARGETS.extend(nodes)
+ BUILD_TARGETS._add_Default(nodes)
- if print_objects:
- SCons.Debug.listLoggedInstances('*')
- #SCons.Debug.dumpLoggedInstances('*')
+#
+help_text = None
-def _exec_main():
- all_args = sys.argv[1:]
- try:
- all_args = string.split(os.environ['SCONSFLAGS']) + all_args
- except KeyError:
- # it's OK if there's no SCONSFLAGS
- pass
- parser = OptParser()
- global options
- options, args = parser.parse_args(all_args)
- if options.debug == "pdb":
- import pdb
- pdb.Pdb().runcall(_main, args, parser)
+def HelpFunction(text):
+ global help_text
+ if SCons.Script.help_text is None:
+ SCons.Script.help_text = text
else:
- _main(args, parser)
-
-def main():
- global exit_status
-
- try:
- _exec_main()
- except SystemExit, s:
- if s:
- exit_status = s
- except KeyboardInterrupt:
- print "Build interrupted."
- sys.exit(2)
- except SyntaxError, e:
- _scons_syntax_error(e)
- except SCons.Errors.InternalError:
- _scons_internal_error()
- except SCons.Errors.UserError, e:
- _scons_user_error(e)
- except:
- # An exception here is likely a builtin Python exception Python
- # code in an SConscript file. Show them precisely what the
- # problem was and where it happened.
- SCons.Script.SConscript.SConscript_exception()
- sys.exit(2)
+ help_text = help_text + text
- if print_time:
- total_time = time.time()-start_time
- scons_time = total_time-sconscript_time-command_time
- print "Total build time: %f seconds"%total_time
- print "Total SConscript file execution time: %f seconds"%sconscript_time
- print "Total SCons execution time: %f seconds"%scons_time
- print "Total command execution time: %f seconds"%command_time
+#
+# Will be set to 1 if we are reading a SConscript.
+sconscript_reading = 0
- sys.exit(exit_status)
+#
+def Options(files=None, args=ARGUMENTS):
+ return SCons.Options.Options(files, args)
+
+# The list of global functions to add to the SConscript name space
+# that end up calling corresponding methods or Builders in the
+# DefaultEnvironment().
+GlobalDefaultEnvironmentFunctions = [
+ # Methods from the SConsEnvironment class, above.
+ 'Default',
+ 'EnsurePythonVersion',
+ 'EnsureSConsVersion',
+ 'Exit',
+ 'Export',
+ 'GetLaunchDir',
+ 'GetOption',
+ 'Help',
+ 'Import',
+ 'SConscript',
+ 'SConscriptChdir',
+ 'SetOption',
+
+ # Methods from the Environment.Base class.
+ 'AddPostAction',
+ 'AddPreAction',
+ 'Alias',
+ 'AlwaysBuild',
+ 'BuildDir',
+ 'CacheDir',
+ 'Clean',
+ 'Command',
+ 'Depends',
+ 'Dir',
+ 'Execute',
+ 'File',
+ 'FindFile',
+ 'Flatten',
+ 'GetBuildPath',
+ 'Ignore',
+ 'Install',
+ 'InstallAs',
+ 'Literal',
+ 'Local',
+ 'ParseDepends',
+ 'Precious',
+ 'Repository',
+ 'SConsignFile',
+ 'SideEffect',
+ 'SourceCode',
+ 'SourceSignatures',
+ 'Split',
+ 'TargetSignatures',
+ 'Value',
+]
+
+GlobalDefaultBuilders = [
+ # Supported builders.
+ 'CFile',
+ 'CXXFile',
+ 'DVI',
+ 'Jar',
+ 'Java',
+ 'JavaH',
+ 'Library',
+ 'M4',
+ 'MSVSProject',
+ 'Object',
+ 'PCH',
+ 'PDF',
+ 'PostScript',
+ 'Program',
+ 'RES',
+ 'RMIC',
+ 'SharedLibrary',
+ 'SharedObject',
+ 'StaticLibrary',
+ 'StaticObject',
+ 'Tar',
+ 'TypeLibrary',
+ 'Zip',
+]
+
+for name in GlobalDefaultEnvironmentFunctions + GlobalDefaultBuilders:
+ exec "%s = _SConscript.DefaultEnvironmentCall(%s)" % (name, repr(name))