Nate's utility for compiling m5
authorNathan Binkert <binkertn@umich.edu>
Mon, 18 Dec 2006 02:58:50 +0000 (18:58 -0800)
committerNathan Binkert <binkertn@umich.edu>
Mon, 18 Dec 2006 02:58:50 +0000 (18:58 -0800)
--HG--
extra : convert_revision : 84b21f667736dfe07891323dcc810437ccb3c7c0

util/compile [new file with mode: 0755]

diff --git a/util/compile b/util/compile
new file mode 100755 (executable)
index 0000000..7f9b5d4
--- /dev/null
@@ -0,0 +1,323 @@
+#!/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()