raise
# Global Python includes
+import itertools
import os
import re
import subprocess
Exit(1)
if main['GCC']:
- # Check for a supported version of gcc, >= 4.4 is needed for c++0x
- # support. See http://gcc.gnu.org/projects/cxx0x.html for details
+ # Check for a supported version of gcc. >= 4.6 is chosen for its
+ # level of c++11 support. See
+ # http://gcc.gnu.org/projects/cxx0x.html for details. 4.6 is also
+ # the first version with proper LTO support.
gcc_version = readCommand([main['CXX'], '-dumpversion'], exception=False)
- if compareVersions(gcc_version, "4.4") < 0:
- print 'Error: gcc version 4.4 or newer required.'
+ if compareVersions(gcc_version, "4.6") < 0:
+ print 'Error: gcc version 4.6 or newer required.'
print ' Installed version:', gcc_version
Exit(1)
main['GCC_VERSION'] = gcc_version
- # Check for versions with bugs
- 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'])
-
- # LTO support is only really working properly from 4.6 and beyond
- if compareVersions(gcc_version, '4.6') >= 0:
- # Add the appropriate Link-Time Optimization (LTO) flags
- # unless LTO is explicitly turned off. Note that these flags
- # are only used by the fast target.
- if not GetOption('no_lto'):
- # Pass the LTO flag when compiling to produce GIMPLE
- # output, we merely create the flags here and only append
- # them later/
- main['LTO_CCFLAGS'] = ['-flto=%d' % GetOption('num_jobs')]
-
- # Use the same amount of jobs for LTO as we are running
- # scons with, we hardcode the use of the linker plugin
- # which requires either gold or GNU ld >= 2.21
- main['LTO_LDFLAGS'] = ['-flto=%d' % GetOption('num_jobs'),
- '-fuse-linker-plugin']
+ # Add the appropriate Link-Time Optimization (LTO) flags
+ # unless LTO is explicitly turned off. Note that these flags
+ # are only used by the fast target.
+ if not GetOption('no_lto'):
+ # Pass the LTO flag when compiling to produce GIMPLE
+ # output, we merely create the flags here and only append
+ # them later/
+ main['LTO_CCFLAGS'] = ['-flto=%d' % GetOption('num_jobs')]
+
+ # Use the same amount of jobs for LTO as we are running
+ # scons with, we hardcode the use of the linker plugin
+ # which requires either gold or GNU ld >= 2.21
+ main['LTO_LDFLAGS'] = ['-flto=%d' % GetOption('num_jobs'),
+ '-fuse-linker-plugin']
main.Append(TCMALLOC_CCFLAGS=['-fno-builtin-malloc', '-fno-builtin-calloc',
'-fno-builtin-realloc', '-fno-builtin-free'])
elif main['CLANG']:
- # Check for a supported version of clang, >= 2.9 is needed to
- # support similar features as gcc 4.4. See
+ # Check for a supported version of clang, >= 3.0 is needed to
+ # support similar features as gcc 4.6. See
# http://clang.llvm.org/cxx_status.html for details
clang_version_re = re.compile(".* version (\d+\.\d+)")
- clang_version_match = clang_version_re.match(CXX_version)
+ clang_version_match = clang_version_re.search(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.'
+ if compareVersions(clang_version, "3.0") < 0:
+ print 'Error: clang version 3.0 or newer required.'
print ' Installed version:', clang_version
Exit(1)
else:
print 'Error determining SWIG version.'
Exit(1)
-min_swig_version = '1.3.34'
+min_swig_version = '2.0.4'
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]
Exit(1)
-# Older versions of swig do not play well with more recent versions of
-# gcc due to assumptions on implicit includes (cstddef) and use of
-# namespaces
-if main['GCC'] and compareVersions(gcc_version, '4.6') > 0 and \
- compareVersions(swig_version[2], '2') < 0:
- print '\n' + termcap.Yellow + termcap.Bold + \
- 'Warning: SWIG 1.x cause issues with gcc 4.6 and later.\n' + \
- termcap.Normal + \
- 'Use SWIG 2.x to avoid assumptions on implicit includes\n' + \
- 'and use of namespaces\n'
-
# Set up SWIG flags & scanner
swig_flags=Split('-c++ -python -modern -templatereduce $_CPPINCFLAGS')
main.Append(SWIGFLAGS=swig_flags)
# we add them explicitly below. If you want to link in an alternate
# version of python, see above for instructions on how to invoke
# scons with the appropriate PATH set.
-py_includes = readCommand(['python-config', '--includes'],
+#
+# First we check if python2-config exists, else we use python-config
+python_config = readCommand(['which', 'python2-config'], exception='').strip()
+if not os.path.exists(python_config):
+ python_config = readCommand(['which', 'python-config'],
+ exception='').strip()
+py_includes = readCommand([python_config, '--includes'],
exception='').split()
# Strip the -I from the include folders before adding them to the
# CPPPATH
# Read the linker flags and split them into libraries and other link
# flags. The libraries are added later through the call the CheckLib.
-py_ld_flags = readCommand(['python-config', '--ldflags'], exception='').split()
+py_ld_flags = readCommand([python_config, '--ldflags'], exception='').split()
py_libs = []
for lib in py_ld_flags:
if not lib.startswith('-l'):
# Walk the tree and execute all SConsopts scripts that wil add to the
# above variables
-if not GetOption('verbose'):
+if GetOption('verbose'):
print "Reading SConsopts"
for bdir in [ base_dir ] + extras_dir_list:
if not isdir(bdir):
###################################################
main['ALL_ISA_LIST'] = all_isa_list
+all_isa_deps = {}
def make_switching_dir(dname, switch_headers, env):
# Generate the header. target[0] is the full path of the output
# header to generate. 'source' is a dummy variable, since we get the
# list of ISAs from env['ALL_ISA_LIST'].
def gen_switch_hdr(target, source, env):
fname = str(target[0])
- f = open(fname, 'w')
isa = env['TARGET_ISA'].lower()
- print >>f, '#include "%s/%s/%s"' % (dname, isa, basename(fname))
- f.close()
+ try:
+ f = open(fname, 'w')
+ print >>f, '#include "%s/%s/%s"' % (dname, isa, basename(fname))
+ f.close()
+ except IOError:
+ print "Failed to create %s" % fname
+ raise
# Build SCons Action object. 'varlist' specifies env vars that this
# action depends on; when env['ALL_ISA_LIST'] changes these actions
# Instantiate actions for each header
for hdr in switch_headers:
env.Command(hdr, [], switch_hdr_action)
+
+ isa_target = Dir('.').up().name.lower().replace('_', '-')
+ env['PHONY_BASE'] = '#'+isa_target
+ all_isa_deps[isa_target] = None
+
Export('make_switching_dir')
+# all-isas -> all-deps -> all-environs -> all_targets
+main.Alias('#all-isas', [])
+main.Alias('#all-deps', '#all-isas')
+
+# Dummy target to ensure all environments are created before telling
+# SCons what to actually make (the command line arguments). We attach
+# them to the dependence graph after the environments are complete.
+ORIG_BUILD_TARGETS = list(BUILD_TARGETS) # force a copy; gets closure to work.
+def environsComplete(target, source, env):
+ for t in ORIG_BUILD_TARGETS:
+ main.Depends('#all-targets', t)
+
+# Each build/* switching_dir attaches its *-environs target to #all-environs.
+main.Append(BUILDERS = {'CompleteEnvirons' :
+ Builder(action=MakeAction(environsComplete, None))})
+main.CompleteEnvirons('#all-environs', [])
+
+def doNothing(**ignored): pass
+main.Append(BUILDERS = {'Dummy': Builder(action=MakeAction(doNothing, None))})
+
+# The final target to which all the original targets ultimately get attached.
+main.Dummy('#all-targets', '#all-environs')
+BUILD_TARGETS[:] = ['#all-targets']
+
###################################################
#
# Define build environments for selected configurations.
###################################################
for variant_path in variant_paths:
- print "Building in", variant_path
+ if not GetOption('silent'):
+ print "Building in", variant_path
# Make a copy of the build-root environment to use for this config.
env = main.Clone()
current_vars_file = joinpath(build_root, 'variables', variant_dir)
if isfile(current_vars_file):
sticky_vars.files.append(current_vars_file)
- print "Using saved variables file %s" % current_vars_file
+ if not GetOption('silent'):
+ print "Using saved variables file %s" % current_vars_file
else:
# Build dir-specific variables file doesn't exist.
# The src/SConscript file sets up the build rules in 'env' according
# to the configured variables. It returns a list of environments,
# one for each variant build (debug, opt, etc.)
- envList = SConscript('src/SConscript', variant_dir = variant_path,
- exports = 'env')
-
- # Set up the regression tests for each build.
- for e in envList:
- SConscript('tests/SConscript',
- variant_dir = joinpath(variant_path, 'tests', e.Label),
- exports = { 'env' : e }, duplicate = False)
+ SConscript('src/SConscript', variant_dir = variant_path, exports = 'env')
+
+def pairwise(iterable):
+ "s -> (s0,s1), (s1,s2), (s2, s3), ..."
+ a, b = itertools.tee(iterable)
+ b.next()
+ return itertools.izip(a, b)
+
+# Create false dependencies so SCons will parse ISAs, establish
+# dependencies, and setup the build Environments serially. Either
+# SCons (likely) and/or our SConscripts (possibly) cannot cope with -j
+# greater than 1. It appears to be standard race condition stuff; it
+# doesn't always fail, but usually, and the behaviors are different.
+# Every time I tried to remove this, builds would fail in some
+# creative new way. So, don't do that. You'll want to, though, because
+# tests/SConscript takes a long time to make its Environments.
+for t1, t2 in pairwise(sorted(all_isa_deps.iterkeys())):
+ main.Depends('#%s-deps' % t2, '#%s-deps' % t1)
+ main.Depends('#%s-environs' % t2, '#%s-environs' % t1)
# base help text
Help('''