ISA,CPU: Generalize and split out the components of the decode cache.
[gem5.git] / SConstruct
index 6ed3b5422147d918c6f6a3a687670c5d797ac64c..415af6ca7d54b49d8ea63ce014bd5dd3a43eceba 100755 (executable)
 #
 # SCons top-level build description (SConstruct) file.
 #
-# While in this directory ('m5'), just type 'scons' to build the default
+# While in this directory ('gem5'), just type 'scons' to build the default
 # configuration (see below), or type 'scons build/<CONFIG>/<binary>'
-# to build some other configuration (e.g., 'build/ALPHA_FS/m5.opt' for
+# to build some other configuration (e.g., 'build/ALPHA/gem5.opt' for
 # the optimized full-system version).
 #
-# You can build M5 in a different directory as long as there is a
+# You can build gem5 in a different directory as long as there is a
 # 'build/<CONFIG>' somewhere along the target path.  The build system
 # expects that all configs under the same build directory are being
 # built for the same host system.
 #
 #   The following two commands are equivalent.  The '-u' option tells
 #   scons to search up the directory tree for this SConstruct file.
-#   % cd <path-to-src>/m5 ; scons build/ALPHA_FS/m5.debug
-#   % cd <path-to-src>/m5/build/ALPHA_FS; scons -u m5.debug
+#   % cd <path-to-src>/gem5 ; scons build/ALPHA/gem5.debug
+#   % cd <path-to-src>/gem5/build/ALPHA; scons -u gem5.debug
 #
 #   The following two commands are equivalent and demonstrate building
 #   in a directory outside of the source tree.  The '-C' option tells
 #   scons to chdir to the specified directory to find this SConstruct
 #   file.
-#   % cd <path-to-src>/m5 ; scons /local/foo/build/ALPHA_FS/m5.debug
-#   % cd /local/foo/build/ALPHA_FS; scons -C <path-to-src>/m5 m5.debug
+#   % cd <path-to-src>/gem5 ; scons /local/foo/build/ALPHA/gem5.debug
+#   % cd /local/foo/build/ALPHA; scons -C <path-to-src>/gem5 gem5.debug
 #
 # You can use 'scons -H' to print scons options.  If you're in this
-# 'm5' directory (or use -u or -C to tell scons where to find this
-# file), you can use 'scons -h' to print all the M5-specific build
+# 'gem5' directory (or use -u or -C to tell scons where to find this
+# file), you can use 'scons -h' to print all the gem5-specific build
 # options as well.
 #
 ###################################################
@@ -77,7 +77,7 @@ try:
 except SystemExit, e:
     print """
 For more details, see:
-    http://m5sim.org/wiki/index.php/Compiling_M5
+    http://gem5.org/Dependencies
 """
     raise
 
@@ -93,7 +93,7 @@ either (1) rearranging your PATH so that scons finds the non-default
 on the scons script.
 
 For more details, see:
