X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=SConstruct;h=ec60964e48ce4f53993b69360dac9d3b3ddb7549;hb=6b73ff43ff58502c80050c7aeff5a08a4ce61f87;hp=50ca2d6e4af0c0e1ce9cb8c305c1a66aa1b3751e;hpb=d3e888ff90c91ce7f3b5b7ab0e3a314a28f3cb88;p=gem5.git diff --git a/SConstruct b/SConstruct index 50ca2d6e4..ec60964e4 100644 --- a/SConstruct +++ b/SConstruct @@ -63,9 +63,11 @@ # ################################################### -# Python library imports import sys import os +import subprocess + +from os.path import isdir, join as joinpath # Check for recent-enough Python and SCons versions. If your system's # default installation of Python is not recent enough, you can use a @@ -89,11 +91,39 @@ except: # The absolute path to the current directory (where this file lives). ROOT = Dir('.').abspath -# Paths to the M5 and external source trees. -SRCDIR = os.path.join(ROOT, 'src') +# Path to the M5 source tree. +SRCDIR = joinpath(ROOT, 'src') # tell python where to find m5 python code -sys.path.append(os.path.join(ROOT, 'src/python')) +sys.path.append(joinpath(ROOT, 'src/python')) + +def check_style_hook(ui): + ui.readconfig(joinpath(ROOT, '.hg', 'hgrc')) + style_hook = ui.config('hooks', 'pretxncommit.style', None) + + if not style_hook: + print """\ +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 +---------------- + +[extensions] +style = %s/util/style.py + +[hooks] +pretxncommit.style = python:style.check_whitespace +""" % (ROOT) + sys.exit(1) + +if isdir(joinpath(ROOT, '.hg')): + try: + from mercurial import ui + check_style_hook(ui.ui()) + except ImportError: + pass ################################################### # @@ -105,13 +135,6 @@ sys.path.append(os.path.join(ROOT, 'src/python')) # Find default configuration & binary. Default(os.environ.get('M5_DEFAULT_BINARY', 'build/ALPHA_SE/m5.debug')) -# Ask SCons which directory it was invoked from. -launch_dir = GetLaunchDir() - -# Make targets relative to invocation directory -abs_targets = map(lambda x: os.path.normpath(os.path.join(launch_dir, str(x))), - BUILD_TARGETS) - # helper function: find last occurrence of element in list def rfind(l, elt, offs = -1): for i in range(len(l)+offs, 0, -1): @@ -141,6 +164,19 @@ def compare_versions(v1, v2): # 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 = map(lambda x: os.path.normpath(joinpath(launch_dir, str(x))), + COMMAND_LINE_TARGETS) +else: + # Default targets are relative to root of tree + abs_targets = map(lambda x: os.path.normpath(joinpath(ROOT, str(x))), + DEFAULT_TARGETS) + + # Generate a list of the unique build roots and configs that the # collected targets reference. build_paths = [] @@ -152,7 +188,7 @@ for t in abs_targets: except: print "Error: no non-leaf 'build' dir found on target path", t Exit(1) - this_build_root = os.path.join('/',*path_dirs[:build_top+1]) + this_build_root = joinpath('/',*path_dirs[:build_top+1]) if not build_root: build_root = this_build_root else: @@ -160,7 +196,7 @@ for t in abs_targets: print "Error: build targets not under same build root\n"\ " %s\n %s" % (build_root, this_build_root) Exit(1) - build_path = os.path.join('/',*path_dirs[:build_top+2]) + build_path = joinpath('/',*path_dirs[:build_top+2]) if build_path not in build_paths: build_paths.append(build_path) @@ -183,7 +219,9 @@ if ARGUMENTS.get('CC', None): if ARGUMENTS.get('CXX', None): env['CXX'] = ARGUMENTS.get('CXX') -env.SConsignFile(os.path.join(build_root,"sconsign")) +Export('env') + +env.SConsignFile(joinpath(build_root,"sconsign")) # Default duplicate option is to use hard links, but this messes up # when you use emacs to edit a file in the target dir, as emacs moves @@ -199,11 +237,42 @@ if False: # M5_PLY is used by isa_parser.py to find the PLY package. env.Append(ENV = { 'M5_PLY' : Dir('ext/ply') }) +env['GCC'] = False +env['SUNCC'] = False +env['ICC'] = False +env['GCC'] = subprocess.Popen(env['CXX'] + ' --version', shell=True, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + close_fds=True).communicate()[0].find('GCC') >= 0 +env['SUNCC'] = subprocess.Popen(env['CXX'] + ' -V', shell=True, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + close_fds=True).communicate()[0].find('Sun C++') >= 0 +env['ICC'] = subprocess.Popen(env['CXX'] + ' -V', shell=True, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + close_fds=True).communicate()[0].find('Intel') >= 0 +if env['GCC'] + env['SUNCC'] + env['ICC'] > 1: + print 'Error: How can we have two at the same time?' + Exit(1) + # Set up default C++ compiler flags -env.Append(CCFLAGS='-pipe') -env.Append(CCFLAGS='-fno-strict-aliasing') -env.Append(CCFLAGS=Split('-Wall -Wno-sign-compare -Werror -Wundef')) +if env['GCC']: + env.Append(CCFLAGS='-pipe') + env.Append(CCFLAGS='-fno-strict-aliasing') + env.Append(CCFLAGS=Split('-Wall -Wno-sign-compare -Werror -Wundef')) +elif env['ICC']: + pass #Fix me... add warning flags once we clean up icc warnings +elif env['SUNCC']: + env.Append(CCFLAGS='-Qoption ccfe') + env.Append(CCFLAGS='-features=gcc') + env.Append(CCFLAGS='-features=extensions') + env.Append(CCFLAGS='-library=stlport4') + env.Append(CCFLAGS='-xar') +# env.Append(CCFLAGS='-instances=semiexplicit') +else: + print 'Error: Don\'t know what compiler options to use for your compiler.' + print ' Please fix SConstruct and src/SConscript and try again.' + Exit(1) + if sys.platform == 'cygwin': # cygwin has some header file issues... env.Append(CCFLAGS=Split("-Wno-uninitialized")) @@ -218,7 +287,8 @@ if not env.has_key('SWIG'): # Check for appropriate SWIG version swig_version = os.popen('swig -version').read().split() # First 3 words should be "SWIG Version x.y.z" -if swig_version[0] != 'SWIG' or swig_version[1] != 'Version': +if len(swig_version) < 3 or \ + swig_version[0] != 'SWIG' or swig_version[1] != 'Version': print 'Error determining SWIG version.' Exit(1) @@ -229,22 +299,35 @@ if compare_versions(swig_version[2], min_swig_version) < 0: Exit(1) # Set up SWIG flags & scanner -env.Append(SWIGFLAGS=Split('-c++ -python -modern $_CPPINCFLAGS')) +swig_flags=Split('-c++ -python -modern -templatereduce $_CPPINCFLAGS') +env.Append(SWIGFLAGS=swig_flags) + +# filter out all existing swig scanners, they mess up the dependency +# stuff for some reason +scanners = [] +for scanner in env['SCANNERS']: + skeys = scanner.skeys + if skeys == '.i': + continue + + if isinstance(skeys, (list, tuple)) and '.i' in skeys: + continue -import SCons.Scanner + scanners.append(scanner) +# add the new swig scanner that we like better +from SCons.Scanner import ClassicCPP as CPPScanner swig_inc_re = '^[ \t]*[%,#][ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")' +scanners.append(CPPScanner("SwigScan", [ ".i" ], "CPPPATH", swig_inc_re)) -swig_scanner = SCons.Scanner.ClassicCPP("SwigScan", ".i", "CPPPATH", - swig_inc_re) - -env.Append(SCANNERS = swig_scanner) +# replace the scanners list that has what we want +env['SCANNERS'] = scanners # Platform-specific configuration. Note again that we assume that all # builds under a given build root run on the same host platform. conf = Configure(env, - conf_dir = os.path.join(build_root, '.scons_config'), - log_file = os.path.join(build_root, 'scons_config.log')) + conf_dir = joinpath(build_root, '.scons_config'), + log_file = joinpath(build_root, 'scons_config.log')) # Find Python include and library directories for embedding the # interpreter. For consistency, we will use the same Python @@ -257,7 +340,7 @@ conf = Configure(env, py_version_name = 'python' + sys.version[:3] # include path, e.g. /usr/local/include/python2.4 -py_header_path = os.path.join(sys.exec_prefix, 'include', py_version_name) +py_header_path = joinpath(sys.exec_prefix, 'include', py_version_name) env.Append(CPPPATH = py_header_path) # verify that it works if not conf.CheckHeader('Python.h', '<>'): @@ -267,7 +350,7 @@ if not conf.CheckHeader('Python.h', '<>'): # add library path too if it's not in the default place py_lib_path = None if sys.exec_prefix != '/usr': - py_lib_path = os.path.join(sys.exec_prefix, 'lib') + py_lib_path = joinpath(sys.exec_prefix, 'lib') elif sys.platform == 'cygwin': # cygwin puts the .dll in /bin for some reason py_lib_path = '/bin' @@ -286,7 +369,7 @@ if not conf.CheckLibWithHeader(None, 'sys/socket.h', 'C++', 'accept(0,0,0);'): # Check for zlib. If the check passes, libz will be automatically # added to the LIBS environment variable. -if not conf.CheckLibWithHeader('z', 'zlib.h', 'C++'): +if not conf.CheckLibWithHeader('z', 'zlib.h', 'C++','zlibVersion();'): print 'Error: did not find needed zlib compression library '\ 'and/or zlib.h header file.' print ' Please install zlib and try again.' @@ -324,30 +407,42 @@ if have_mysql: env = conf.Finish() # Define the universe of supported ISAs -env['ALL_ISA_LIST'] = ['alpha', 'sparc', 'mips'] +all_isa_list = [ ] +Export('all_isa_list') # Define the universe of supported CPU models -env['ALL_CPU_LIST'] = ['AtomicSimpleCPU', 'TimingSimpleCPU', - 'O3CPU', 'OzoneCPU'] - -if os.path.isdir(os.path.join(SRCDIR, 'src/encumbered/cpu/full')): - env['ALL_CPU_LIST'] += ['FullCPU'] +all_cpu_list = [ ] +default_cpus = [ ] +Export('all_cpu_list', 'default_cpus') # Sticky options get saved in the options file so they persist from # one invocation to the next (unless overridden, in which case the new # value becomes sticky). sticky_opts = Options(args=ARGUMENTS) +Export('sticky_opts') + +# Non-sticky options only apply to the current build. +nonsticky_opts = Options(args=ARGUMENTS) +Export('nonsticky_opts') + +# Walk the tree and execute all SConsopts scripts that wil add to the +# above options +for root, dirs, files in os.walk('.'): + if 'SConsopts' in files: + SConscript(os.path.join(root, 'SConsopts')) + +all_isa_list.sort() +all_cpu_list.sort() +default_cpus.sort() + sticky_opts.AddOptions( - EnumOption('TARGET_ISA', 'Target ISA', 'alpha', env['ALL_ISA_LIST']), + EnumOption('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list), BoolOption('FULL_SYSTEM', 'Full-system support', False), # There's a bug in scons 0.96.1 that causes ListOptions with list # values (more than one value) not to be able to be restored from # a saved option file. If this causes trouble then upgrade to # scons 0.96.90 or later. - ListOption('CPU_MODELS', 'CPU models', 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU', - env['ALL_CPU_LIST']), - BoolOption('ALPHA_TLASER', - 'Model Alpha TurboLaser platform (vs. Tsunami)', False), + ListOption('CPU_MODELS', 'CPU models', default_cpus, all_cpu_list), BoolOption('NO_FAST_ALLOC', 'Disable fast object allocator', False), BoolOption('EFENCE', 'Link with Electric Fence malloc debugger', False), @@ -369,8 +464,6 @@ sticky_opts.AddOptions( '%s:%s' % (sys.prefix, sys.exec_prefix)) ) -# Non-sticky options only apply to the current build. -nonsticky_opts = Options(args=ARGUMENTS) nonsticky_opts.AddOptions( BoolOption('update_ref', 'Update test reference outputs', False) ) @@ -417,7 +510,7 @@ def config_emitter(target, source, env): # extract option name from Builder arg option = str(target[0]) # True target is config header file - target = os.path.join('config', option.lower() + '.hh') + target = joinpath('config', option.lower() + '.hh') val = env[option] if isinstance(val, bool): # Force value to 0/1 @@ -466,7 +559,7 @@ Usage: scons [scons options] [build options] [target(s)] # libelf build is shared across all configs in the build root. env.SConscript('ext/libelf/SConscript', - build_dir = os.path.join(build_root, 'libelf'), + build_dir = joinpath(build_root, 'libelf'), exports = 'env') ################################################### @@ -475,6 +568,7 @@ env.SConscript('ext/libelf/SConscript', # ################################################### +env['ALL_ISA_LIST'] = all_isa_list def make_switching_dir(dirname, 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 @@ -485,7 +579,7 @@ def make_switching_dir(dirname, switch_headers, env): f = open(fname, 'w') f.write('#include "arch/isa_specific.hh"\n') cond = '#if' - for isa in env['ALL_ISA_LIST']: + for isa in all_isa_list: f.write('%s THE_ISA == %s_ISA\n#include "%s/%s/%s"\n' % (cond, isa.upper(), dirname, isa, basename)) cond = '#elif' @@ -506,8 +600,7 @@ def make_switching_dir(dirname, switch_headers, env): # Instantiate actions for each header for hdr in switch_headers: env.Command(hdr, [], switch_hdr_action) - -env.make_switching_dir = make_switching_dir +Export('make_switching_dir') ################################################### # @@ -531,7 +624,7 @@ for build_path in build_paths: # Options for $BUILD_ROOT/$BUILD_DIR are stored in # $BUILD_ROOT/options/$BUILD_DIR so you can nuke # $BUILD_ROOT/$BUILD_DIR without losing your options settings. - current_opts_file = os.path.join(build_root, 'options', build_dir) + current_opts_file = joinpath(build_root, 'options', build_dir) if os.path.isfile(current_opts_file): sticky_opts.files.append(current_opts_file) print "Using saved options file %s" % current_opts_file @@ -546,8 +639,8 @@ for build_path in build_paths: # Get default build options from source tree. Options are # normally determined by name of $BUILD_DIR, but can be # overriden by 'default=' arg on command line. - default_opts_file = os.path.join('build_opts', - ARGUMENTS.get('default', build_dir)) + default_opts_file = joinpath('build_opts', + ARGUMENTS.get('default', build_dir)) if os.path.isfile(default_opts_file): sticky_opts.files.append(default_opts_file) print "Options file %s not found,\n using defaults in %s" \ @@ -611,7 +704,7 @@ for build_path in build_paths: # Set up the regression tests for each build. for e in envList: SConscript('tests/SConscript', - build_dir = os.path.join(build_path, 'tests', e.Label), + build_dir = joinpath(build_path, 'tests', e.Label), exports = { 'env' : e }, duplicate = False) Help(help_text)