+from os import mkdir, environ
+from os.path import abspath, basename, dirname, expanduser, normpath
+from os.path import exists, isdir, isfile
+from os.path import join as joinpath, split as splitpath
+
+# SCons includes
+import SCons
+import SCons.Node
+
+extra_python_paths = [
+ Dir('src/python').srcnode().abspath, # gem5 includes
+ Dir('ext/ply').srcnode().abspath, # ply is used by several files
+ ]
+
+sys.path[1:1] = extra_python_paths
+
+from m5.util import compareVersions, readCommand
+from m5.util.terminal import get_termcap
+
+help_texts = {
+ "options" : "",
+ "global_vars" : "",
+ "local_vars" : ""
+}
+
+Export("help_texts")
+
+
+# There's a bug in scons in that (1) by default, the help texts from
+# AddOption() are supposed to be displayed when you type 'scons -h'
+# and (2) you can override the help displayed by 'scons -h' using the
+# Help() function, but these two features are incompatible: once
+# you've overridden the help text using Help(), there's no way to get
+# at the help texts from AddOptions. See:
+# http://scons.tigris.org/issues/show_bug.cgi?id=2356
+# http://scons.tigris.org/issues/show_bug.cgi?id=2611
+# This hack lets us extract the help text from AddOptions and
+# re-inject it via Help(). Ideally someday this bug will be fixed and
+# we can just use AddOption directly.
+def AddLocalOption(*args, **kwargs):
+ col_width = 30
+
+ help = " " + ", ".join(args)
+ if "help" in kwargs:
+ length = len(help)
+ if length >= col_width:
+ help += "\n" + " " * col_width
+ else:
+ help += " " * (col_width - length)
+ help += kwargs["help"]
+ help_texts["options"] += help + "\n"
+
+ AddOption(*args, **kwargs)
+
+AddLocalOption('--colors', dest='use_colors', action='store_true',
+ help="Add color to abbreviated scons output")
+AddLocalOption('--no-colors', dest='use_colors', action='store_false',
+ help="Don't add color to abbreviated scons output")
+AddLocalOption('--with-cxx-config', dest='with_cxx_config',
+ action='store_true',
+ help="Build with support for C++-based configuration")
+AddLocalOption('--default', dest='default', type='string', action='store',
+ help='Override which build_opts file to use for defaults')
+AddLocalOption('--ignore-style', dest='ignore_style', action='store_true',
+ help='Disable style checking hooks')
+AddLocalOption('--no-lto', dest='no_lto', action='store_true',
+ help='Disable Link-Time Optimization for fast')
+AddLocalOption('--update-ref', dest='update_ref', action='store_true',
+ help='Update test reference outputs')
+AddLocalOption('--verbose', dest='verbose', action='store_true',
+ help='Print full tool command lines')
+AddLocalOption('--without-python', dest='without_python',
+ action='store_true',
+ help='Build without Python configuration support')
+AddLocalOption('--without-tcmalloc', dest='without_tcmalloc',
+ action='store_true',
+ help='Disable linking against tcmalloc')
+AddLocalOption('--with-ubsan', dest='with_ubsan', action='store_true',
+ help='Build with Undefined Behavior Sanitizer if available')
+AddLocalOption('--with-asan', dest='with_asan', action='store_true',
+ help='Build with Address Sanitizer if available')
+
+termcap = get_termcap(GetOption('use_colors'))
+
+########################################################################
+#
+# Set up the main build environment.
+#
+########################################################################
+
+# export TERM so that clang reports errors in color
+use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH',
+ 'LIBRARY_PATH', 'PATH', 'PKG_CONFIG_PATH', 'PROTOC',
+ 'PYTHONPATH', 'RANLIB', 'SWIG', 'TERM' ])
+
+use_prefixes = [
+ "ASAN_", # address sanitizer symbolizer path and settings
+ "CCACHE_", # ccache (caching compiler wrapper) configuration
+ "CCC_", # clang static analyzer configuration
+ "DISTCC_", # distcc (distributed compiler wrapper) configuration
+ "INCLUDE_SERVER_", # distcc pump server settings
+ "M5", # M5 configuration (e.g., path to kernels)
+ ]
+
+use_env = {}
+for key,val in sorted(os.environ.iteritems()):
+ if key in use_vars or \
+ any([key.startswith(prefix) for prefix in use_prefixes]):
+ use_env[key] = val
+
+# Tell scons to avoid implicit command dependencies to avoid issues
+# with the param wrappes being compiled twice (see
+# http://scons.tigris.org/issues/show_bug.cgi?id=2811)
+main = Environment(ENV=use_env, IMPLICIT_COMMAND_DEPENDENCIES=0)
+main.Decider('MD5-timestamp')
+main.root = Dir(".") # The current directory (where this file lives).
+main.srcdir = Dir("src") # The source directory
+
+main_dict_keys = main.Dictionary().keys()
+
+# Check that we have a C/C++ compiler
+if not ('CC' in main_dict_keys and 'CXX' in main_dict_keys):
+ print "No C++ compiler installed (package g++ on Ubuntu and RedHat)"
+ Exit(1)
+
+# Check that swig is present
+if not 'SWIG' in main_dict_keys:
+ print "swig is not installed (package swig on Ubuntu and RedHat)"
+ Exit(1)
+
+# add useful python code PYTHONPATH so it can be used by subprocesses
+# as well
+main.AppendENVPath('PYTHONPATH', extra_python_paths)
+
+########################################################################
+#
+# Mercurial Stuff.
+#
+# If the gem5 directory is a mercurial repository, we should do some
+# extra things.
+#
+########################################################################
+
+hgdir = main.root.Dir(".hg")
+
+
+style_message = """
+You're missing the gem5 style hook, which automatically checks your code
+against the gem5 style rules on %s.
+This script will now install the hook in your %s.
+Press enter to continue, or ctrl-c to abort: """
+
+mercurial_style_message = style_message % ("hg commit and qrefresh commands",
+ ".hg/hgrc file")
+git_style_message = style_message % ("'git commit'",
+ ".git/hooks/ directory")
+
+mercurial_style_upgrade_message = """
+Your Mercurial style hooks are not up-to-date. This script will now
+try to automatically update them. A backup of your hgrc will be saved
+in .hg/hgrc.old.
+Press enter to continue, or ctrl-c to abort: """
+
+mercurial_style_hook = """
+# The following lines were automatically added by gem5/SConstruct
+# to provide the gem5 style-checking hooks
+[extensions]
+hgstyle = %s/util/hgstyle.py
+
+[hooks]
+pretxncommit.style = python:hgstyle.check_style
+pre-qrefresh.style = python:hgstyle.check_style
+# End of SConstruct additions
+
+""" % (main.root.abspath)
+
+mercurial_lib_not_found = """
+Mercurial libraries cannot be found, ignoring style hook. If
+you are a gem5 developer, please fix this and run the style
+hook. It is important.
+"""
+
+# Check for style hook and prompt for installation if it's not there.
+# Skip this if --ignore-style was specified, there's no interactive
+# terminal to prompt, or no recognized revision control system can be
+# found.
+ignore_style = GetOption('ignore_style') or not sys.stdin.isatty()
+
+# Try wire up Mercurial to the style hooks
+if not ignore_style and hgdir.exists():
+ style_hook = True
+ style_hooks = tuple()
+ hgrc = hgdir.File('hgrc')
+ hgrc_old = hgdir.File('hgrc.old')
+ try:
+ from mercurial import ui
+ ui = ui.ui()
+ ui.readconfig(hgrc.abspath)
+ style_hooks = (ui.config('hooks', 'pretxncommit.style', None),
+ ui.config('hooks', 'pre-qrefresh.style', None))
+ style_hook = all(style_hooks)
+ style_extension = ui.config('extensions', 'style', None)
+ except ImportError:
+ print mercurial_lib_not_found
+
+ if "python:style.check_style" in style_hooks:
+ # Try to upgrade the style hooks
+ print mercurial_style_upgrade_message
+ # continue unless user does ctrl-c/ctrl-d etc.
+ try:
+ raw_input()
+ except:
+ print "Input exception, exiting scons.\n"
+ sys.exit(1)
+ shutil.copyfile(hgrc.abspath, hgrc_old.abspath)
+ re_style_hook = re.compile(r"^([^=#]+)\.style\s*=\s*([^#\s]+).*")
+ re_style_extension = re.compile("style\s*=\s*([^#\s]+).*")
+ old, new = open(hgrc_old.abspath, 'r'), open(hgrc.abspath, 'w')
+ for l in old:
+ m_hook = re_style_hook.match(l)
+ m_ext = re_style_extension.match(l)
+ if m_hook:
+ hook, check = m_hook.groups()
+ if check != "python:style.check_style":
+ print "Warning: %s.style is using a non-default " \
+ "checker: %s" % (hook, check)
+ if hook not in ("pretxncommit", "pre-qrefresh"):
+ print "Warning: Updating unknown style hook: %s" % hook
+
+ l = "%s.style = python:hgstyle.check_style\n" % hook
+ elif m_ext and m_ext.group(1) == style_extension:
+ l = "hgstyle = %s/util/hgstyle.py\n" % main.root.abspath
+
+ new.write(l)
+ elif not style_hook:
+ print mercurial_style_message,
+ # continue unless user does ctrl-c/ctrl-d etc.
+ try:
+ raw_input()
+ except:
+ print "Input exception, exiting scons.\n"
+ sys.exit(1)
+ hgrc_path = '%s/.hg/hgrc' % main.root.abspath
+ print "Adding style hook to", hgrc_path, "\n"
+ try:
+ with open(hgrc_path, 'a') as f:
+ f.write(mercurial_style_hook)
+ except:
+ print "Error updating", hgrc_path
+ sys.exit(1)
+
+def install_git_style_hooks():
+ try:
+ gitdir = Dir(readCommand(
+ ["git", "rev-parse", "--git-dir"]).strip("\n"))
+ except Exception, e:
+ print "Warning: Failed to find git repo directory: %s" % e
+ return
+
+ git_hooks = gitdir.Dir("hooks")
+ git_pre_commit_hook = git_hooks.File("pre-commit")
+ git_style_script = File("util/git-pre-commit.py")
+
+ if git_pre_commit_hook.exists():
+ return