-    http://m5sim.org/wiki/index.php/Using_a_non-default_Python_installation
+    http://gem5.org/wiki/index.php/Using_a_non-default_Python_installation
 """
     raise
 
@@ -113,13 +113,14 @@ import SCons
 import SCons.Node
 
 extra_python_paths = [
-    Dir('src/python').srcnode().abspath, # M5 includes
+    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" : "",
@@ -129,7 +130,19 @@ help_texts = {
 
 Export("help_texts")
 
-def AddM5Option(*args, **kwargs):
+
+# 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)
@@ -144,27 +157,20 @@ def AddM5Option(*args, **kwargs):
 
     AddOption(*args, **kwargs)
 
-AddM5Option('--colors', dest='use_colors', action='store_true',
-            help="Add color to abbreviated scons output")
-AddM5Option('--no-colors', dest='use_colors', action='store_false',
-            help="Don't add color to abbreviated scons output")
-AddM5Option('--default', dest='default', type='string', action='store',
-            help='Override which build_opts file to use for defaults')
-AddM5Option('--ignore-style', dest='ignore_style', action='store_true',
-            help='Disable style checking hooks')
-AddM5Option('--update-ref', dest='update_ref', action='store_true',
-            help='Update test reference outputs')
-AddM5Option('--verbose', dest='verbose', action='store_true',
-            help='Print full tool command lines')
-
-use_colors = GetOption('use_colors')
-if use_colors:
-    from m5.util.terminal import termcap
-elif use_colors is None:
-    # option unspecified; default behavior is to use colors iff isatty
-    from m5.util.terminal import tty_termcap as termcap
-else:
-    from m5.util.terminal import no_termcap as termcap
+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('--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('--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')
+
+termcap = get_termcap(GetOption('use_colors'))
 
 ########################################################################
 #
@@ -172,7 +178,7 @@ else:
 #
 ########################################################################
 use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH', 'PATH',
-                 'PYTHONPATH', 'RANLIB' ])
+                 'PYTHONPATH', 'RANLIB', 'SWIG' ])
 
 use_env = {}
 for key,val in os.environ.iteritems():
@@ -180,6 +186,7 @@ for key,val in os.environ.iteritems():
         use_env[key] = val
 
 main = Environment(ENV=use_env)
+main.Decider('MD5-timestamp')
 main.root = Dir(".")         # The current directory (where this file lives).
 main.srcdir = Dir("src")     # The source directory
 
@@ -191,7 +198,7 @@ main.AppendENVPath('PYTHONPATH', extra_python_paths)
 #
 # Mercurial Stuff.
 #
-# If the M5 directory is a mercurial repository, we should do some
+# If the gem5 directory is a mercurial repository, we should do some
 # extra things.
 #
 ########################################################################
@@ -199,63 +206,62 @@ main.AppendENVPath('PYTHONPATH', extra_python_paths)
 hgdir = main.root.Dir(".hg")
 
 mercurial_style_message = """
-You're missing the M5 style hook.
-Please install the hook so we can ensure that all code fits a common style.
-
-All you'd need to do is add the following lines to your repository .hg/hgrc
-or your personal .hgrc
-----------------
-
+You're missing the gem5 style hook, which automatically checks your code
+against the gem5 style rules on hg commit and qrefresh commands.  This
+script will now install the hook in your .hg/hgrc file.
+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]
 style = %s/util/style.py
 
 [hooks]
 pretxncommit.style = python:style.check_style
 pre-qrefresh.style = python:style.check_style
-""" % (main.root)
+# End of SConstruct additions
 
-mercurial_bin_not_found = """
-Mercurial binary cannot be found, unfortunately this means that we
-cannot easily determine the version of M5 that you are running and
-this makes error messages more difficult to collect.  Please consider
-installing mercurial if you choose to post an error message
-"""
+""" % (main.root.abspath)
 
 mercurial_lib_not_found = """
-Mercurial libraries cannot be found, ignoring style hook
-If you are actually a M5 developer, please fix this and
-run the style hook. It is important.
+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.
 """
 
-hg_info = "Unknown"
-if hgdir.exists():
-    # 1) Grab repository revision if we know it.
-    cmd = "hg id -n -i -t -b"
+# Check for style hook and prompt for installation if it's not there.
+# Skip this if --ignore-style was specified, there's no .hg dir to
+# install a hook in, or there's no interactive terminal to prompt.
+if not GetOption('ignore_style') and hgdir.exists() and sys.stdin.isatty():
+    style_hook = True
     try:
-        hg_info = readCommand(cmd, cwd=main.root.abspath).strip()
-    except OSError:
-        print mercurial_bin_not_found
-
-    # 2) Ensure that the style hook is in place.
-    try:
-        ui = None
-        if GetOption('ignore_style'):
-            from mercurial import ui
-            ui = ui.ui()
+        from mercurial import ui
+        ui = ui.ui()
+        ui.readconfig(hgdir.File('hgrc').abspath)
+        style_hook = ui.config('hooks', 'pretxncommit.style', None) and \
+                     ui.config('hooks', 'pre-qrefresh.style', None)
     except ImportError:
         print mercurial_lib_not_found
 
-    if ui is not None:
-        ui.readconfig(hgdir.File('hgrc').abspath)
-        style_hook = ui.config('hooks', 'pretxncommit.style', None)
-
-        if not style_hook:
-            print mercurial_style_message
+    if 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:
+            hgrc = open(hgrc_path, 'a')
+            hgrc.write(mercurial_style_hook)
+            hgrc.close()
+        except:
+            print "Error updating", hgrc_path
             sys.exit(1)
