1# -*- mode:python -*-
2
3# Copyright (c) 2004-2005 The Regents of The University of Michigan
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions are
8# met: redistributions of source code must retain the above copyright

--- 13 unchanged lines hidden (view full) ---

22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28#
29# Authors: Steve Reinhardt
30# Nathan Binkert
31
32###################################################
33#
34# SCons top-level build description (SConstruct) file.
35#
36# While in this directory ('m5'), just type 'scons' to build the default
37# configuration (see below), or type 'scons build/<CONFIG>/<binary>'
38# to build some other configuration (e.g., 'build/ALPHA_FS/m5.opt' for

--- 20 unchanged lines hidden (view full) ---

59#
60# You can use 'scons -H' to print scons options. If you're in this
61# 'm5' directory (or use -u or -C to tell scons where to find this
62# file), you can use 'scons -h' to print all the M5-specific build
63# options as well.
64#
65###################################################
66
66import sys
67# Check for recent-enough Python and SCons versions.
68try:
69 # Really old versions of scons only take two options for the
70 # function, so check once without the revision and once with the
71 # revision, the first instance will fail for stuff other than
72 # 0.98, and the second will fail for 0.98.0
73 EnsureSConsVersion(0, 98)
74 EnsureSConsVersion(0, 98, 1)
75except SystemExit, e:
76 print """
77For more details, see:
78 http://m5sim.org/wiki/index.php/Compiling_M5
79"""
80 raise
81
82# We ensure the python version early because we have stuff that
83# requires python 2.4
84try:
85 EnsurePythonVersion(2, 4)
86except SystemExit, e:
87 print """
88You can use a non-default installation of the Python interpreter by
89either (1) rearranging your PATH so that scons finds the non-default
90'python' first or (2) explicitly invoking an alternative interpreter
91on the scons script.
92
93For more details, see:
94 http://m5sim.org/wiki/index.php/Using_a_non-default_Python_installation
95"""
96 raise
97
98import os
99import re
100import subprocess
101import sys
102
70from os.path import isdir, isfile, join as joinpath
103from os import mkdir, environ
104from os.path import abspath, basename, dirname, expanduser, normpath
105from os.path import exists, isdir, isfile
106from os.path import join as joinpath, split as splitpath
107
108import SCons
109
74# Check for recent-enough Python and SCons versions. If your system's
75# default installation of Python is not recent enough, you can use a
76# non-default installation of the Python interpreter by either (1)
77# rearranging your PATH so that scons finds the non-default 'python'
78# first or (2) explicitly invoking an alternative interpreter on the
79# scons script, e.g., "/usr/local/bin/python2.4 `which scons` [args]".
80EnsurePythonVersion(2,4)
110def read_command(cmd):
111 """run the command cmd, read the results and return them
112 this is sorta like `cmd` in shell"""
113 from subprocess import Popen, PIPE, STDOUT
114 subp = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT, close_fds=True)
115 return subp.communicate()[0]
116
82# Import subprocess after we check the version since it doesn't exist in
83# Python < 2.4.
84import subprocess
85
117# helper function: compare arrays or strings of version numbers.
118# E.g., compare_version((1,3,25), (1,4,1)')
119# returns -1, 0, 1 if v1 is <, ==, > v2
120def compare_versions(v1, v2):
121 def make_version_list(v):
122 if isinstance(v, (list,tuple)):
123 return v
124 elif isinstance(v, str):

--- 7 unchanged lines hidden (view full) ---

