diff options
Diffstat (limited to 'src/scons.py')
| -rw-r--r-- | src/scons.py | 374 | 
1 files changed, 348 insertions, 26 deletions
diff --git a/src/scons.py b/src/scons.py index 04292da..49f8dec 100644 --- a/src/scons.py +++ b/src/scons.py @@ -51,6 +51,8 @@ class Taskmaster:  # Global variables +local_help = None +num_jobs = 1  Scripts = []  # utility functions @@ -86,49 +88,363 @@ def _scons_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): +    global Scripts      Scripts.append(filename) -def main(): +def Help(text): +    global local_help +    if local_help: +	print text +	print "Use scons -H for help about command-line options." +	sys.exit(0) + + +option_list = [] + +# Generic routine for to-be-written options, used by multiple options below. + +def opt_not_yet(opt, arg): +    sys.stderr.write("Warning:  the %s option is not yet implemented\n" % opt) + +class Option: +    """Class for command-line option information. + +    This exists to provide a central location for everything +    describing a command-line option, so that we can change +    options without having to update the code to handle the +    option in one place, the -h help message in another place, +    etc.  There are no methods here, only attributes. + +    You can initialize an Option with the following: + +	func	The function that will be called when this +		option is processed on the command line. +		Calling sequence is: + +			func(opt, arg) + +		If there is no func, then this Option probably +		stores an optstring to be printed. + +	helpline +		The string to be printed in -h output.  If no +		helpline is specified but a help string is +		specified (the usual case), a helpline will be +		constructed automatically from the short, long, +		arg, and help attributes.  (In practice, then, +		setting helpline without setting func allows you +		to print arbitrary lines of text in the -h +		output.) + +	short	The string for short, single-hyphen +		command-line options. +		Do not include the hyphen: + +			'a' for -a, 'xy' for -x and -y, etc. + +	long	An array of strings for long, double-hyphen +		command-line options.  Do not include +		the hyphens: + +			['my-option', 'verbose'] + +	arg	If this option takes an argument, this string +		specifies how you want it to appear in the +		-h output ('DIRECTORY', 'FILE', etc.). + +	help	The help string that will be printed for +		this option in the -h output.  Must be +		49 characters or fewer. + +	future	If non-zero, this indicates that this feature +		will be supported in a future release, not +		the currently planned one.  SCons will +		recognize the option, but it won't show up +		in the -h output. + +    The following attribute is derived from the supplied attributes: + +	optstring +		A string, with hyphens, describing the flags +		for this option, as constructed from the +		specified short, long and arg attributes. + +    All Option objects are stored in the global option_list list, +    in the order in which they're created.  This is the list +    that's used to generate -h output, so the order in which the +    objects are created is the order in which they're printed. + +    The upshot is that specifying a command-line option and having +    everything work correctly is a matter of defining a function to +    process its command-line argument (set the right flag, update +    the right value), and then creating an appropriate Option object +    at the correct point in the code below. +    """ + +    def __init__(self, func = None, helpline = None, +		 short = None, long = None, arg = None, +		 help = None, future = None): +	self.func = func +	self.short = short +	self.long = long +	self.arg = arg +	self.help = help +	opts = [] +	if self.short: +	    for c in self.short: +		if arg: +		    c = c + " " + arg +		opts = opts + ['-' + c] +	if self.long: +	    l = self.long +	    if arg: +		l = map(lambda x,a=arg: x + "=" + a, self.long) +	    opts = opts + map(lambda x: '--' + x, l) +	self.optstring = string.join(opts, ', ') +	if helpline: +	    self.helpline = helpline +	elif help and not future: +	    if len(self.optstring) <= 26: +		sep = " " * (28 - len(self.optstring)) +	    else: +		sep = self.helpstring = "\n" + " " * 30 +	    self.helpline = "  " + self.optstring + sep + self.help +	else: +	    self.helpline = None +	global option_list +	option_list.append(self) + +# In the following instantiations, the help string should be no +# longer than 49 characters.  Use the following as a guide: +#	help = "1234567890123456789012345678901234567890123456789" + +def opt_ignore(opt, arg): +    sys.stderr.write("Warning:  ignoring %s option\n" % opt) + +Option(func = opt_ignore, +	short = 'bmSt', long = ['no-keep-going', 'stop', 'touch'], +	help = "Ignored for compatibility.") + +Option(func = opt_not_yet, +	short = 'c', long = ['clean', 'remove'], +	help = "Remove specified targets and dependencies.") + +Option(func = opt_not_yet, future = 1, +	long = ['cache-disable', 'no-cache'], +	help = "Do not retrieve built targets from Cache.") + +Option(func = opt_not_yet, future = 1, +	long = ['cache-force', 'cache-populate'], +	help = "Copy already-built targets into the Cache.") + +Option(func = opt_not_yet, future = 1, +	long = ['cache-show'], +	help = "Print what would have built Cached targets.") + +Option(func = opt_not_yet, +	short = 'C', long = ['directory'], arg = 'DIRECTORY', +	help = "Change to DIRECTORY before doing anything.") + +Option(func = opt_not_yet, +	short = 'd', +	help = "Print file dependency information.") + +Option(func = opt_not_yet, future = 1, +	long = ['debug'], arg = 'FLAGS', +	help = "Print various types of debugging information.") + +Option(func = opt_not_yet, future = 1, +	short = 'e', long = ['environment-overrides'], +	help = "Environment variables override makefiles.") + +def opt_f(opt, arg):      global Scripts +    Scripts.append(arg) + +Option(func = opt_f, +	short = 'f', long = ['file', 'makefile', 'sconstruct'], arg = 'FILE', +	help = "Read FILE as the top-level SConstruct file.") + +def opt_help(opt, arg): +    global local_help +    local_help = 1 + +Option(func = opt_help, +	short = 'h', long = ['help'], +	help = "Print defined help message, or this one.") + +def opt_help_options(opt, arg): +    PrintUsage() +    sys.exit(0) + +Option(func = opt_help_options, +	short = 'H', long = ['help-options'], +	help = "Print this message and exit.") +Option(func = opt_not_yet, +	short = 'i', long = ['ignore-errors'], +	help = "Ignore errors from build actions.") + +Option(func = opt_not_yet, +	short = 'I', long = ['include-dir'], arg = 'DIRECTORY', +	help = "Search DIRECTORY for imported Python modules.") + +def opt_j(opt, arg): +    global num_jobs      try: -        opts, targets = getopt.getopt(sys.argv[1:], 'f:j:', ['help']) -    except getopt.GetoptError, x: -        print x +        num_jobs = int(arg) +    except:          PrintUsage()          sys.exit(1) -    num_jobs = 1 -    for o, a in opts: -        if o == '-f': Scripts.append(a) +    if num_jobs <= 0: +        PrintUsage() +        sys.exit(1) -        if o == '-j': -            try: -                num_jobs = int(a) -            except: -                PrintUsage() -                sys.exit(1) +Option(func = opt_j, +	short = 'j', long = ['jobs'], arg = 'N', +	help = "Allow N jobs at once.") + +Option(func = opt_not_yet, +	short = 'k', long = ['keep-going'], +	help = "Keep going when a target can't be made.") + +Option(func = opt_not_yet, future = 1, +	short = 'l', long = ['load-average', 'max-load'], arg = 'N', +	help = "Don't start multiple jobs unless load is below N.") + +Option(func = opt_not_yet, future = 1, +	long = ['list-derived'], +	help = "Don't build; list files that would be built.") + +Option(func = opt_not_yet, future = 1, +	long = ['list-actions'], +	help = "Don't build; list files and build actions.") + +Option(func = opt_not_yet, future = 1, +	long = ['list-where'], +	help = "Don't build; list files and where defined.") + +Option(func = opt_not_yet, +	short = 'n', long = ['no-exec', 'just-print', 'dry-run', 'recon'], +	help = "Don't build; just print commands.") + +Option(func = opt_not_yet, future = 1, +	short = 'o', long = ['old-file', 'assume-old'], arg = 'FILE', +	help = "Consider FILE to be old; don't rebuild it.") + +Option(func = opt_not_yet, future = 1, +	long = ['override'], arg = 'FILE', +	help = "Override variables as specified in FILE.") + +Option(func = opt_not_yet, future = 1, +	short = 'p', +	help = "Print internal environments/objects.") + +Option(func = opt_not_yet, future = 1, +	short = 'q', long = ['question'], +	help = "Don't build; exit status says if up to date.") + +Option(func = opt_not_yet, future = 1, +	short = 'rR', long = ['no-builtin-rules', 'no-builtin-variables'], +	help = "Clear default environments and variables.") + +Option(func = opt_not_yet, future = 1, +	long = ['random'], +	help = "Build dependencies in random order.") + +Option(func = opt_not_yet, +	short = 's', long = ['silent', 'quiet'], +	help = "Don't print commands.") + +Option(func = opt_not_yet, future = 1, +	short = 'u', long = ['up', 'search-up'], +	help = "Search up directory tree for SConstruct.") + +Option(func = opt_not_yet, +	short = 'v', long = ['version'], +	help = "Print the SCons version number and exit.") + +Option(func = opt_not_yet, +	short = 'w', long = ['print-directory'], +	help = "Print the current directory.") + +Option(func = opt_not_yet, +	long = ['no-print-directory'], +	help = "Turn off -w, even if it was turned on implicitly.") + +Option(func = opt_not_yet, future = 1, +	long = ['write-filenames'], arg = 'FILE', +	help = "Write all filenames examined into FILE.") + +Option(func = opt_not_yet, future = 1, +	short = 'W', long = ['what-if', 'new-file', 'assume-new'], arg = 'FILE', +	help = "Consider FILE to be changed.") + +Option(func = opt_not_yet, future = 1, +	long = ['warn-undefined-variables'], +	help = "Warn when an undefined variable is referenced.") + +Option(func = opt_not_yet, future = 1, +	short = 'Y', long = ['repository'], arg = 'REPOSITORY', +	help = "Search REPOSITORY for source and target files.") + +short_opts = "" +long_opts = [] +opt_func = {} + +for o in option_list: +    if o.short: +	if o.func: +	    for c in o.short: +		opt_func['-' + c] = o.func +	short_opts = short_opts + o.short +	if o.arg: +	    short_opts = short_opts + ":" +    if o.long: +	if o.func: +	    for l in o.long: +		opt_func['--' + l] = o.func +	if o.arg: +	    long_opts = long_opts + map(lambda a: a + "=", o.long) +	else: +	    long_opts = long_opts + o.long -            if num_jobs <= 0: -                PrintUsage() -                sys.exit(1) -        if o == '--help': -            PrintUsage() -            sys.exit(0) + +def PrintUsage(): +    print "Usage: scons [OPTION] [TARGET] ..." +    print "Options:" +    for o in option_list: +	if o.helpline: +	    print o.helpline + + + +def main(): +    global Scripts, local_help, num_jobs + +    try: +	cmd_opts, targets = getopt.getopt(sys.argv[1:], short_opts, long_opts) +#   except getopt.GetoptError, x: +    except: +        #print x +        PrintUsage() +        sys.exit(1) + +    for opt, arg in cmd_opts: +	opt_func[opt](opt, arg)      if not Scripts:          Scripts.append('SConstruct') +    if local_help and not os.path.isfile(Scripts[0]): +	# They specified -h, but there's no SConstruct.  Give them +	# the options usage before we try to read it and fail. +	PrintUsage() +	sys.exit(0)      # 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 @@ -152,6 +468,12 @@ def main():          file, Scripts = Scripts[0], Scripts[1:]          execfile(file) +    if local_help: +	# They specified -h, but there was no Help() inside the +	# SConscript files.  Give them the options usage. +	PrintUsage() +	sys.exit(0) +      taskmaster = Taskmaster(map(lambda x: lookup(File, x), targets))      jobs = scons.Job.Jobs(num_jobs, taskmaster)  | 