-else:
-    print ".hg directory not found"
 
-main['HG_INFO'] = hg_info
 
 ###################################################
 #
@@ -265,7 +271,7 @@ main['HG_INFO'] = hg_info
 ###################################################
 
 # Find default configuration & binary.
-Default(environ.get('M5_DEFAULT_BINARY', 'build/ALPHA_SE/m5.debug'))
+Default(environ.get('M5_DEFAULT_BINARY', 'build/ALPHA/gem5.debug'))
 
 # helper function: find last occurrence of element in list
 def rfind(l, elt, offs = -1):
@@ -274,30 +280,29 @@ def rfind(l, elt, offs = -1):
             return i
     raise ValueError, "element not found"
 
+# Take a list of paths (or SCons Nodes) and return a list with all
+# paths made absolute and ~-expanded.  Paths will be interpreted
+# relative to the launch directory unless a different root is provided
+def makePathListAbsolute(path_list, root=GetLaunchDir()):
+    return [abspath(joinpath(root, expanduser(str(p))))
+            for p in path_list]
+
 # Each target must have 'build' in the interior of the path; the
 # directory below this will determine the build parameters.  For
 # example, for target 'foo/bar/build/ALPHA_SE/arch/alpha/blah.do' we
 # recognize that ALPHA_SE specifies the configuration because it
-# follow 'build' in the bulid path.
-
-# Generate absolute paths to targets so we can see where the build dir is
-if COMMAND_LINE_TARGETS:
-    # Ask SCons which directory it was invoked from
-    launch_dir = GetLaunchDir()
-    # Make targets relative to invocation directory
-    abs_targets = [ normpath(joinpath(launch_dir, str(x))) for x in \
-                    COMMAND_LINE_TARGETS]
-else:
-    # Default targets are relative to root of tree
-    abs_targets = [ normpath(joinpath(main.root.abspath, str(x))) for x in \
-                    DEFAULT_TARGETS]
+# follow 'build' in the build path.
 
+# The funky assignment to "[:]" is needed to replace the list contents
+# in place rather than reassign the symbol to a new list, which
+# doesn't work (obviously!).
+BUILD_TARGETS[:] = makePathListAbsolute(BUILD_TARGETS)
 
 # Generate a list of the unique build roots and configs that the
 # collected targets reference.
 variant_paths = []
 build_root = None
-for t in abs_targets:
+for t in BUILD_TARGETS:
     path_dirs = t.split('/')
     try:
         build_top = rfind(path_dirs, 'build', -2)
@@ -336,21 +341,6 @@ main.SetOption('duplicate', 'soft-copy')
 # tree (not specific to a particular build like ALPHA_SE)
 #
 
-# Variable validators & converters for global sticky variables
-def PathListMakeAbsolute(val):
-    if not val:
-        return val
-    f = lambda p: abspath(expanduser(p))
-    return ':'.join(map(f, val.split(':')))
-
-def PathListAllExist(key, val, env):
-    if not val:
-        return
-    paths = val.split(':')
-    for path in paths:
-        if not isdir(path):
-            raise SCons.Errors.UserError("Path does not exist: '%s'" % path)
-
 global_vars_file = joinpath(build_root, 'variables.global')
 
 global_vars = Variables(global_vars_file, args=ARGUMENTS)
@@ -358,11 +348,11 @@ global_vars = Variables(global_vars_file, args=ARGUMENTS)
 global_vars.AddVariables(
     ('CC', 'C compiler', environ.get('CC', main['CC'])),
     ('CXX', 'C++ compiler', environ.get('CXX', main['CXX'])),
+    ('SWIG', 'SWIG tool', environ.get('SWIG', main['SWIG'])),
     ('BATCH', 'Use batch pool for build and tests', False),
     ('BATCH_CMD', 'Batch pool submission command name', 'qdo'),
     ('M5_BUILD_CACHE', 'Cache built objects in this directory', False),
-    ('EXTRAS', 'Add Extra directories to the compilation', '',
-     PathListAllExist, PathListMakeAbsolute),
+    ('EXTRAS', 'Add extra directories to the compilation', '')
     )
 
 # Update main environment with values from ARGUMENTS & global_vars_file