132 for n1,n2 in zip(v1, v2):
133 if n1 < n2: return -1
134 if n1 > n2: return 1
135 # all corresponding values are equal... see if one has extra values
136 if len(v1) < len(v2): return -1
137 if len(v1) > len(v2): return 1
138 return 0
139
109# SCons version numbers need special processing because they can have
110# charecters and an release date embedded in them. This function does
111# the magic to extract them in a similar way to the SCons internal function
112# function does and then checks that the current version is not contained in
113# a list of version tuples (bad_ver_strs)
114def CheckSCons(bad_ver_strs):
115 def scons_ver(v):
116 num_parts = v.split(' ')[0].split('.')
117 major = int(num_parts[0])
118 minor = int(re.match('\d+', num_parts[1]).group())
119 rev = 0
120 rdate = 0
121 if len(num_parts) > 2:
122 try: rev = int(re.match('\d+', num_parts[2]).group())
123 except: pass
124 rev_parts = num_parts[2].split('d')
125 if len(rev_parts) > 1:
126 rdate = int(re.match('\d+', rev_parts[1]).group())
127
128 return (major, minor, rev, rdate)
129
130 sc_ver = scons_ver(SCons.__version__)
131 for bad_ver in bad_ver_strs:
132 bv = (scons_ver(bad_ver[0]), scons_ver(bad_ver[1]))
133 if compare_versions(sc_ver, bv[0]) != -1 and\
134 compare_versions(sc_ver, bv[1]) != 1:
135 print "The version of SCons that you have installed: ", SCons.__version__
136 print "has a bug that prevents it from working correctly with M5."
137 print "Please install a version NOT contained within the following",
138 print "ranges (inclusive):"
139 for bad_ver in bad_ver_strs:
140 print " %s - %s" % bad_ver
141 Exit(2)
142
143CheckSCons((
144 # We need a version that is 0.96.91 or newer
145 ('0.0.0', '0.96.90'),
146 ))
147
148
140# The absolute path to the current directory (where this file lives).
141ROOT = Dir('.').abspath
142
143# Path to the M5 source tree.
144SRCDIR = joinpath(ROOT, 'src')
145
146# tell python where to find m5 python code
147sys.path.append(joinpath(ROOT, 'src/python'))
148
149###################################################
150# Mercurial Stuff.
151# 1) Grab repository revision if we know it.
152# 2) Ensure that the style hook is in place.
153###################################################
154
155hg_info = "Unknown"
156try:
157 if not exists(ROOT) or not isdir(ROOT) or \
158 not exists(joinpath(ROOT, ".hg")):
159 raise ValueError(".hg directory not found")
160 hg_info = read_command("cd %s; hg id -n -i -t -b" % ROOT).strip()
161except ImportError, e:
162 print "Mercurial not found"
163except ValueError, e:
164 print e
165except Exception, e:
166 print "Other mercurial exception: %s" % e
167
168def check_style_hook(ui):
169 ui.readconfig(joinpath(ROOT, '.hg', 'hgrc'))
170 style_hook = ui.config('hooks', 'pretxncommit.style', None)
171
172 if not style_hook:
173 print """\
174You're missing the M5 style hook.
175Please install the hook so we can ensure that all code fits a common style.

--- 12 unchanged lines hidden (view full) ---

188
189if ARGUMENTS.get('IGNORE_STYLE') != 'True' and isdir(joinpath(ROOT, '.hg')):
190 try:
191 from mercurial import ui
192 check_style_hook(ui.ui())
193 except ImportError:
194 pass
195
196
197###################################################
198#
199# Figure out which configurations to set up based on the path(s) of
200# the target(s).
201#
202###################################################
203
204# Find default configuration & binary.
194Default(os.environ.get('M5_DEFAULT_BINARY', 'build/ALPHA_SE/m5.debug'))
205Default(environ.get('M5_DEFAULT_BINARY', 'build/ALPHA_SE/m5.debug'))
206
207# helper function: find last occurrence of element in list
208def rfind(l, elt, offs = -1):
209 for i in range(len(l)+offs, 0, -1):
210 if l[i] == elt:
211 return i
212 raise ValueError, "element not found"
213
214# Each target must have 'build' in the interior of the path; the
215# directory below this will determine the build parameters. For
216# example, for target 'foo/bar/build/ALPHA_SE/arch/alpha/blah.do' we
217# recognize that ALPHA_SE specifies the configuration because it
218# follow 'build' in the bulid path.
219
220# Generate absolute paths to targets so we can see where the build dir is
221if COMMAND_LINE_TARGETS:
222 # Ask SCons which directory it was invoked from
223 launch_dir = GetLaunchDir()
224 # Make targets relative to invocation directory
214 abs_targets = map(lambda x: os.path.normpath(joinpath(launch_dir, str(x))),
215 COMMAND_LINE_TARGETS)
225 abs_targets = [ normpath(joinpath(launch_dir, str(x))) for x in \
226 COMMAND_LINE_TARGETS]
227else:
228 # Default targets are relative to root of tree
218 abs_targets = map(lambda x: os.path.normpath(joinpath(ROOT, str(x))),
219 DEFAULT_TARGETS)
229 abs_targets = [ normpath(joinpath(ROOT, str(x))) for x in \
230 DEFAULT_TARGETS]
231
232
233# Generate a list of the unique build roots and configs that the
234# collected targets reference.
224build_paths = []
235variant_paths = []
236build_root = None
237for t in abs_targets:
238 path_dirs = t.split('/')
239 try:
240 build_top = rfind(path_dirs, 'build', -2)
241 except:
242 print "Error: no non-leaf 'build' dir found on target path", t
243 Exit(1)
244 this_build_root = joinpath('/',*path_dirs[:build_top+1])
245 if not build_root:
246 build_root = this_build_root
247 else:
248 if this_build_root != build_root:
249 print "Error: build targets not under same build root\n"\
250 " %s\n %s" % (build_root, this_build_root)
251 Exit(1)
241 build_path = joinpath('/',*path_dirs[:build_top+2])
242 if build_path not in build_paths:
243 build_paths.append(build_path)
252 variant_path = joinpath('/',*path_dirs[:build_top+2])
253 if variant_path not in variant_paths:
254 variant_paths.append(variant_path)
255
256# Make sure build_root exists (might not if this is the first build there)
257if not isdir(build_root):
247 os.mkdir(build_root)
258 mkdir(build_root)
259
260###################################################
261#
262# Set up the default build environment. This environment is copied
263# and modified according to each selected configuration.
264#
265###################################################
266
256env = Environment(ENV = os.environ, # inherit user's environment vars
267env = Environment(ENV = environ, # inherit user's environment vars
268 ROOT = ROOT,
258 SRCDIR = SRCDIR)
269 SRCDIR = SRCDIR,
270 HG_INFO = hg_info)
271
272Export('env')
273
262env.SConsignFile(joinpath(build_root,"sconsign"))
274env.SConsignFile(joinpath(build_root, "sconsign"))
275
276# Default duplicate option is to use hard links, but this messes up
277# when you use emacs to edit a file in the target dir, as emacs moves
278# file to file~ then copies to file, breaking the link. Symbolic
279# (soft) links work better.
280env.SetOption('duplicate', 'soft-copy')
281
270# I waffle on this setting... it does avoid a few painful but
271# unnecessary builds, but it also seems to make trivial builds take
272# noticeably longer.
273if False:
274 env.TargetSignatures('content')
275
282#
277# Set up global sticky options... these are common to an entire build
283# Set up global sticky variables... these are common to an entire build
284# tree (not specific to a particular build like ALPHA_SE)
285#
286
281# Option validators & converters for global sticky options
287# Variable validators & converters for global sticky variables
288def PathListMakeAbsolute(val):
289 if not val:
290 return val
285 f = lambda p: os.path.abspath(os.path.expanduser(p))
291 f = lambda p: abspath(expanduser(p))
292 return ':'.join(map(f, val.split(':')))
293
294def PathListAllExist(key, val, env):
295 if not val:
296 return
297 paths = val.split(':')
298 for path in paths:
299 if not isdir(path):
300 raise SCons.Errors.UserError("Path does not exist: '%s'" % path)
301
296global_sticky_opts_file = joinpath(build_root, 'options.global')
302global_sticky_vars_file = joinpath(build_root, 'variables.global')
303
298global_sticky_opts = Options(global_sticky_opts_file, args=ARGUMENTS)
304global_sticky_vars = Variables(global_sticky_vars_file, args=ARGUMENTS)
305
300global_sticky_opts.AddOptions(
301 ('CC', 'C compiler', os.environ.get('CC', env['CC'])),
302 ('CXX', 'C++ compiler', os.environ.get('CXX', env['CXX'])),
306global_sticky_vars.AddVariables(
307 ('CC', 'C compiler', environ.get('CC', env['CC'])),
308 ('CXX', 'C++ compiler', environ.get('CXX', env['CXX'])),
309 ('BATCH', 'Use batch pool for build and tests', False),
310 ('BATCH_CMD', 'Batch pool submission command name', 'qdo'),
311 ('EXTRAS', 'Add Extra directories to the compilation', '',
312 PathListAllExist, PathListMakeAbsolute)
313 )
314
309
315# base help text
316help_text = '''
317Usage: scons [scons options] [build options] [target(s)]
318
319Global sticky options:
320'''
321
316help_text += "Global sticky options:\n" \
317 + global_sticky_opts.GenerateHelpText(env)
322help_text += global_sticky_vars.GenerateHelpText(env)
323
319# Update env with values from ARGUMENTS & file global_sticky_opts_file
320global_sticky_opts.Update(env)
324# Update env with values from ARGUMENTS & file global_sticky_vars_file
325global_sticky_vars.Update(env)
326
322# Save sticky option settings back to current options file
323global_sticky_opts.Save(global_sticky_opts_file, env)
327# Save sticky variable settings back to current variables file
328global_sticky_vars.Save(global_sticky_vars_file, env)
329
325# Parse EXTRAS option to build list of all directories where we're
330# Parse EXTRAS variable to build list of all directories where we're
331# look for sources etc. This list is exported as base_dir_list.
332base_dir = joinpath(ROOT, 'src')
333if env['EXTRAS']:
334 extras_dir_list = env['EXTRAS'].split(':')
335else:
336 extras_dir_list = []
337
338Export('base_dir')
339Export('extras_dir_list')
340
341# M5_PLY is used by isa_parser.py to find the PLY package.
342env.Append(ENV = { 'M5_PLY' : str(Dir('ext/ply')) })
338env['GCC'] = subprocess.Popen(env['CXX'] + ' --version', shell=True,
339 stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
340 close_fds=True).communicate()[0].find('g++') >= 0
341env['SUNCC'] = subprocess.Popen(env['CXX'] + ' -V', shell=True,
342 stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
343 close_fds=True).communicate()[0].find('Sun C++') >= 0
344env['ICC'] = subprocess.Popen(env['CXX'] + ' -V', shell=True,
345 stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
346 close_fds=True).communicate()[0].find('Intel') >= 0
343env['GCC'] = read_command(env['CXX'] + ' --version').find('g++') >= 0
344env['SUNCC'] = read_command(env['CXX'] + ' -V').find('Sun C++') >= 0
345env['ICC'] = read_command(env['CXX'] + ' -V').find('Intel') >= 0
346if env['GCC'] + env['SUNCC'] + env['ICC'] > 1:
347 print 'Error: How can we have two at the same time?'
348 Exit(1)
349
351
350# Set up default C++ compiler flags
351if env['GCC']:
352 env.Append(CCFLAGS='-pipe')
353 env.Append(CCFLAGS='-fno-strict-aliasing')
354 env.Append(CCFLAGS=Split('-Wall -Wno-sign-compare -Werror -Wundef'))
355 env.Append(CXXFLAGS='-Wno-deprecated')
356elif env['ICC']:
357 pass #Fix me... add warning flags once we clean up icc warnings

--- 25 unchanged lines hidden (view full) ---

383
384# Check for SWIG
385if not env.has_key('SWIG'):
386 print 'Error: SWIG utility not found.'
387 print ' Please install (see http://www.swig.org) and retry.'
388 Exit(1)
389
390# Check for appropriate SWIG version
393swig_version = os.popen('swig -version').read().split()
391swig_version = read_command('swig -version').split()
392# First 3 words should be "SWIG Version x.y.z"
393if len(swig_version) < 3 or \
394 swig_version[0] != 'SWIG' or swig_version[1] != 'Version':
395 print 'Error determining SWIG version.'
396 Exit(1)
397
398min_swig_version = '1.3.28'
399if compare_versions(swig_version[2], min_swig_version) < 0:

--- 63 unchanged lines hidden (view full) ---

463# way so don't need to check the return code.
464conf.CheckLeading()
465
466# Check if we should compile a 64 bit binary on Mac OS X/Darwin
467try:
468 import platform
469 uname = platform.uname()
470 if uname[0] == 'Darwin' and compare_versions(uname[2], '9.0.0') >= 0:
473 if int(subprocess.Popen('sysctl -n hw.cpu64bit_capable', shell=True,
474 stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
475 close_fds=True).communicate()[0][0]):
471 if int(read_command('sysctl -n hw.cpu64bit_capable')[0]):
472 env.Append(CCFLAGS='-arch x86_64')
473 env.Append(CFLAGS='-arch x86_64')
474 env.Append(LINKFLAGS='-arch x86_64')
475 env.Append(ASFLAGS='-arch x86_64')
476except:
477 pass
478
479# Recent versions of scons substitute a "Null" object for Configure()

--- 15 unchanged lines hidden (view full) ---

495
496 conf = NullConf(env)
497
498# Find Python include and library directories for embedding the
499# interpreter. For consistency, we will use the same Python
500# installation used to run scons (and thus this script). If you want
501# to link in an alternate version, see above for instructions on how
502# to invoke scons with a different copy of the Python interpreter.
503from distutils import sysconfig
504
508# Get brief Python version name (e.g., "python2.4") for locating
509# include & library files
510py_version_name = 'python' + sys.version[:3]
505py_getvar = sysconfig.get_config_var
506
512# include path, e.g. /usr/local/include/python2.4
513py_header_path = joinpath(sys.exec_prefix, 'include', py_version_name)
514env.Append(CPPPATH = py_header_path)
515# verify that it works
507py_version = 'python' + py_getvar('VERSION')
508
509py_general_include = sysconfig.get_python_inc()
510py_platform_include = sysconfig.get_python_inc(plat_specific=True)
511py_includes = [ py_general_include ]
512if py_platform_include != py_general_include:
513 py_includes.append(py_platform_include)
514
515py_lib_path = []
516# add the prefix/lib/pythonX.Y/config dir, but only if there is no
517# shared library in prefix/lib/.
518if not py_getvar('Py_ENABLE_SHARED'):
519 py_lib_path.append('-L' + py_getvar('LIBPL'))
520
521py_libs = []
522for lib in py_getvar('LIBS').split() + py_getvar('SYSLIBS').split():
523 if lib not in py_libs:
524 py_libs.append(lib)
525py_libs.append('-l' + py_version)
526
527env.Append(CPPPATH=py_includes)
528env.Append(LIBPATH=py_lib_path)
529#env.Append(LIBS=py_libs)
530
531# verify that this stuff works
532if not conf.CheckHeader('Python.h', '<>'):
517 print "Error: can't find Python.h header in", py_header_path
533 print "Error: can't find Python.h header in", py_includes
534 Exit(1)
535
520# add library path too if it's not in the default place
521py_lib_path = None
522if sys.exec_prefix != '/usr':
523 py_lib_path = joinpath(sys.exec_prefix, 'lib')
524elif sys.platform == 'cygwin':
525 # cygwin puts the .dll in /bin for some reason
526 py_lib_path = '/bin'
527if py_lib_path:
528 env.Append(LIBPATH = py_lib_path)
529 print 'Adding', py_lib_path, 'to LIBPATH for', py_version_name
530if not conf.CheckLib(py_version_name):
531 print "Error: can't find Python library", py_version_name
532 Exit(1)
536for lib in py_libs:
537 assert lib.startswith('-l')
538 lib = lib[2:]
539 if not conf.CheckLib(lib):
540 print "Error: can't find library %s required by python" % lib
541 Exit(1)
542
543# On Solaris you need to use libsocket for socket ops
544if not conf.CheckLibWithHeader(None, 'sys/socket.h', 'C++', 'accept(0,0,0);'):
545 if not conf.CheckLibWithHeader('socket', 'sys/socket.h', 'C++', 'accept(0,0,0);'):
546 print "Can't find library with socket calls (e.g. accept())"
547 Exit(1)
548
549# Check for zlib. If the check passes, libz will be automatically

--- 5 unchanged lines hidden (view full) ---

555 Exit(1)
556
557# Check for <fenv.h> (C99 FP environment control)
558have_fenv = conf.CheckHeader('fenv.h', '<>')
559if not have_fenv:
560 print "Warning: Header file <fenv.h> not found."
561 print " This host has no IEEE FP rounding mode control."
562
563######################################################################
564#
565# Check for mysql.
566#
567mysql_config = WhereIs('mysql_config')
556have_mysql = mysql_config != None
568have_mysql = bool(mysql_config)
569
570# Check MySQL version.
571if have_mysql:
560 mysql_version = os.popen(mysql_config + ' --version').read()
572 mysql_version = read_command(mysql_config + ' --version')
573 min_mysql_version = '4.1'
574 if compare_versions(mysql_version, min_mysql_version) < 0:
575 print 'Warning: MySQL', min_mysql_version, 'or newer required.'
576 print ' Version', mysql_version, 'detected.'
577 have_mysql = False
578
579# Set up mysql_config commands.
580if have_mysql:
581 mysql_config_include = mysql_config + ' --include'
582 if os.system(mysql_config_include + ' > /dev/null') != 0:
583 # older mysql_config versions don't support --include, use
584 # --cflags instead
585 mysql_config_include = mysql_config + ' --cflags | sed s/\\\'//g'
586 # This seems to work in all versions
587 mysql_config_libs = mysql_config + ' --libs'
588
589######################################################################
590#
591# Finish the configuration
592#
593env = conf.Finish()
594
595######################################################################
596#
597# Collect all non-global variables
598#
599
600# Define the universe of supported ISAs
601all_isa_list = [ ]
602Export('all_isa_list')
603
604# Define the universe of supported CPU models
605all_cpu_list = [ ]
606default_cpus = [ ]
607Export('all_cpu_list', 'default_cpus')
608
588# Sticky options get saved in the options file so they persist from
609# Sticky variables get saved in the variables file so they persist from
610# one invocation to the next (unless overridden, in which case the new
611# value becomes sticky).
591sticky_opts = Options(args=ARGUMENTS)
592Export('sticky_opts')
612sticky_vars = Variables(args=ARGUMENTS)
613Export('sticky_vars')
614
594# Non-sticky options only apply to the current build.
595nonsticky_opts = Options(args=ARGUMENTS)
596Export('nonsticky_opts')
615# Non-sticky variables only apply to the current build.
616nonsticky_vars = Variables(args=ARGUMENTS)
617Export('nonsticky_vars')
618
619# Walk the tree and execute all SConsopts scripts that wil add to the
599# above options
620# above variables
621for bdir in [ base_dir ] + extras_dir_list:
622 for root, dirs, files in os.walk(bdir):
623 if 'SConsopts' in files:
624 print "Reading", joinpath(root, 'SConsopts')
625 SConscript(joinpath(root, 'SConsopts'))
626
627all_isa_list.sort()
628all_cpu_list.sort()
629default_cpus.sort()
630
610sticky_opts.AddOptions(
611 EnumOption('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list),
612 BoolOption('FULL_SYSTEM', 'Full-system support', False),
613 # There's a bug in scons 0.96.1 that causes ListOptions with list
614 # values (more than one value) not to be able to be restored from
615 # a saved option file. If this causes trouble then upgrade to
616 # scons 0.96.90 or later.
617 ListOption('CPU_MODELS', 'CPU models', default_cpus, all_cpu_list),
618 BoolOption('NO_FAST_ALLOC', 'Disable fast object allocator', False),
619 BoolOption('FAST_ALLOC_DEBUG', 'Enable fast object allocator debugging',
620 False),
621 BoolOption('FAST_ALLOC_STATS', 'Enable fast object allocator statistics',
622 False),
623 BoolOption('EFENCE', 'Link with Electric Fence malloc debugger',
624 False),
625 BoolOption('SS_COMPATIBLE_FP',
626 'Make floating-point results compatible with SimpleScalar',
627 False),
628 BoolOption('USE_SSE2',
629 'Compile for SSE2 (-msse2) to get IEEE FP on x86 hosts',
630 False),
631 BoolOption('USE_MYSQL', 'Use MySQL for stats output', have_mysql),
632 BoolOption('USE_FENV', 'Use <fenv.h> IEEE mode control', have_fenv),
633 BoolOption('USE_CHECKER', 'Use checker for detailed CPU models', False),
631sticky_vars.AddVariables(
632 EnumVariable('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list),
633 BoolVariable('FULL_SYSTEM', 'Full-system support', False),
634 ListVariable('CPU_MODELS', 'CPU models', default_cpus, all_cpu_list),
635 BoolVariable('NO_FAST_ALLOC', 'Disable fast object allocator', False),
636 BoolVariable('FAST_ALLOC_DEBUG', 'Enable fast object allocator debugging',
637 False),
638 BoolVariable('FAST_ALLOC_STATS', 'Enable fast object allocator statistics',
639 False),
640 BoolVariable('EFENCE', 'Link with Electric Fence malloc debugger',
641 False),
642 BoolVariable('SS_COMPATIBLE_FP',
643 'Make floating-point results compatible with SimpleScalar',
644 False),
645 BoolVariable('USE_SSE2',
646 'Compile for SSE2 (-msse2) to get IEEE FP on x86 hosts',
647 False),
648 BoolVariable('USE_MYSQL', 'Use MySQL for stats output', have_mysql),
649 BoolVariable('USE_FENV', 'Use <fenv.h> IEEE mode control', have_fenv),
650 BoolVariable('USE_CHECKER', 'Use checker for detailed CPU models', False),
651 )
652
636nonsticky_opts.AddOptions(
637 BoolOption('update_ref', 'Update test reference outputs', False)
653nonsticky_vars.AddVariables(
654 BoolVariable('update_ref', 'Update test reference outputs', False)
655 )
656
640# These options get exported to #defines in config/*.hh (see src/SConscript).
641env.ExportOptions = ['FULL_SYSTEM', 'ALPHA_TLASER', 'USE_FENV', \
642 'USE_MYSQL', 'NO_FAST_ALLOC', 'FAST_ALLOC_DEBUG', \
643 'FAST_ALLOC_STATS', 'SS_COMPATIBLE_FP', \
644 'USE_CHECKER', 'TARGET_ISA']
657# These variables get exported to #defines in config/*.hh (see src/SConscript).
658env.ExportVariables = ['FULL_SYSTEM', 'ALPHA_TLASER', 'USE_FENV', \
659 'USE_MYSQL', 'NO_FAST_ALLOC', 'FAST_ALLOC_DEBUG', \
660 'FAST_ALLOC_STATS', 'SS_COMPATIBLE_FP', \
661 'USE_CHECKER', 'TARGET_ISA']
662
646# Define a handy 'no-op' action
647def no_action(target, source, env):
648 return 0
649
650env.NoAction = Action(no_action, None)
651
663###################################################
664#
665# Define a SCons builder for configuration flag headers.
666#
667###################################################
668
669# This function generates a config header file that #defines the
659# option symbol to the current option setting (0 or 1). The source
660# operands are the name of the option and a Value node containing the
661# value of the option.
670# variable symbol to the current variable setting (0 or 1). The source
671# operands are the name of the variable and a Value node containing the
672# value of the variable.
673def build_config_file(target, source, env):
663 (option, value) = [s.get_contents() for s in source]
674 (variable, value) = [s.get_contents() for s in source]
675 f = file(str(target[0]), 'w')
665 print >> f, '#define', option, value
676 print >> f, '#define', variable, value
677 f.close()
678 return None
679
680# Generate the message to be printed when building the config file.
681def build_config_file_string(target, source, env):
671 (option, value) = [s.get_contents() for s in source]
672 return "Defining %s as %s in %s." % (option, value, target[0])
682 (variable, value) = [s.get_contents() for s in source]
683 return "Defining %s as %s in %s." % (variable, value, target[0])
684
685# Combine the two functions into a scons Action object.
686config_action = Action(build_config_file, build_config_file_string)
687
688# The emitter munges the source & target node lists to reflect what
689# we're really doing.
690def config_emitter(target, source, env):
680 # extract option name from Builder arg
681 option = str(target[0])
691 # extract variable name from Builder arg
692 variable = str(target[0])
693 # True target is config header file
683 target = joinpath('config', option.lower() + '.hh')
684 val = env[option]
694 target = joinpath('config', variable.lower() + '.hh')
695 val = env[variable]
696 if isinstance(val, bool):
697 # Force value to 0/1
698 val = int(val)
699 elif isinstance(val, str):
700 val = '"' + val + '"'
701
691 # Sources are option name & value (packaged in SCons Value nodes)
692 return ([target], [Value(option), Value(val)])
702 # Sources are variable name & value (packaged in SCons Value nodes)
703 return ([target], [Value(variable), Value(val)])
704
705config_builder = Builder(emitter = config_emitter, action = config_action)
706
707env.Append(BUILDERS = { 'ConfigFile' : config_builder })
708
698###################################################
699#
700# Define a SCons builder for copying files. This is used by the
701# Python zipfile code in src/python/SConscript, but is placed up here
702# since it's potentially more generally applicable.
703#
704###################################################
705
706copy_builder = Builder(action = Copy("$TARGET", "$SOURCE"))
707
708env.Append(BUILDERS = { 'CopyFile' : copy_builder })
709
710###################################################
711#
712# Define a simple SCons builder to concatenate files.
713#
714# Used to append the Python zip archive to the executable.
715#
716###################################################
717
718concat_builder = Builder(action = Action(['cat $SOURCES > $TARGET',
719 'chmod +x $TARGET']))
720
721env.Append(BUILDERS = { 'Concat' : concat_builder })
722
723
709# libelf build is shared across all configs in the build root.
710env.SConscript('ext/libelf/SConscript',
726 build_dir = joinpath(build_root, 'libelf'),
711 variant_dir = joinpath(build_root, 'libelf'),
712 exports = 'env')
713
714# gzstream build is shared across all configs in the build root.
715env.SConscript('ext/gzstream/SConscript',
731 build_dir = joinpath(build_root, 'gzstream'),
716 variant_dir = joinpath(build_root, 'gzstream'),
717 exports = 'env')
718
719###################################################
720#
721# This function is used to set up a directory with switching headers
722#
723###################################################
724
725env['ALL_ISA_LIST'] = all_isa_list
741def make_switching_dir(dirname, switch_headers, env):
726def make_switching_dir(dname, switch_headers, env):
727 # Generate the header. target[0] is the full path of the output
728 # header to generate. 'source' is a dummy variable, since we get the
729 # list of ISAs from env['ALL_ISA_LIST'].
730 def gen_switch_hdr(target, source, env):
731 fname = str(target[0])
747 basename = os.path.basename(fname)
732 bname = basename(fname)
733 f = open(fname, 'w')
734 f.write('#include "arch/isa_specific.hh"\n')
735 cond = '#if'
736 for isa in all_isa_list:
737 f.write('%s THE_ISA == %s_ISA\n#include "%s/%s/%s"\n'
753 % (cond, isa.upper(), dirname, isa, basename))
738 % (cond, isa.upper(), dname, isa, bname))
739 cond = '#elif'
740 f.write('#else\n#error "THE_ISA not set"\n#endif\n')
741 f.close()
742 return 0
743
744 # String to print when generating header
745 def gen_switch_hdr_string(target, source, env):
746 return "Generating switch header " + str(target[0])

--- 13 unchanged lines hidden (view full) ---

760#
761# Define build environments for selected configurations.
762#
763###################################################
764
765# rename base env
766base_env = env
767
783for build_path in build_paths:
784 print "Building in", build_path
768for variant_path in variant_paths:
769 print "Building in", variant_path
770
771 # Make a copy of the build-root environment to use for this config.
787 env = base_env.Copy()
788 env['BUILDDIR'] = build_path
772 env = base_env.Clone()
773 env['BUILDDIR'] = variant_path
774
790 # build_dir is the tail component of build path, and is used to
775 # variant_dir is the tail component of build path, and is used to
776 # determine the build parameters (e.g., 'ALPHA_SE')
792 (build_root, build_dir) = os.path.split(build_path)
777 (build_root, variant_dir) = splitpath(variant_path)
778
794 # Set env options according to the build directory config.
795 sticky_opts.files = []
796 # Options for $BUILD_ROOT/$BUILD_DIR are stored in
797 # $BUILD_ROOT/options/$BUILD_DIR so you can nuke
798 # $BUILD_ROOT/$BUILD_DIR without losing your options settings.
799 current_opts_file = joinpath(build_root, 'options', build_dir)
800 if isfile(current_opts_file):
801 sticky_opts.files.append(current_opts_file)
802 print "Using saved options file %s" % current_opts_file
779 # Set env variables according to the build directory config.
780 sticky_vars.files = []
781 # Variables for $BUILD_ROOT/$VARIANT_DIR are stored in
782 # $BUILD_ROOT/variables/$VARIANT_DIR so you can nuke
783 # $BUILD_ROOT/$VARIANT_DIR without losing your variables settings.
784 current_vars_file = joinpath(build_root, 'variables', variant_dir)
785 if isfile(current_vars_file):
786 sticky_vars.files.append(current_vars_file)
787 print "Using saved variables file %s" % current_vars_file
788 else:
804 # Build dir-specific options file doesn't exist.
789 # Build dir-specific variables file doesn't exist.
790
791 # Make sure the directory is there so we can create it later
807 opt_dir = os.path.dirname(current_opts_file)
792 opt_dir = dirname(current_vars_file)
793 if not isdir(opt_dir):
809 os.mkdir(opt_dir)
794 mkdir(opt_dir)
795
811 # Get default build options from source tree. Options are
812 # normally determined by name of $BUILD_DIR, but can be
796 # Get default build variables from source tree. Variables are
797 # normally determined by name of $VARIANT_DIR, but can be
798 # overriden by 'default=' arg on command line.
814 default_opts_file = joinpath('build_opts',
815 ARGUMENTS.get('default', build_dir))
816 if isfile(default_opts_file):
817 sticky_opts.files.append(default_opts_file)
818 print "Options file %s not found,\n using defaults in %s" \
819 % (current_opts_file, default_opts_file)
799 default_vars_file = joinpath('build_opts',
800 ARGUMENTS.get('default', variant_dir))
801 if isfile(default_vars_file):
802 sticky_vars.files.append(default_vars_file)
803 print "Variables file %s not found,\n using defaults in %s" \
804 % (current_vars_file, default_vars_file)
805 else:
821 print "Error: cannot find options file %s or %s" \
822 % (current_opts_file, default_opts_file)
806 print "Error: cannot find variables file %s or %s" \
807 % (current_vars_file, default_vars_file)
808 Exit(1)
809
825 # Apply current option settings to env
826 sticky_opts.Update(env)
827 nonsticky_opts.Update(env)
810 # Apply current variable settings to env
811 sticky_vars.Update(env)
812 nonsticky_vars.Update(env)
813
829 help_text += "\nSticky options for %s:\n" % build_dir \
830 + sticky_opts.GenerateHelpText(env) \
831 + "\nNon-sticky options for %s:\n" % build_dir \
832 + nonsticky_opts.GenerateHelpText(env)
814 help_text += "\nSticky variables for %s:\n" % variant_dir \
815 + sticky_vars.GenerateHelpText(env) \
816 + "\nNon-sticky variables for %s:\n" % variant_dir \
817 + nonsticky_vars.GenerateHelpText(env)
818
834 # Process option settings.
819 # Process variable settings.
820
821 if not have_fenv and env['USE_FENV']:
822 print "Warning: <fenv.h> not available; " \
838 "forcing USE_FENV to False in", build_dir + "."
823 "forcing USE_FENV to False in", variant_dir + "."
824 env['USE_FENV'] = False
825
826 if not env['USE_FENV']:
842 print "Warning: No IEEE FP rounding mode control in", build_dir + "."
827 print "Warning: No IEEE FP rounding mode control in", variant_dir + "."
828 print " FP results may deviate slightly from other platforms."
829
830 if env['EFENCE']:
831 env.Append(LIBS=['efence'])
832
833 if env['USE_MYSQL']:
834 if not have_mysql:
835 print "Warning: MySQL not available; " \
851 "forcing USE_MYSQL to False in", build_dir + "."
836 "forcing USE_MYSQL to False in", variant_dir + "."
837 env['USE_MYSQL'] = False
838 else:
854 print "Compiling in", build_dir, "with MySQL support."
839 print "Compiling in", variant_dir, "with MySQL support."
840 env.ParseConfig(mysql_config_libs)
841 env.ParseConfig(mysql_config_include)
842
858 # Save sticky option settings back to current options file
859 sticky_opts.Save(current_opts_file, env)
843 # Save sticky variable settings back to current variables file
844 sticky_vars.Save(current_vars_file, env)
845
846 if env['USE_SSE2']:
847 env.Append(CCFLAGS='-msse2')
848
849 # The src/SConscript file sets up the build rules in 'env' according
865 # to the configured options. It returns a list of environments,
850 # to the configured variables. It returns a list of environments,
851 # one for each variant build (debug, opt, etc.)
867 envList = SConscript('src/SConscript', build_dir = build_path,
852 envList = SConscript('src/SConscript', variant_dir = variant_path,
853 exports = 'env')
854
855 # Set up the regression tests for each build.
856 for e in envList:
857 SConscript('tests/SConscript',
873 build_dir = joinpath(build_path, 'tests', e.Label),
858 variant_dir = joinpath(variant_path, 'tests', e.Label),
859 exports = { 'env' : e }, duplicate = False)
860
861Help(help_text)
862
863
864###################################################
865#
866# Let SCons do its thing. At this point SCons will use the defined
867# build environments to build the requested targets.
868#
869###################################################
870