X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=SConstruct;h=0a3d6de027faf9239b4a77b2bd483e769d1d1977;hb=ea7bdf9f60c404761dfc568d5291c75747a2dd88;hp=6f20d97563526df667f83b2001a9d82209f97046;hpb=bc3d009abaa0000469d5e556bd264009f7c50464;p=gem5.git diff --git a/SConstruct b/SConstruct index 6f20d9756..0a3d6de02 100644 --- a/SConstruct +++ b/SConstruct @@ -66,6 +66,8 @@ # Python library imports import sys import os +import subprocess +from os.path import 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,11 @@ 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')) ################################################### # @@ -105,13 +107,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): @@ -119,12 +114,41 @@ def rfind(l, elt, offs = -1): return i raise ValueError, "element not found" +# helper function: compare dotted version numbers. +# E.g., compare_version('1.3.25', '1.4.1') +# returns -1, 0, 1 if v1 is <, ==, > v2 +def compare_versions(v1, v2): + # Convert dotted strings to lists + v1 = map(int, v1.split('.')) + v2 = map(int, v2.split('.')) + # Compare corresponding elements of lists + for n1,n2 in zip(v1, v2): + if n1 < n2: return -1 + if n1 > n2: return 1 + # all corresponding values are equal... see if one has extra values + if len(v1) < len(v2): return -1 + if len(v1) > len(v2): return 1 + return 0 + # 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 = 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 = [] @@ -136,7 +160,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: @@ -144,7 +168,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) @@ -159,7 +183,15 @@ env = Environment(ENV = os.environ, # inherit user's environment vars ROOT = ROOT, SRCDIR = SRCDIR) -env.SConsignFile("sconsign") +#Parse CC/CXX early so that we use the correct compiler for +# to test for dependencies/versions/libraries/includes +if ARGUMENTS.get('CC', None): + env['CC'] = ARGUMENTS.get('CC') + +if ARGUMENTS.get('CXX', None): + env['CXX'] = ARGUMENTS.get('CXX') + +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 @@ -175,35 +207,67 @@ 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")) env.Append(CPPPATH=[Dir('ext/dnet')]) -# Find Python include and library directories for embedding the -# interpreter. For consistency, we will use the same Python -# installation used to run scons (and thus this script). If you want -# to link in an alternate version, see above for instructions on how -# to invoke scons with a different copy of the Python interpreter. - -# Get brief Python version name (e.g., "python2.4") for locating -# include & library files -py_version_name = 'python' + sys.version[:3] - -# include path, e.g. /usr/local/include/python2.4 -env.Append(CPPPATH = os.path.join(sys.exec_prefix, 'include', py_version_name)) -env.Append(LIBS = py_version_name) -# add library path too if it's not in the default place -if sys.exec_prefix != '/usr': - env.Append(LIBPATH = os.path.join(sys.exec_prefix, 'lib')) +# Check for SWIG +if not env.has_key('SWIG'): + print 'Error: SWIG utility not found.' + print ' Please install (see http://www.swig.org) and retry.' + Exit(1) + +# 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': + print 'Error determining SWIG version.' + Exit(1) + +min_swig_version = '1.3.28' +if compare_versions(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) # Set up SWIG flags & scanner - env.Append(SWIGFLAGS=Split('-c++ -python -modern $_CPPINCFLAGS')) import SCons.Scanner @@ -215,14 +279,57 @@ swig_scanner = SCons.Scanner.ClassicCPP("SwigScan", ".i", "CPPPATH", env.Append(SCANNERS = swig_scanner) -# Other default libraries -env.Append(LIBS=['z']) - # 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 +# installation used to run scons (and thus this script). If you want +# to link in an alternate version, see above for instructions on how +# to invoke scons with a different copy of the Python interpreter. + +# Get brief Python version name (e.g., "python2.4") for locating +# include & library files +py_version_name = 'python' + sys.version[:3] + +# include path, e.g. /usr/local/include/python2.4 +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', '<>'): + print "Error: can't find Python.h header in", py_header_path + Exit(1) + +# add library path too if it's not in the default place +py_lib_path = None +if sys.exec_prefix != '/usr': + 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' +if py_lib_path: + env.Append(LIBPATH = py_lib_path) + print 'Adding', py_lib_path, 'to LIBPATH for', py_version_name +if not conf.CheckLib(py_version_name): + print "Error: can't find Python library", py_version_name + Exit(1) + +# On Solaris you need to use libsocket for socket ops +if not conf.CheckLibWithHeader(None, 'sys/socket.h', 'C++', 'accept(0,0,0);'): + if not conf.CheckLibWithHeader('socket', 'sys/socket.h', 'C++', 'accept(0,0,0);'): + print "Can't find library with socket calls (e.g. accept())" + Exit(1) + +# 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++','zlibVersion();'): + print 'Error: did not find needed zlib compression library '\ + 'and/or zlib.h header file.' + print ' Please install zlib and try again.' + Exit(1) # Check for (C99 FP environment control) have_fenv = conf.CheckHeader('fenv.h', '<>') @@ -237,13 +344,10 @@ have_mysql = mysql_config != None # Check MySQL version. if have_mysql: mysql_version = os.popen(mysql_config + ' --version').read() - mysql_version = mysql_version.split('.') - mysql_major = int(mysql_version[0]) - mysql_minor = int(mysql_version[1]) - # This version check is probably overly conservative, but it deals - # with the versions we have installed. - if mysql_major < 4 or (mysql_major == 4 and mysql_minor < 1): - print "Warning: MySQL v4.1 or newer required." + min_mysql_version = '4.1' + if compare_versions(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. @@ -259,12 +363,14 @@ if have_mysql: env = conf.Finish() # Define the universe of supported ISAs -env['ALL_ISA_LIST'] = ['alpha', 'sparc', 'mips'] +env['ALL_ISA_LIST'] = ['alpha', 'sparc', 'mips', 'x86'] # Define the universe of supported CPU models env['ALL_CPU_LIST'] = ['AtomicSimpleCPU', 'TimingSimpleCPU', - 'FullCPU', 'AlphaO3CPU', - 'OzoneSimpleCPU', 'OzoneCPU'] + 'O3CPU', 'OzoneCPU'] + +if os.path.isdir(joinpath(SRCDIR, 'encumbered/cpu/full')): + env['ALL_CPU_LIST'] += ['FullCPU'] # Sticky options get saved in the options file so they persist from # one invocation to the next (unless overridden, in which case the new @@ -277,7 +383,7 @@ sticky_opts.AddOptions( # 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', + ListOption('CPU_MODELS', 'CPU models', 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU', env['ALL_CPU_LIST']), BoolOption('ALPHA_TLASER', 'Model Alpha TurboLaser platform (vs. Tsunami)', False), @@ -296,7 +402,10 @@ sticky_opts.AddOptions( ('CC', 'C compiler', os.environ.get('CC', env['CC'])), ('CXX', 'C++ compiler', os.environ.get('CXX', env['CXX'])), BoolOption('BATCH', 'Use batch pool for build and tests', False), - ('BATCH_CMD', 'Batch pool submission command name', 'qdo') + ('BATCH_CMD', 'Batch pool submission command name', 'qdo'), + ('PYTHONHOME', + 'Override the default PYTHONHOME for this system (use with caution)', + '%s:%s' % (sys.prefix, sys.exec_prefix)) ) # Non-sticky options only apply to the current build. @@ -308,7 +417,7 @@ nonsticky_opts.AddOptions( # These options get exported to #defines in config/*.hh (see src/SConscript). env.ExportOptions = ['FULL_SYSTEM', 'ALPHA_TLASER', 'USE_FENV', \ 'USE_MYSQL', 'NO_FAST_ALLOC', 'SS_COMPATIBLE_FP', \ - 'USE_CHECKER'] + 'USE_CHECKER', 'PYTHONHOME', 'TARGET_ISA'] # Define a handy 'no-op' action def no_action(target, source, env): @@ -347,9 +456,14 @@ 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') - # Force value to 0/1 even if it's a Python bool - val = int(eval(str(env[option]))) + target = joinpath('config', option.lower() + '.hh') + val = env[option] + if isinstance(val, bool): + # Force value to 0/1 + val = int(val) + elif isinstance(val, str): + val = '"' + val + '"' + # Sources are option name & value (packaged in SCons Value nodes) return ([target], [Value(option), Value(val)]) @@ -391,9 +505,49 @@ 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') +################################################### +# +# This function is used to set up a directory with switching headers +# +################################################### + +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 + # list of ISAs from env['ALL_ISA_LIST']. + def gen_switch_hdr(target, source, env): + fname = str(target[0]) + basename = os.path.basename(fname) + f = open(fname, 'w') + f.write('#include "arch/isa_specific.hh"\n') + cond = '#if' + for isa in env['ALL_ISA_LIST']: + f.write('%s THE_ISA == %s_ISA\n#include "%s/%s/%s"\n' + % (cond, isa.upper(), dirname, isa, basename)) + cond = '#elif' + f.write('#else\n#error "THE_ISA not set"\n#endif\n') + f.close() + return 0 + + # String to print when generating header + def gen_switch_hdr_string(target, source, env): + return "Generating switch header " + str(target[0]) + + # Build SCons Action object. 'varlist' specifies env vars that this + # action depends on; when env['ALL_ISA_LIST'] changes these actions + # should get re-executed. + switch_hdr_action = Action(gen_switch_hdr, gen_switch_hdr_string, + varlist=['ALL_ISA_LIST']) + + # Instantiate actions for each header + for hdr in switch_headers: + env.Command(hdr, [], switch_hdr_action) + +env.make_switching_dir = make_switching_dir + ################################################### # # Define build environments for selected configurations. @@ -416,7 +570,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 @@ -431,8 +585,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" \ @@ -494,13 +648,14 @@ for build_path in build_paths: exports = 'env') # Set up the regression tests for each build. -# for e in envList: -# SConscript('m5-test/SConscript', -# build_dir = os.path.join(build_dir, 'test', e.Label), -# exports = { 'env' : e }, duplicate = False) + for e in envList: + SConscript('tests/SConscript', + build_dir = joinpath(build_path, 'tests', e.Label), + exports = { 'env' : e }, duplicate = False) Help(help_text) + ################################################### # # Let SCons do its thing. At this point SCons will use the defined