@@ -373,10 +363,10 @@ help_texts["global_vars"] += global_vars.GenerateHelpText(main)
 global_vars.Save(global_vars_file, main)
 
 # Parse EXTRAS variable to build list of all directories where we're
-# look for sources etc.  This list is exported as base_dir_list.
+# look for sources etc.  This list is exported as extras_dir_list.
 base_dir = main.srcdir.abspath
 if main['EXTRAS']:
-    extras_dir_list = main['EXTRAS'].split(':')
+    extras_dir_list = makePathListAbsolute(main['EXTRAS'].split(':'))
 else:
     extras_dir_list = []
 
@@ -467,6 +457,8 @@ class Transform(object):
 
 Export('Transform')
 
+# enable the regression script to use the termcap
+main['TERMCAP'] = termcap
 
 if GetOption('verbose'):
     def MakeAction(action, string, *args, **kwargs):
@@ -491,7 +483,8 @@ CXX_V = readCommand([main['CXX'],'-V'], exception=False)
 main['GCC'] = CXX_version and CXX_version.find('g++') >= 0
 main['SUNCC'] = CXX_V and CXX_V.find('Sun C++') >= 0
 main['ICC'] = CXX_V and CXX_V.find('Intel') >= 0
-if main['GCC'] + main['SUNCC'] + main['ICC'] > 1:
+main['CLANG'] = CXX_version and CXX_version.find('clang') >= 0
+if main['GCC'] + main['SUNCC'] + main['ICC'] + main['CLANG'] > 1:
     print 'Error: How can we have two at the same time?'
     Exit(1)
 
@@ -500,15 +493,17 @@ if main['GCC']:
     main.Append(CCFLAGS=['-pipe'])
     main.Append(CCFLAGS=['-fno-strict-aliasing'])
     main.Append(CCFLAGS=['-Wall', '-Wno-sign-compare', '-Wundef'])
-    main.Append(CXXFLAGS=['-Wno-deprecated'])
     # Read the GCC version to check for versions with bugs
     # Note CCVERSION doesn't work here because it is run with the CC
     # before we override it from the command line
     gcc_version = readCommand([main['CXX'], '-dumpversion'], exception=False)
+    main['GCC_VERSION'] = gcc_version
     if not compareVersions(gcc_version, '4.4.1') or \
        not compareVersions(gcc_version, '4.4.2'):
         print 'Info: Tree vectorizer in GCC 4.4.1 & 4.4.2 is buggy, disabling.'
         main.Append(CCFLAGS=['-fno-tree-vectorize'])
+    if compareVersions(gcc_version, '4.6') >= 0:
+        main.Append(CXXFLAGS=['-std=c++0x'])
 elif main['ICC']:
     pass #Fix me... add warning flags once we clean up icc warnings
 elif main['SUNCC']:
@@ -518,6 +513,30 @@ elif main['SUNCC']:
     main.Append(CCFLAGS=['-library=stlport4'])
     main.Append(CCFLAGS=['-xar'])
     #main.Append(CCFLAGS=['-instances=semiexplicit'])
+elif main['CLANG']:
+    clang_version_re = re.compile(".* version (\d+\.\d+)")
+    clang_version_match = clang_version_re.match(CXX_version)
+    if (clang_version_match):
+        clang_version = clang_version_match.groups()[0]
+        if compareVersions(clang_version, "2.9") < 0:
+            print 'Error: clang version 2.9 or newer required.'
+            print '       Installed version:', clang_version
+            Exit(1)
+    else:
+        print 'Error: Unable to determine clang version.'
+        Exit(1)
+
+    main.Append(CCFLAGS=['-pipe'])
+    main.Append(CCFLAGS=['-fno-strict-aliasing'])
+    main.Append(CCFLAGS=['-Wall', '-Wno-sign-compare', '-Wundef'])
+    main.Append(CCFLAGS=['-Wno-tautological-compare'])
+    main.Append(CCFLAGS=['-Wno-self-assign'])
+    # Ruby makes frequent use of extraneous parantheses in the printing
+    # of if-statements
+    main.Append(CCFLAGS=['-Wno-parentheses'])
+
+    if compareVersions(clang_version, "3") >= 0:
+        main.Append(CXXFLAGS=['-std=c++0x'])
 else:
     print 'Error: Don\'t know what compiler options to use for your compiler.'
     print '       Please fix SConstruct and src/SConscript and try again.'
