/util/compile
Python | 323 lines | 270 code | 18 blank | 35 comment | 12 complexity | 6c14f59e03ebf58c63089219ae2f9b25 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1
- #!/usr/bin/env python
- # 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.
- #
- # Authors: Nathan Binkert
- 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] <version> [SCons options]
- %prog assumes that the user has a directory called ~/m5/<version> where
- the source tree resides, and a directory called ~/build, where %prog
- will create ~/build/<version> 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/<username>/.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("alpha", default=False, help="compile Alpha")
- 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.alpha = True
- options.mips = True
- options.sparc = True
- isas = []
- if options.alpha:
- isas.append('alpha')
- if options.mips:
- isas.append('mips')
- if options.sparc:
- isas.append('sparc')
- if not isas:
- isas.append('alpha')
- 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 = { ('alpha', 'syscall') : 'ALPHA_SE',
- ('alpha', 'fullsys') : 'ALPHA_FS',
- ('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()