#!/usr/bin/env python3 # Copyright (c) 2006 The Regents of The University of Michigan # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer; # redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution; # neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os, re, sys from os.path import isdir, isfile, join as joinpath homedir = os.environ['HOME'] def do_compile(): # # Find SCons # search_dirs = [ joinpath(homedir, 'local/lib'), '/opt/local/lib', '/usr/local/lib', '/usr/lib' ] if os.environ.has_key("SCONS_LIB_DIR"): search_dirs.append(os.environ["SCONS_LIB_DIR"]) local = re.compile(r'^scons-local-([0-9]*)\.([0-9]*)\.([0-9]*)$') standard = re.compile(r'^scons-([0-9]*)\.([0-9]*)\.([0-9]*)$') scons_dirs = [] for dir in search_dirs: if not isdir(dir): continue entries = os.listdir(dir) for entry in entries: if not entry.startswith('scons'): continue version = (0,0,0) path = joinpath(dir, entry) match = local.search(entry) if not match: match = standard.search(entry) if match: version = match.group(1), match.group(2), match.group(3) scons_dirs.append((version, path)) scons_dirs.sort() scons_dirs.reverse() if not scons_dirs: print >>sys.stderr, \ "could not find scons in the following dirs: %s" % search_dirs sys.exit(1) sys.path = [ scons_dirs[0][1] ] + sys.path # invoke SCons import SCons.Script SCons.Script.main() # # do argument parsing # progname = sys.argv[0] import optparse usage = '''%prog [compile options] [SCons options] %prog assumes that the user has a directory called ~/m5/ where the source tree resides, and a directory called ~/build, where %prog will create ~/build/ if it does not exist and build the resulting simulators there. If ~/build is set up in such a way that it points to a local disk on each host, compiles will be very efficient. For example: ~/build -> /z//.build (Assuming that /z is a local disk and not NFS mounted, whereas your home directory is NFS mounted). ''' version = '%prog 0.1' parser = optparse.OptionParser(usage=usage, version=version, formatter=optparse.TitledHelpFormatter()) parser.disable_interspersed_args() # current option group group = None def set_group(*args, **kwargs): '''set the current option group''' global group if not args and not kwargs: group = None else: group = parser.add_option_group(*args, **kwargs) def add_option(*args, **kwargs): if group: return group.add_option(*args, **kwargs) else: return parser.add_option(*args, **kwargs) def bool_option(name, default, help): '''add a boolean option called --name and --no-name. Display help depending on which is the default''' tname = '--%s' % name fname = '--no-%s' % name dest = name.replace('-', '_') if default: thelp = optparse.SUPPRESS_HELP fhelp = help else: thelp = help fhelp = optparse.SUPPRESS_HELP add_option(tname, action="store_true", default=default, help=thelp) add_option(fname, action="store_false", dest=dest, help=fhelp) add_option('-n', '--no-compile', default=False, action='store_true', help="don't actually compile, just echo SCons command line") add_option('--everything', default=False, action='store_true', help="compile everything that can be compiled") add_option('-E', "--experimental", action='store_true', default=False, help="enable experimental builds") add_option('-v', "--verbose", default=False, action='store_true', help="be verbose") set_group("Output binary types") bool_option("debug", default=False, help="compile debug binaries") bool_option("opt", default=False, help="compile opt binaries") bool_option("fast", default=False, help="compile fast binaries") bool_option("prof", default=False, help="compile profile binaries") add_option('-a', "--all-bin", default=False, action='store_true', help="compile debug, opt, and fast binaries") set_group("ISA options") bool_option("mips", default=False, help="compile MIPS") bool_option("sparc", default=False, help="compile SPARC") add_option('-i', "--all-isa", default=False, action='store_true', help="compile all ISAs") set_group("Emulation options") bool_option("syscall", default=True, help="Do not compile System Call Emulation mode") bool_option("fullsys", default=True, help="Do not compile Full System mode") def usage(exitcode=None): parser.print_help() if exitcode is not None: sys.exit(exitcode) (options, args) = parser.parse_args() if options.everything: options.all_bin = True options.prof = True options.all_isa = True if options.all_bin: options.debug = True options.opt = True options.fast = True binaries = [] if options.debug: binaries.append('m5.debug') if options.opt: binaries.append('m5.opt') if options.fast: binaries.append('m5.fast') if options.prof: binaries.append('m5.prof') if not binaries: binaries.append('m5.debug') if options.all_isa: options.mips = True options.sparc = True isas = [] if options.mips: isas.append('mips') if options.sparc: isas.append('sparc') modes = [] if options.syscall: modes.append('syscall') if options.fullsys: modes.append('fullsys') if not modes: sys.exit("must specify at least one mode") # # Convert options into SCons command line arguments # # valid combinations of ISA and emulation mode valid = { ('mips', 'syscall') : 'MIPS_SE', ('sparc', 'syscall') : 'SPARC_SE' } # experimental combinations of ISA and emulation mode experiment = { ('mips', 'fullsys') : 'MIPS_FS', ('sparc', 'fullsys') : 'SPARC_FS' } if options.experimental: valid.update(experiment) builds = [] for isa in isas: for mode in modes: try: build = valid[(isa, mode)] builds.append(build) except KeyError: pass if not builds: sys.exit("must specify at least one valid combination of ISA and mode") if not args: usage(2) version = args[0] del args[0] for bin in binaries: for build in builds: args.append('%s/%s' % (build, bin)) # # set up compile # build_base = joinpath(homedir, 'build') m5_base = joinpath(homedir, 'm5') if not isdir(build_base): sys.exit('build directory %s not found' % build_base) if not isdir(m5_base): sys.exit('m5 base directory %s not found' % m5_base) m5_dir = joinpath(m5_base, version) if not isdir(m5_dir): sys.exit('source directory %s not found' % m5_dir) # support M5 1.x oldstyle = isfile(joinpath(m5_dir, 'SConscript')) if oldstyle: ext_dir = joinpath(m5_base, 'ext') test_dir = joinpath(m5_base, 'test.' + version) if not isdir(ext_dir): sys.exit('ext directory not found at %s' % ext_dir) if not isdir(test_dir): sys.exit('test directory not found at %s' % test_dir) build_dir = joinpath(build_base, version) if not isdir(build_dir): os.mkdir(build_dir) # need some symlinks for m5 1.x if oldstyle: os.symlink(m5_dir, joinpath(build_dir, 'm5')) os.symlink(ext_dir, joinpath(build_dir, 'ext')) os.symlink(test_dir, joinpath(build_dir, 'test')) os.symlink(joinpath(m5_dir, 'build', 'SConstruct'), joinpath(build_dir, 'SConstruct')) os.symlink(joinpath(m5_dir, 'build', 'default_options'), joinpath(build_dir, 'default_options')) sys.argv = [ progname ] if oldstyle: os.chdir(build_dir) sys.argv.extend(args) else: os.chdir(m5_dir) for arg in args: if not arg.startswith('-') and '=' not in arg: arg = joinpath(build_dir, 'build', arg) sys.argv.append(arg) if options.no_compile or options.verbose: for arg in sys.argv[1:]: print arg if not options.no_compile: do_compile()