@@ -554,7 +573,7 @@ if len(swig_version) < 3 or \
     print 'Error determining SWIG version.'
     Exit(1)
 
-min_swig_version = '1.3.28'
+min_swig_version = '1.3.34'
 if compareVersions(swig_version[2], min_swig_version) < 0:
     print 'Error: SWIG version', min_swig_version, 'or newer required.'
     print '       Installed version:', swig_version[2]
@@ -680,10 +699,14 @@ if not py_getvar('Py_ENABLE_SHARED'):
 
 py_libs = []
 for lib in py_getvar('LIBS').split() + py_getvar('SYSLIBS').split():
-    assert lib.startswith('-l')
-    lib = lib[2:]   
-    if lib not in py_libs:
-        py_libs.append(lib)
+    if not lib.startswith('-l'):
+        # Python requires some special flags to link (e.g. -framework
+        # common on OS X systems), assume appending preserves order
+        main.Append(LINKFLAGS=[lib])
+    else:
+        lib = lib[2:]
+        if lib not in py_libs:
+            py_libs.append(lib)
 py_libs.append(py_version)
 
 main.Append(CPPPATH=py_includes)
@@ -735,32 +758,6 @@ if not have_fenv:
     print "Warning: Header file <fenv.h> not found."
     print "         This host has no IEEE FP rounding mode control."
 
-######################################################################
-#
-# Check for mysql.
-#
-mysql_config = WhereIs('mysql_config')
-have_mysql = bool(mysql_config)
-
-# Check MySQL version.
-if have_mysql:
-    mysql_version = readCommand(mysql_config + ' --version')
-    min_mysql_version = '4.1'
-    if compareVersions(mysql_version, min_mysql_version) < 0:
-        print 'Warning: MySQL', min_mysql_version, 'or newer required.'
-        print '         Version', mysql_version, 'detected.'
-        have_mysql = False
-
-# Set up mysql_config commands.
-if have_mysql:
-    mysql_config_include = mysql_config + ' --include'
-    if os.system(mysql_config_include + ' > /dev/null') != 0:
-        # older mysql_config versions don't support --include, use
-        # --cflags instead
-        mysql_config_include = mysql_config + ' --cflags | sed s/\\\'//g'
-    # This seems to work in all versions
-    mysql_config_libs = mysql_config + ' --libs'
-
 ######################################################################
 #
 # Finish the configuration
@@ -817,23 +814,28 @@ Export('export_vars')
 
 # Walk the tree and execute all SConsopts scripts that wil add to the
 # above variables
+if not GetOption('verbose'):
+    print "Reading SConsopts"
 for bdir in [ base_dir ] + extras_dir_list:
+    if not isdir(bdir):
+        print "Error: directory '%s' does not exist" % bdir
+        Exit(1)
     for root, dirs, files in os.walk(bdir):
         if 'SConsopts' in files:
-            print "Reading", joinpath(root, 'SConsopts')
+            if GetOption('verbose'):
+                print "Reading", joinpath(root, 'SConsopts')
             SConscript(joinpath(root, 'SConsopts'))
 
 all_isa_list.sort()
 
 sticky_vars.AddVariables(
     EnumVariable('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list),
-    BoolVariable('FULL_SYSTEM', 'Full-system support', False),
     ListVariable('CPU_MODELS', 'CPU models',
                  sorted(n for n,m in CpuModel.dict.iteritems() if m.default),
                  sorted(CpuModel.list)),
     BoolVariable('NO_FAST_ALLOC', 'Disable fast object allocator', False),
-    BoolVariable('FAST_ALLOC_DEBUG', 'Enable fast object allocator debugging',
-                 False),
+    BoolVariable('FORCE_FAST_ALLOC',
+                 'Enable fast object allocator, even for gem5.debug', False),
     BoolVariable('FAST_ALLOC_STATS', 'Enable fast object allocator statistics',
                  False),
     BoolVariable('EFENCE', 'Link with Electric Fence malloc debugger',
@@ -844,19 +846,15 @@ sticky_vars.AddVariables(
     BoolVariable('USE_SSE2',
                  'Compile for SSE2 (-msse2) to get IEEE FP on x86 hosts',
                  False),
-    BoolVariable('USE_MYSQL', 'Use MySQL for stats output', have_mysql),
     BoolVariable('USE_POSIX_CLOCK', 'Use POSIX Clocks', have_posix_clock),
     BoolVariable('USE_FENV', 'Use <fenv.h> IEEE mode control', have_fenv),
-    BoolVariable('USE_CHECKER', 'Use checker for detailed CPU models', False),
     BoolVariable('CP_ANNOTATE', 'Enable critical path annotation capability', False),
-    BoolVariable('RUBY', 'Build with Ruby', False),
     )
 
 # These variables get exported to #defines in config/*.hh (see src/SConscript).
-export_vars += ['FULL_SYSTEM', 'USE_FENV', 'USE_MYSQL',
-                'NO_FAST_ALLOC', 'FAST_ALLOC_DEBUG', 'FAST_ALLOC_STATS',
-                'SS_COMPATIBLE_FP', 'USE_CHECKER', 'TARGET_ISA', 'CP_ANNOTATE',
-                'USE_POSIX_CLOCK' ]
+export_vars += ['USE_FENV', 'NO_FAST_ALLOC', 'FORCE_FAST_ALLOC',
+                'FAST_ALLOC_STATS', 'SS_COMPATIBLE_FP',
+                'TARGET_ISA', 'CP_ANNOTATE', 'USE_POSIX_CLOCK' ]
 
 ###################################################
 #
@@ -875,13 +873,8 @@ def build_config_file(target, source, env):
     f.close()
     return None
 
-# Generate the message to be printed when building the config file.
-def build_config_file_string(target, source, env):
-    (variable, value) = [s.get_contents() for s in source]
-    return "Defining %s as %s in %s." % (variable, value, target[0])
-
 # Combine the two functions into a scons Action object.
-config_action = Action(build_config_file, build_config_file_string)
+config_action = MakeAction(build_config_file, Transform("CONFIG H", 2))
 
 # The emitter munges the source & target node lists to reflect what
 # we're really doing.
@@ -977,18 +970,24 @@ for variant_path in variant_paths:
 
         # Get default build variables from source tree.  Variables are
         # normally determined by name of $VARIANT_DIR, but can be
-        # overriden by 'default=' arg on command line.
+        # overridden by '--default=' arg on command line.
         default = GetOption('default')
-        if not default:
-            default = variant_dir
-        default_vars_file = joinpath('build_opts', default)
-        if isfile(default_vars_file):
+        opts_dir = joinpath(main.root.abspath, 'build_opts')
+        if default:
+            default_vars_files = [joinpath(build_root, 'variables', default),
+                                  joinpath(opts_dir, default)]
+        else:
+            default_vars_files = [joinpath(opts_dir, variant_dir)]
+        existing_files = filter(isfile, default_vars_files)
+        if existing_files:
+            default_vars_file = existing_files[0]
             sticky_vars.files.append(default_vars_file)
             print "Variables file %s not found,\n  using defaults in %s" \
                   % (current_vars_file, default_vars_file)
         else:
-            print "Error: cannot find variables file %s or %s" \
-                  % (current_vars_file, default_vars_file)
+            print "Error: cannot find variables file %s or " \
+                  "default file(s) %s" \
+                  % (current_vars_file, ' or '.join(default_vars_files))
             Exit(1)
 
     # Apply current variable settings to env
@@ -1012,16 +1011,6 @@ for variant_path in variant_paths:
     if env['EFENCE']:
         env.Append(LIBS=['efence'])
 
-    if env['USE_MYSQL']:
-        if not have_mysql:
-            print "Warning: MySQL not available; " \
-                  "forcing USE_MYSQL to False in", variant_dir + "."
-            env['USE_MYSQL'] = False
-        else:
-            print "Compiling in", variant_dir, "with MySQL support."
-            env.ParseConfig(mysql_config_libs)
-            env.ParseConfig(mysql_config_include)
-
     # Save sticky variable settings back to current variables file
     sticky_vars.Save(current_vars_file, env)