SConstruct revision 8881
16019Shines@cs.fsu.edu# -*- mode:python -*- 27097Sgblack@eecs.umich.edu 37097Sgblack@eecs.umich.edu# Copyright (c) 2011 Advanced Micro Devices, Inc. 47097Sgblack@eecs.umich.edu# Copyright (c) 2009 The Hewlett-Packard Development Company 57097Sgblack@eecs.umich.edu# Copyright (c) 2004-2005 The Regents of The University of Michigan 67097Sgblack@eecs.umich.edu# All rights reserved. 77097Sgblack@eecs.umich.edu# 87097Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 97097Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are 107097Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright 117097Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 127097Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 137097Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 146019Shines@cs.fsu.edu# documentation and/or other materials provided with the distribution; 156019Shines@cs.fsu.edu# neither the name of the copyright holders nor the names of its 166019Shines@cs.fsu.edu# contributors may be used to endorse or promote products derived from 176019Shines@cs.fsu.edu# this software without specific prior written permission. 186019Shines@cs.fsu.edu# 196019Shines@cs.fsu.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 206019Shines@cs.fsu.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 216019Shines@cs.fsu.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 226019Shines@cs.fsu.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 236019Shines@cs.fsu.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 246019Shines@cs.fsu.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 256019Shines@cs.fsu.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 266019Shines@cs.fsu.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 276019Shines@cs.fsu.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 286019Shines@cs.fsu.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 296019Shines@cs.fsu.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 306019Shines@cs.fsu.edu# 316019Shines@cs.fsu.edu# Authors: Steve Reinhardt 326019Shines@cs.fsu.edu# Nathan Binkert 336019Shines@cs.fsu.edu 346019Shines@cs.fsu.edu################################################### 356019Shines@cs.fsu.edu# 366019Shines@cs.fsu.edu# SCons top-level build description (SConstruct) file. 376019Shines@cs.fsu.edu# 386019Shines@cs.fsu.edu# While in this directory ('gem5'), just type 'scons' to build the default 396019Shines@cs.fsu.edu# configuration (see below), or type 'scons build/<CONFIG>/<binary>' 406019Shines@cs.fsu.edu# to build some other configuration (e.g., 'build/ALPHA/gem5.opt' for 416019Shines@cs.fsu.edu# the optimized full-system version). 426019Shines@cs.fsu.edu# 436019Shines@cs.fsu.edu# You can build gem5 in a different directory as long as there is a 446019Shines@cs.fsu.edu# 'build/<CONFIG>' somewhere along the target path. The build system 456019Shines@cs.fsu.edu# expects that all configs under the same build directory are being 466251Sgblack@eecs.umich.edu# built for the same host system. 476214Snate@binkert.org# 486019Shines@cs.fsu.edu# Examples: 496019Shines@cs.fsu.edu# 506019Shines@cs.fsu.edu# The following two commands are equivalent. The '-u' option tells 516019Shines@cs.fsu.edu# scons to search up the directory tree for this SConstruct file. 526251Sgblack@eecs.umich.edu# % cd <path-to-src>/gem5 ; scons build/ALPHA/gem5.debug 536267Sgblack@eecs.umich.edu# % cd <path-to-src>/gem5/build/ALPHA; scons -u gem5.debug 547376Sgblack@eecs.umich.edu# 557376Sgblack@eecs.umich.edu# The following two commands are equivalent and demonstrate building 567376Sgblack@eecs.umich.edu# in a directory outside of the source tree. The '-C' option tells 577376Sgblack@eecs.umich.edu# scons to chdir to the specified directory to find this SConstruct 587097Sgblack@eecs.umich.edu# file. 597097Sgblack@eecs.umich.edu# % cd <path-to-src>/gem5 ; scons /local/foo/build/ALPHA/gem5.debug 607097Sgblack@eecs.umich.edu# % cd /local/foo/build/ALPHA; scons -C <path-to-src>/gem5 gem5.debug 617097Sgblack@eecs.umich.edu# 626267Sgblack@eecs.umich.edu# You can use 'scons -H' to print scons options. If you're in this 636267Sgblack@eecs.umich.edu# 'gem5' directory (or use -u or -C to tell scons where to find this 646267Sgblack@eecs.umich.edu# file), you can use 'scons -h' to print all the gem5-specific build 656267Sgblack@eecs.umich.edu# options as well. 667098Sgblack@eecs.umich.edu# 677098Sgblack@eecs.umich.edu################################################### 686251Sgblack@eecs.umich.edu 696268Sgblack@eecs.umich.edu# Check for recent-enough Python and SCons versions. 706749Sgblack@eecs.umich.edutry: 716268Sgblack@eecs.umich.edu # Really old versions of scons only take two options for the 726269Sgblack@eecs.umich.edu # function, so check once without the revision and once with the 736251Sgblack@eecs.umich.edu # revision, the first instance will fail for stuff other than 747161Sgblack@eecs.umich.edu # 0.98, and the second will fail for 0.98.0 756251Sgblack@eecs.umich.edu EnsureSConsVersion(0, 98) 766251Sgblack@eecs.umich.edu EnsureSConsVersion(0, 98, 1) 776743Ssaidi@eecs.umich.eduexcept SystemExit, e: 786251Sgblack@eecs.umich.edu print """ 797105Sgblack@eecs.umich.eduFor more details, see: 806251Sgblack@eecs.umich.edu http://gem5.org/Dependencies 816741Sgblack@eecs.umich.edu""" 826251Sgblack@eecs.umich.edu raise 836251Sgblack@eecs.umich.edu 846268Sgblack@eecs.umich.edu# We ensure the python version early because we have stuff that 856759SAli.Saidi@ARM.com# requires python 2.4 866251Sgblack@eecs.umich.edutry: 877105Sgblack@eecs.umich.edu EnsurePythonVersion(2, 4) 886251Sgblack@eecs.umich.eduexcept SystemExit, e: 896251Sgblack@eecs.umich.edu print """ 906251Sgblack@eecs.umich.eduYou can use a non-default installation of the Python interpreter by 916251Sgblack@eecs.umich.edueither (1) rearranging your PATH so that scons finds the non-default 926251Sgblack@eecs.umich.edu'python' first or (2) explicitly invoking an alternative interpreter 936251Sgblack@eecs.umich.eduon the scons script. 947121Sgblack@eecs.umich.edu 956251Sgblack@eecs.umich.eduFor more details, see: 966251Sgblack@eecs.umich.edu http://gem5.org/wiki/index.php/Using_a_non-default_Python_installation 976251Sgblack@eecs.umich.edu""" 986251Sgblack@eecs.umich.edu raise 996251Sgblack@eecs.umich.edu 1006251Sgblack@eecs.umich.edu# Global Python includes 1016251Sgblack@eecs.umich.eduimport os 1026251Sgblack@eecs.umich.eduimport re 1036251Sgblack@eecs.umich.eduimport subprocess 1046251Sgblack@eecs.umich.eduimport sys 1056251Sgblack@eecs.umich.edu 1066251Sgblack@eecs.umich.edufrom os import mkdir, environ 1076251Sgblack@eecs.umich.edufrom os.path import abspath, basename, dirname, expanduser, normpath 1086251Sgblack@eecs.umich.edufrom os.path import exists, isdir, isfile 1096251Sgblack@eecs.umich.edufrom os.path import join as joinpath, split as splitpath 1106251Sgblack@eecs.umich.edu 1116275Sgblack@eecs.umich.edu# SCons includes 1126251Sgblack@eecs.umich.eduimport SCons 1136251Sgblack@eecs.umich.eduimport SCons.Node 1146275Sgblack@eecs.umich.edu 1156275Sgblack@eecs.umich.eduextra_python_paths = [ 1166251Sgblack@eecs.umich.edu Dir('src/python').srcnode().abspath, # gem5 includes 1176251Sgblack@eecs.umich.edu Dir('ext/ply').srcnode().abspath, # ply is used by several files 1186251Sgblack@eecs.umich.edu ] 1196251Sgblack@eecs.umich.edu 1206251Sgblack@eecs.umich.edusys.path[1:1] = extra_python_paths 1216251Sgblack@eecs.umich.edu 1226251Sgblack@eecs.umich.edufrom m5.util import compareVersions, readCommand 1236251Sgblack@eecs.umich.edu 1246251Sgblack@eecs.umich.eduhelp_texts = { 1256251Sgblack@eecs.umich.edu "options" : "", 1266251Sgblack@eecs.umich.edu "global_vars" : "", 1276251Sgblack@eecs.umich.edu "local_vars" : "" 1286251Sgblack@eecs.umich.edu} 1296251Sgblack@eecs.umich.edu 1306251Sgblack@eecs.umich.eduExport("help_texts") 1316251Sgblack@eecs.umich.edu 1326251Sgblack@eecs.umich.edu 1336251Sgblack@eecs.umich.edu# There's a bug in scons in that (1) by default, the help texts from 1346251Sgblack@eecs.umich.edu# AddOption() are supposed to be displayed when you type 'scons -h' 1356251Sgblack@eecs.umich.edu# and (2) you can override the help displayed by 'scons -h' using the 1367103Sgblack@eecs.umich.edu# Help() function, but these two features are incompatible: once 1377103Sgblack@eecs.umich.edu# you've overridden the help text using Help(), there's no way to get 1387103Sgblack@eecs.umich.edu# at the help texts from AddOptions. See: 1397103Sgblack@eecs.umich.edu# http://scons.tigris.org/issues/show_bug.cgi?id=2356 1407103Sgblack@eecs.umich.edu# http://scons.tigris.org/issues/show_bug.cgi?id=2611 1417103Sgblack@eecs.umich.edu# This hack lets us extract the help text from AddOptions and 1427103Sgblack@eecs.umich.edu# re-inject it via Help(). Ideally someday this bug will be fixed and 1437103Sgblack@eecs.umich.edu# we can just use AddOption directly. 1447103Sgblack@eecs.umich.edudef AddLocalOption(*args, **kwargs): 1457103Sgblack@eecs.umich.edu col_width = 30 1467103Sgblack@eecs.umich.edu 1477103Sgblack@eecs.umich.edu help = " " + ", ".join(args) 1487103Sgblack@eecs.umich.edu if "help" in kwargs: 1497103Sgblack@eecs.umich.edu length = len(help) 1507103Sgblack@eecs.umich.edu if length >= col_width: 1517103Sgblack@eecs.umich.edu help += "\n" + " " * col_width 1527106Sgblack@eecs.umich.edu else: 1537106Sgblack@eecs.umich.edu help += " " * (col_width - length) 1547106Sgblack@eecs.umich.edu help += kwargs["help"] 1557106Sgblack@eecs.umich.edu help_texts["options"] += help + "\n" 1567106Sgblack@eecs.umich.edu 1577106Sgblack@eecs.umich.edu AddOption(*args, **kwargs) 1587106Sgblack@eecs.umich.edu 1597106Sgblack@eecs.umich.eduAddLocalOption('--colors', dest='use_colors', action='store_true', 1607106Sgblack@eecs.umich.edu help="Add color to abbreviated scons output") 1617106Sgblack@eecs.umich.eduAddLocalOption('--no-colors', dest='use_colors', action='store_false', 1627106Sgblack@eecs.umich.edu help="Don't add color to abbreviated scons output") 1637106Sgblack@eecs.umich.eduAddLocalOption('--default', dest='default', type='string', action='store', 1647113Sgblack@eecs.umich.edu help='Override which build_opts file to use for defaults') 1657116Sgblack@eecs.umich.eduAddLocalOption('--ignore-style', dest='ignore_style', action='store_true', 1667245Sgblack@eecs.umich.edu help='Disable style checking hooks') 1677106Sgblack@eecs.umich.eduAddLocalOption('--update-ref', dest='update_ref', action='store_true', 1687106Sgblack@eecs.umich.edu help='Update test reference outputs') 1697106Sgblack@eecs.umich.eduAddLocalOption('--verbose', dest='verbose', action='store_true', 1707106Sgblack@eecs.umich.edu help='Print full tool command lines') 1717106Sgblack@eecs.umich.edu 1727106Sgblack@eecs.umich.eduuse_colors = GetOption('use_colors') 1737106Sgblack@eecs.umich.eduif use_colors: 1747106Sgblack@eecs.umich.edu from m5.util.terminal import termcap 1757113Sgblack@eecs.umich.eduelif use_colors is None: 1767113Sgblack@eecs.umich.edu # option unspecified; default behavior is to use colors iff isatty 1777106Sgblack@eecs.umich.edu from m5.util.terminal import tty_termcap as termcap 1787106Sgblack@eecs.umich.eduelse: 1797106Sgblack@eecs.umich.edu from m5.util.terminal import no_termcap as termcap 1807106Sgblack@eecs.umich.edu 1817106Sgblack@eecs.umich.edu######################################################################## 1826251Sgblack@eecs.umich.edu# 1836251Sgblack@eecs.umich.edu# Set up the main build environment. 1846254Sgblack@eecs.umich.edu# 1856254Sgblack@eecs.umich.edu######################################################################## 1866254Sgblack@eecs.umich.eduuse_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH', 'PATH', 1876254Sgblack@eecs.umich.edu 'PYTHONPATH', 'RANLIB' ]) 1886254Sgblack@eecs.umich.edu 1896254Sgblack@eecs.umich.eduuse_env = {} 1906254Sgblack@eecs.umich.edufor key,val in os.environ.iteritems(): 1916254Sgblack@eecs.umich.edu if key in use_vars or key.startswith("M5"): 1926019Shines@cs.fsu.edu use_env[key] = val 1936019Shines@cs.fsu.edu 1946019Shines@cs.fsu.edumain = Environment(ENV=use_env) 1956019Shines@cs.fsu.edumain.Decider('MD5-timestamp') 1966019Shines@cs.fsu.edumain.SetOption('implicit_cache', 1) 1976019Shines@cs.fsu.edumain.root = Dir(".") # The current directory (where this file lives). 1986019Shines@cs.fsu.edumain.srcdir = Dir("src") # The source directory 1996019Shines@cs.fsu.edu 2006019Shines@cs.fsu.edu# add useful python code PYTHONPATH so it can be used by subprocesses 2016019Shines@cs.fsu.edu# as well 2026019Shines@cs.fsu.edumain.AppendENVPath('PYTHONPATH', extra_python_paths) 2036019Shines@cs.fsu.edu 2046019Shines@cs.fsu.edu######################################################################## 2056019Shines@cs.fsu.edu# 2066019Shines@cs.fsu.edu# Mercurial Stuff. 2076019Shines@cs.fsu.edu# 2086019Shines@cs.fsu.edu# If the gem5 directory is a mercurial repository, we should do some 2096019Shines@cs.fsu.edu# extra things. 2106019Shines@cs.fsu.edu# 2116019Shines@cs.fsu.edu######################################################################## 2126019Shines@cs.fsu.edu 2136019Shines@cs.fsu.eduhgdir = main.root.Dir(".hg") 2146019Shines@cs.fsu.edu 2156019Shines@cs.fsu.edumercurial_style_message = """ 2166019Shines@cs.fsu.eduYou're missing the gem5 style hook, which automatically checks your code 2176019Shines@cs.fsu.eduagainst the gem5 style rules on hg commit and qrefresh commands. This 2186019Shines@cs.fsu.eduscript will now install the hook in your .hg/hgrc file. 2196019Shines@cs.fsu.eduPress enter to continue, or ctrl-c to abort: """ 2206019Shines@cs.fsu.edu 2216019Shines@cs.fsu.edumercurial_style_hook = """ 2226019Shines@cs.fsu.edu# The following lines were automatically added by gem5/SConstruct 2236019Shines@cs.fsu.edu# to provide the gem5 style-checking hooks 2246019Shines@cs.fsu.edu[extensions] 2256019Shines@cs.fsu.edustyle = %s/util/style.py 2266019Shines@cs.fsu.edu 2276019Shines@cs.fsu.edu[hooks] 2286019Shines@cs.fsu.edupretxncommit.style = python:style.check_style 2296019Shines@cs.fsu.edupre-qrefresh.style = python:style.check_style 2306019Shines@cs.fsu.edu# End of SConstruct additions 2316019Shines@cs.fsu.edu 2326019Shines@cs.fsu.edu""" % (main.root.abspath) 2336019Shines@cs.fsu.edu 2346019Shines@cs.fsu.edumercurial_lib_not_found = """ 2356723Sgblack@eecs.umich.eduMercurial libraries cannot be found, ignoring style hook. If 2366019Shines@cs.fsu.eduyou are a gem5 developer, please fix this and run the style 2376019Shines@cs.fsu.eduhook. It is important. 2386019Shines@cs.fsu.edu""" 2396019Shines@cs.fsu.edu 2406019Shines@cs.fsu.edu# Check for style hook and prompt for installation if it's not there. 2417311Sgblack@eecs.umich.edu# Skip this if --ignore-style was specified, there's no .hg dir to 2427311Sgblack@eecs.umich.edu# install a hook in, or there's no interactive terminal to prompt. 2437311Sgblack@eecs.umich.eduif not GetOption('ignore_style') and hgdir.exists() and sys.stdin.isatty(): 2447311Sgblack@eecs.umich.edu style_hook = True 2457311Sgblack@eecs.umich.edu try: 2467311Sgblack@eecs.umich.edu from mercurial import ui 2477311Sgblack@eecs.umich.edu ui = ui.ui() 2487311Sgblack@eecs.umich.edu ui.readconfig(hgdir.File('hgrc').abspath) 2497311Sgblack@eecs.umich.edu style_hook = ui.config('hooks', 'pretxncommit.style', None) and \ 2507311Sgblack@eecs.umich.edu ui.config('hooks', 'pre-qrefresh.style', None) 2517311Sgblack@eecs.umich.edu except ImportError: 2527311Sgblack@eecs.umich.edu print mercurial_lib_not_found 2537311Sgblack@eecs.umich.edu 2547311Sgblack@eecs.umich.edu if not style_hook: 2557311Sgblack@eecs.umich.edu print mercurial_style_message, 2567311Sgblack@eecs.umich.edu # continue unless user does ctrl-c/ctrl-d etc. 2577311Sgblack@eecs.umich.edu try: 2587311Sgblack@eecs.umich.edu raw_input() 2596019Shines@cs.fsu.edu except: 2606019Shines@cs.fsu.edu print "Input exception, exiting scons.\n" 2616019Shines@cs.fsu.edu sys.exit(1) 2626019Shines@cs.fsu.edu hgrc_path = '%s/.hg/hgrc' % main.root.abspath 2636019Shines@cs.fsu.edu print "Adding style hook to", hgrc_path, "\n" 2646019Shines@cs.fsu.edu try: 2656019Shines@cs.fsu.edu hgrc = open(hgrc_path, 'a') 266 hgrc.write(mercurial_style_hook) 267 hgrc.close() 268 except: 269 print "Error updating", hgrc_path 270 sys.exit(1) 271 272 273################################################### 274# 275# Figure out which configurations to set up based on the path(s) of 276# the target(s). 277# 278################################################### 279 280# Find default configuration & binary. 281Default(environ.get('M5_DEFAULT_BINARY', 'build/ALPHA/gem5.debug')) 282 283# helper function: find last occurrence of element in list 284def rfind(l, elt, offs = -1): 285 for i in range(len(l)+offs, 0, -1): 286 if l[i] == elt: 287 return i 288 raise ValueError, "element not found" 289 290# Take a list of paths (or SCons Nodes) and return a list with all 291# paths made absolute and ~-expanded. Paths will be interpreted 292# relative to the launch directory unless a different root is provided 293def makePathListAbsolute(path_list, root=GetLaunchDir()): 294 return [abspath(joinpath(root, expanduser(str(p)))) 295 for p in path_list] 296 297# Each target must have 'build' in the interior of the path; the 298# directory below this will determine the build parameters. For 299# example, for target 'foo/bar/build/ALPHA_SE/arch/alpha/blah.do' we 300# recognize that ALPHA_SE specifies the configuration because it 301# follow 'build' in the build path. 302 303# The funky assignment to "[:]" is needed to replace the list contents 304# in place rather than reassign the symbol to a new list, which 305# doesn't work (obviously!). 306BUILD_TARGETS[:] = makePathListAbsolute(BUILD_TARGETS) 307 308# Generate a list of the unique build roots and configs that the 309# collected targets reference. 310variant_paths = [] 311build_root = None 312for t in BUILD_TARGETS: 313 path_dirs = t.split('/') 314 try: 315 build_top = rfind(path_dirs, 'build', -2) 316 except: 317 print "Error: no non-leaf 'build' dir found on target path", t 318 Exit(1) 319 this_build_root = joinpath('/',*path_dirs[:build_top+1]) 320 if not build_root: 321 build_root = this_build_root 322 else: 323 if this_build_root != build_root: 324 print "Error: build targets not under same build root\n"\ 325 " %s\n %s" % (build_root, this_build_root) 326 Exit(1) 327 variant_path = joinpath('/',*path_dirs[:build_top+2]) 328 if variant_path not in variant_paths: 329 variant_paths.append(variant_path) 330 331# Make sure build_root exists (might not if this is the first build there) 332if not isdir(build_root): 333 mkdir(build_root) 334main['BUILDROOT'] = build_root 335 336Export('main') 337 338main.SConsignFile(joinpath(build_root, "sconsign")) 339 340# Default duplicate option is to use hard links, but this messes up 341# when you use emacs to edit a file in the target dir, as emacs moves 342# file to file~ then copies to file, breaking the link. Symbolic 343# (soft) links work better. 344main.SetOption('duplicate', 'soft-copy') 345 346# 347# Set up global sticky variables... these are common to an entire build 348# tree (not specific to a particular build like ALPHA_SE) 349# 350 351global_vars_file = joinpath(build_root, 'variables.global') 352 353global_vars = Variables(global_vars_file, args=ARGUMENTS) 354 355global_vars.AddVariables( 356 ('CC', 'C compiler', environ.get('CC', main['CC'])), 357 ('CXX', 'C++ compiler', environ.get('CXX', main['CXX'])), 358 ('BATCH', 'Use batch pool for build and tests', False), 359 ('BATCH_CMD', 'Batch pool submission command name', 'qdo'), 360 ('M5_BUILD_CACHE', 'Cache built objects in this directory', False), 361 ('EXTRAS', 'Add extra directories to the compilation', '') 362 ) 363 364# Update main environment with values from ARGUMENTS & global_vars_file 365global_vars.Update(main) 366help_texts["global_vars"] += global_vars.GenerateHelpText(main) 367 368# Save sticky variable settings back to current variables file 369global_vars.Save(global_vars_file, main) 370 371# Parse EXTRAS variable to build list of all directories where we're 372# look for sources etc. This list is exported as extras_dir_list. 373base_dir = main.srcdir.abspath 374if main['EXTRAS']: 375 extras_dir_list = makePathListAbsolute(main['EXTRAS'].split(':')) 376else: 377 extras_dir_list = [] 378 379Export('base_dir') 380Export('extras_dir_list') 381 382# the ext directory should be on the #includes path 383main.Append(CPPPATH=[Dir('ext')]) 384 385def strip_build_path(path, env): 386 path = str(path) 387 variant_base = env['BUILDROOT'] + os.path.sep 388 if path.startswith(variant_base): 389 path = path[len(variant_base):] 390 elif path.startswith('build/'): 391 path = path[6:] 392 return path 393 394# Generate a string of the form: 395# common/path/prefix/src1, src2 -> tgt1, tgt2 396# to print while building. 397class Transform(object): 398 # all specific color settings should be here and nowhere else 399 tool_color = termcap.Normal 400 pfx_color = termcap.Yellow 401 srcs_color = termcap.Yellow + termcap.Bold 402 arrow_color = termcap.Blue + termcap.Bold 403 tgts_color = termcap.Yellow + termcap.Bold 404 405 def __init__(self, tool, max_sources=99): 406 self.format = self.tool_color + (" [%8s] " % tool) \ 407 + self.pfx_color + "%s" \ 408 + self.srcs_color + "%s" \ 409 + self.arrow_color + " -> " \ 410 + self.tgts_color + "%s" \ 411 + termcap.Normal 412 self.max_sources = max_sources 413 414 def __call__(self, target, source, env, for_signature=None): 415 # truncate source list according to max_sources param 416 source = source[0:self.max_sources] 417 def strip(f): 418 return strip_build_path(str(f), env) 419 if len(source) > 0: 420 srcs = map(strip, source) 421 else: 422 srcs = [''] 423 tgts = map(strip, target) 424 # surprisingly, os.path.commonprefix is a dumb char-by-char string 425 # operation that has nothing to do with paths. 426 com_pfx = os.path.commonprefix(srcs + tgts) 427 com_pfx_len = len(com_pfx) 428 if com_pfx: 429 # do some cleanup and sanity checking on common prefix 430 if com_pfx[-1] == ".": 431 # prefix matches all but file extension: ok 432 # back up one to change 'foo.cc -> o' to 'foo.cc -> .o' 433 com_pfx = com_pfx[0:-1] 434 elif com_pfx[-1] == "/": 435 # common prefix is directory path: OK 436 pass 437 else: 438 src0_len = len(srcs[0]) 439 tgt0_len = len(tgts[0]) 440 if src0_len == com_pfx_len: 441 # source is a substring of target, OK 442 pass 443 elif tgt0_len == com_pfx_len: 444 # target is a substring of source, need to back up to 445 # avoid empty string on RHS of arrow 446 sep_idx = com_pfx.rfind(".") 447 if sep_idx != -1: 448 com_pfx = com_pfx[0:sep_idx] 449 else: 450 com_pfx = '' 451 elif src0_len > com_pfx_len and srcs[0][com_pfx_len] == ".": 452 # still splitting at file extension: ok 453 pass 454 else: 455 # probably a fluke; ignore it 456 com_pfx = '' 457 # recalculate length in case com_pfx was modified 458 com_pfx_len = len(com_pfx) 459 def fmt(files): 460 f = map(lambda s: s[com_pfx_len:], files) 461 return ', '.join(f) 462 return self.format % (com_pfx, fmt(srcs), fmt(tgts)) 463 464Export('Transform') 465 466 467if GetOption('verbose'): 468 def MakeAction(action, string, *args, **kwargs): 469 return Action(action, *args, **kwargs) 470else: 471 MakeAction = Action 472 main['CCCOMSTR'] = Transform("CC") 473 main['CXXCOMSTR'] = Transform("CXX") 474 main['ASCOMSTR'] = Transform("AS") 475 main['SWIGCOMSTR'] = Transform("SWIG") 476 main['ARCOMSTR'] = Transform("AR", 0) 477 main['LINKCOMSTR'] = Transform("LINK", 0) 478 main['RANLIBCOMSTR'] = Transform("RANLIB", 0) 479 main['M4COMSTR'] = Transform("M4") 480 main['SHCCCOMSTR'] = Transform("SHCC") 481 main['SHCXXCOMSTR'] = Transform("SHCXX") 482Export('MakeAction') 483 484CXX_version = readCommand([main['CXX'],'--version'], exception=False) 485CXX_V = readCommand([main['CXX'],'-V'], exception=False) 486 487main['GCC'] = CXX_version and CXX_version.find('g++') >= 0 488main['SUNCC'] = CXX_V and CXX_V.find('Sun C++') >= 0 489main['ICC'] = CXX_V and CXX_V.find('Intel') >= 0 490main['CLANG'] = CXX_V and CXX_V.find('clang') >= 0 491if main['GCC'] + main['SUNCC'] + main['ICC'] + main['CLANG'] > 1: 492 print 'Error: How can we have two at the same time?' 493 Exit(1) 494 495# Set up default C++ compiler flags 496if main['GCC']: 497 main.Append(CCFLAGS=['-pipe']) 498 main.Append(CCFLAGS=['-fno-strict-aliasing']) 499 main.Append(CCFLAGS=['-Wall', '-Wno-sign-compare', '-Wundef']) 500 main.Append(CXXFLAGS=['-Wno-deprecated']) 501 # Read the GCC version to check for versions with bugs 502 # Note CCVERSION doesn't work here because it is run with the CC 503 # before we override it from the command line 504 gcc_version = readCommand([main['CXX'], '-dumpversion'], exception=False) 505 main['GCC_VERSION'] = gcc_version 506 if not compareVersions(gcc_version, '4.4.1') or \ 507 not compareVersions(gcc_version, '4.4.2'): 508 print 'Info: Tree vectorizer in GCC 4.4.1 & 4.4.2 is buggy, disabling.' 509 main.Append(CCFLAGS=['-fno-tree-vectorize']) 510elif main['ICC']: 511 pass #Fix me... add warning flags once we clean up icc warnings 512elif main['SUNCC']: 513 main.Append(CCFLAGS=['-Qoption ccfe']) 514 main.Append(CCFLAGS=['-features=gcc']) 515 main.Append(CCFLAGS=['-features=extensions']) 516 main.Append(CCFLAGS=['-library=stlport4']) 517 main.Append(CCFLAGS=['-xar']) 518 #main.Append(CCFLAGS=['-instances=semiexplicit']) 519elif main['CLANG']: 520 clang_version_re = re.compile(".* version (\d+\.\d+)") 521 clang_version_match = clang_version_re.match(CXX_version) 522 if (clang_version_match): 523 clang_version = clang_version_match.groups()[0] 524 if compareVersions(clang_version, "2.9") < 0: 525 print 'Error: clang version 2.9 or newer required.' 526 print ' Installed version:', clang_version 527 Exit(1) 528 else: 529 print 'Error: Unable to determine clang version.' 530 Exit(1) 531 532 main.Append(CCFLAGS=['-pipe']) 533 main.Append(CCFLAGS=['-fno-strict-aliasing']) 534 main.Append(CCFLAGS=['-Wall', '-Wno-sign-compare', '-Wundef']) 535 main.Append(CCFLAGS=['-Wno-tautological-compare']) 536 main.Append(CCFLAGS=['-Wno-self-assign']) 537else: 538 print 'Error: Don\'t know what compiler options to use for your compiler.' 539 print ' Please fix SConstruct and src/SConscript and try again.' 540 Exit(1) 541 542# Set up common yacc/bison flags (needed for Ruby) 543main['YACCFLAGS'] = '-d' 544main['YACCHXXFILESUFFIX'] = '.hh' 545 546# Do this after we save setting back, or else we'll tack on an 547# extra 'qdo' every time we run scons. 548if main['BATCH']: 549 main['CC'] = main['BATCH_CMD'] + ' ' + main['CC'] 550 main['CXX'] = main['BATCH_CMD'] + ' ' + main['CXX'] 551 main['AS'] = main['BATCH_CMD'] + ' ' + main['AS'] 552 main['AR'] = main['BATCH_CMD'] + ' ' + main['AR'] 553 main['RANLIB'] = main['BATCH_CMD'] + ' ' + main['RANLIB'] 554 555if sys.platform == 'cygwin': 556 # cygwin has some header file issues... 557 main.Append(CCFLAGS=["-Wno-uninitialized"]) 558 559# Check for SWIG 560if not main.has_key('SWIG'): 561 print 'Error: SWIG utility not found.' 562 print ' Please install (see http://www.swig.org) and retry.' 563 Exit(1) 564 565# Check for appropriate SWIG version 566swig_version = readCommand(('swig', '-version'), exception='').split() 567# First 3 words should be "SWIG Version x.y.z" 568if len(swig_version) < 3 or \ 569 swig_version[0] != 'SWIG' or swig_version[1] != 'Version': 570 print 'Error determining SWIG version.' 571 Exit(1) 572 573min_swig_version = '1.3.28' 574if compareVersions(swig_version[2], min_swig_version) < 0: 575 print 'Error: SWIG version', min_swig_version, 'or newer required.' 576 print ' Installed version:', swig_version[2] 577 Exit(1) 578 579# Set up SWIG flags & scanner 580swig_flags=Split('-c++ -python -modern -templatereduce $_CPPINCFLAGS') 581main.Append(SWIGFLAGS=swig_flags) 582 583# filter out all existing swig scanners, they mess up the dependency 584# stuff for some reason 585scanners = [] 586for scanner in main['SCANNERS']: 587 skeys = scanner.skeys 588 if skeys == '.i': 589 continue 590 591 if isinstance(skeys, (list, tuple)) and '.i' in skeys: 592 continue 593 594 scanners.append(scanner) 595 596# add the new swig scanner that we like better 597from SCons.Scanner import ClassicCPP as CPPScanner 598swig_inc_re = '^[ \t]*[%,#][ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")' 599scanners.append(CPPScanner("SwigScan", [ ".i" ], "CPPPATH", swig_inc_re)) 600 601# replace the scanners list that has what we want 602main['SCANNERS'] = scanners 603 604# Add a custom Check function to the Configure context so that we can 605# figure out if the compiler adds leading underscores to global 606# variables. This is needed for the autogenerated asm files that we 607# use for embedding the python code. 608def CheckLeading(context): 609 context.Message("Checking for leading underscore in global variables...") 610 # 1) Define a global variable called x from asm so the C compiler 611 # won't change the symbol at all. 612 # 2) Declare that variable. 613 # 3) Use the variable 614 # 615 # If the compiler prepends an underscore, this will successfully 616 # link because the external symbol 'x' will be called '_x' which 617 # was defined by the asm statement. If the compiler does not 618 # prepend an underscore, this will not successfully link because 619 # '_x' will have been defined by assembly, while the C portion of 620 # the code will be trying to use 'x' 621 ret = context.TryLink(''' 622 asm(".globl _x; _x: .byte 0"); 623 extern int x; 624 int main() { return x; } 625 ''', extension=".c") 626 context.env.Append(LEADING_UNDERSCORE=ret) 627 context.Result(ret) 628 return ret 629 630# Platform-specific configuration. Note again that we assume that all 631# builds under a given build root run on the same host platform. 632conf = Configure(main, 633 conf_dir = joinpath(build_root, '.scons_config'), 634 log_file = joinpath(build_root, 'scons_config.log'), 635 custom_tests = { 'CheckLeading' : CheckLeading }) 636 637# Check for leading underscores. Don't really need to worry either 638# way so don't need to check the return code. 639conf.CheckLeading() 640 641# Check if we should compile a 64 bit binary on Mac OS X/Darwin 642try: 643 import platform 644 uname = platform.uname() 645 if uname[0] == 'Darwin' and compareVersions(uname[2], '9.0.0') >= 0: 646 if int(readCommand('sysctl -n hw.cpu64bit_capable')[0]): 647 main.Append(CCFLAGS=['-arch', 'x86_64']) 648 main.Append(CFLAGS=['-arch', 'x86_64']) 649 main.Append(LINKFLAGS=['-arch', 'x86_64']) 650 main.Append(ASFLAGS=['-arch', 'x86_64']) 651except: 652 pass 653 654# Recent versions of scons substitute a "Null" object for Configure() 655# when configuration isn't necessary, e.g., if the "--help" option is 656# present. Unfortuantely this Null object always returns false, 657# breaking all our configuration checks. We replace it with our own 658# more optimistic null object that returns True instead. 659if not conf: 660 def NullCheck(*args, **kwargs): 661 return True 662 663 class NullConf: 664 def __init__(self, env): 665 self.env = env 666 def Finish(self): 667 return self.env 668 def __getattr__(self, mname): 669 return NullCheck 670 671 conf = NullConf(main) 672 673# Find Python include and library directories for embedding the 674# interpreter. For consistency, we will use the same Python 675# installation used to run scons (and thus this script). If you want 676# to link in an alternate version, see above for instructions on how 677# to invoke scons with a different copy of the Python interpreter. 678from distutils import sysconfig 679 680py_getvar = sysconfig.get_config_var 681 682py_debug = getattr(sys, 'pydebug', False) 683py_version = 'python' + py_getvar('VERSION') + (py_debug and "_d" or "") 684 685py_general_include = sysconfig.get_python_inc() 686py_platform_include = sysconfig.get_python_inc(plat_specific=True) 687py_includes = [ py_general_include ] 688if py_platform_include != py_general_include: 689 py_includes.append(py_platform_include) 690 691py_lib_path = [ py_getvar('LIBDIR') ] 692# add the prefix/lib/pythonX.Y/config dir, but only if there is no 693# shared library in prefix/lib/. 694if not py_getvar('Py_ENABLE_SHARED'): 695 py_lib_path.append(py_getvar('LIBPL')) 696 697py_libs = [] 698for lib in py_getvar('LIBS').split() + py_getvar('SYSLIBS').split(): 699 if not lib.startswith('-l'): 700 # Python requires some special flags to link (e.g. -framework 701 # common on OS X systems), assume appending preserves order 702 main.Append(LINKFLAGS=[lib]) 703 else: 704 lib = lib[2:] 705 if lib not in py_libs: 706 py_libs.append(lib) 707py_libs.append(py_version) 708 709main.Append(CPPPATH=py_includes) 710main.Append(LIBPATH=py_lib_path) 711 712# Cache build files in the supplied directory. 713if main['M5_BUILD_CACHE']: 714 print 'Using build cache located at', main['M5_BUILD_CACHE'] 715 CacheDir(main['M5_BUILD_CACHE']) 716 717 718# verify that this stuff works 719if not conf.CheckHeader('Python.h', '<>'): 720 print "Error: can't find Python.h header in", py_includes 721 Exit(1) 722 723for lib in py_libs: 724 if not conf.CheckLib(lib): 725 print "Error: can't find library %s required by python" % lib 726 Exit(1) 727 728# On Solaris you need to use libsocket for socket ops 729if not conf.CheckLibWithHeader(None, 'sys/socket.h', 'C++', 'accept(0,0,0);'): 730 if not conf.CheckLibWithHeader('socket', 'sys/socket.h', 'C++', 'accept(0,0,0);'): 731 print "Can't find library with socket calls (e.g. accept())" 732 Exit(1) 733 734# Check for zlib. If the check passes, libz will be automatically 735# added to the LIBS environment variable. 736if not conf.CheckLibWithHeader('z', 'zlib.h', 'C++','zlibVersion();'): 737 print 'Error: did not find needed zlib compression library '\ 738 'and/or zlib.h header file.' 739 print ' Please install zlib and try again.' 740 Exit(1) 741 742# Check for librt. 743have_posix_clock = \ 744 conf.CheckLibWithHeader(None, 'time.h', 'C', 745 'clock_nanosleep(0,0,NULL,NULL);') or \ 746 conf.CheckLibWithHeader('rt', 'time.h', 'C', 747 'clock_nanosleep(0,0,NULL,NULL);') 748 749if not have_posix_clock: 750 print "Can't find library for POSIX clocks." 751 752# Check for <fenv.h> (C99 FP environment control) 753have_fenv = conf.CheckHeader('fenv.h', '<>') 754if not have_fenv: 755 print "Warning: Header file <fenv.h> not found." 756 print " This host has no IEEE FP rounding mode control." 757 758###################################################################### 759# 760# Finish the configuration 761# 762main = conf.Finish() 763 764###################################################################### 765# 766# Collect all non-global variables 767# 768 769# Define the universe of supported ISAs 770all_isa_list = [ ] 771Export('all_isa_list') 772 773class CpuModel(object): 774 '''The CpuModel class encapsulates everything the ISA parser needs to 775 know about a particular CPU model.''' 776 777 # Dict of available CPU model objects. Accessible as CpuModel.dict. 778 dict = {} 779 list = [] 780 defaults = [] 781 782 # Constructor. Automatically adds models to CpuModel.dict. 783 def __init__(self, name, filename, includes, strings, default=False): 784 self.name = name # name of model 785 self.filename = filename # filename for output exec code 786 self.includes = includes # include files needed in exec file 787 # The 'strings' dict holds all the per-CPU symbols we can 788 # substitute into templates etc. 789 self.strings = strings 790 791 # This cpu is enabled by default 792 self.default = default 793 794 # Add self to dict 795 if name in CpuModel.dict: 796 raise AttributeError, "CpuModel '%s' already registered" % name 797 CpuModel.dict[name] = self 798 CpuModel.list.append(name) 799 800Export('CpuModel') 801 802# Sticky variables get saved in the variables file so they persist from 803# one invocation to the next (unless overridden, in which case the new 804# value becomes sticky). 805sticky_vars = Variables(args=ARGUMENTS) 806Export('sticky_vars') 807 808# Sticky variables that should be exported 809export_vars = [] 810Export('export_vars') 811 812# Walk the tree and execute all SConsopts scripts that wil add to the 813# above variables 814if not GetOption('verbose'): 815 print "Reading SConsopts" 816for bdir in [ base_dir ] + extras_dir_list: 817 if not isdir(bdir): 818 print "Error: directory '%s' does not exist" % bdir 819 Exit(1) 820 for root, dirs, files in os.walk(bdir): 821 if 'SConsopts' in files: 822 if GetOption('verbose'): 823 print "Reading", joinpath(root, 'SConsopts') 824 SConscript(joinpath(root, 'SConsopts')) 825 826all_isa_list.sort() 827 828sticky_vars.AddVariables( 829 EnumVariable('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list), 830 ListVariable('CPU_MODELS', 'CPU models', 831 sorted(n for n,m in CpuModel.dict.iteritems() if m.default), 832 sorted(CpuModel.list)), 833 BoolVariable('NO_FAST_ALLOC', 'Disable fast object allocator', False), 834 BoolVariable('FORCE_FAST_ALLOC', 835 'Enable fast object allocator, even for gem5.debug', False), 836 BoolVariable('FAST_ALLOC_STATS', 'Enable fast object allocator statistics', 837 False), 838 BoolVariable('EFENCE', 'Link with Electric Fence malloc debugger', 839 False), 840 BoolVariable('SS_COMPATIBLE_FP', 841 'Make floating-point results compatible with SimpleScalar', 842 False), 843 BoolVariable('USE_SSE2', 844 'Compile for SSE2 (-msse2) to get IEEE FP on x86 hosts', 845 False), 846 BoolVariable('USE_POSIX_CLOCK', 'Use POSIX Clocks', have_posix_clock), 847 BoolVariable('USE_FENV', 'Use <fenv.h> IEEE mode control', have_fenv), 848 BoolVariable('USE_CHECKER', 'Use checker for detailed CPU models', False), 849 BoolVariable('CP_ANNOTATE', 'Enable critical path annotation capability', False), 850 ) 851 852# These variables get exported to #defines in config/*.hh (see src/SConscript). 853export_vars += ['USE_FENV', 'NO_FAST_ALLOC', 'FORCE_FAST_ALLOC', 854 'FAST_ALLOC_STATS', 'SS_COMPATIBLE_FP', 'USE_CHECKER', 855 'TARGET_ISA', 'CP_ANNOTATE', 'USE_POSIX_CLOCK' ] 856 857################################################### 858# 859# Define a SCons builder for configuration flag headers. 860# 861################################################### 862 863# This function generates a config header file that #defines the 864# variable symbol to the current variable setting (0 or 1). The source 865# operands are the name of the variable and a Value node containing the 866# value of the variable. 867def build_config_file(target, source, env): 868 (variable, value) = [s.get_contents() for s in source] 869 f = file(str(target[0]), 'w') 870 print >> f, '#define', variable, value 871 f.close() 872 return None 873 874# Combine the two functions into a scons Action object. 875config_action = MakeAction(build_config_file, Transform("CONFIG H", 2)) 876 877# The emitter munges the source & target node lists to reflect what 878# we're really doing. 879def config_emitter(target, source, env): 880 # extract variable name from Builder arg 881 variable = str(target[0]) 882 # True target is config header file 883 target = joinpath('config', variable.lower() + '.hh') 884 val = env[variable] 885 if isinstance(val, bool): 886 # Force value to 0/1 887 val = int(val) 888 elif isinstance(val, str): 889 val = '"' + val + '"' 890 891 # Sources are variable name & value (packaged in SCons Value nodes) 892 return ([target], [Value(variable), Value(val)]) 893 894config_builder = Builder(emitter = config_emitter, action = config_action) 895 896main.Append(BUILDERS = { 'ConfigFile' : config_builder }) 897 898# libelf build is shared across all configs in the build root. 899main.SConscript('ext/libelf/SConscript', 900 variant_dir = joinpath(build_root, 'libelf')) 901 902# gzstream build is shared across all configs in the build root. 903main.SConscript('ext/gzstream/SConscript', 904 variant_dir = joinpath(build_root, 'gzstream')) 905 906################################################### 907# 908# This function is used to set up a directory with switching headers 909# 910################################################### 911 912main['ALL_ISA_LIST'] = all_isa_list 913def make_switching_dir(dname, switch_headers, env): 914 # Generate the header. target[0] is the full path of the output 915 # header to generate. 'source' is a dummy variable, since we get the 916 # list of ISAs from env['ALL_ISA_LIST']. 917 def gen_switch_hdr(target, source, env): 918 fname = str(target[0]) 919 f = open(fname, 'w') 920 isa = env['TARGET_ISA'].lower() 921 print >>f, '#include "%s/%s/%s"' % (dname, isa, basename(fname)) 922 f.close() 923 924 # Build SCons Action object. 'varlist' specifies env vars that this 925 # action depends on; when env['ALL_ISA_LIST'] changes these actions 926 # should get re-executed. 927 switch_hdr_action = MakeAction(gen_switch_hdr, 928 Transform("GENERATE"), varlist=['ALL_ISA_LIST']) 929 930 # Instantiate actions for each header 931 for hdr in switch_headers: 932 env.Command(hdr, [], switch_hdr_action) 933Export('make_switching_dir') 934 935################################################### 936# 937# Define build environments for selected configurations. 938# 939################################################### 940 941for variant_path in variant_paths: 942 print "Building in", variant_path 943 944 # Make a copy of the build-root environment to use for this config. 945 env = main.Clone() 946 env['BUILDDIR'] = variant_path 947 948 # variant_dir is the tail component of build path, and is used to 949 # determine the build parameters (e.g., 'ALPHA_SE') 950 (build_root, variant_dir) = splitpath(variant_path) 951 952 # Set env variables according to the build directory config. 953 sticky_vars.files = [] 954 # Variables for $BUILD_ROOT/$VARIANT_DIR are stored in 955 # $BUILD_ROOT/variables/$VARIANT_DIR so you can nuke 956 # $BUILD_ROOT/$VARIANT_DIR without losing your variables settings. 957 current_vars_file = joinpath(build_root, 'variables', variant_dir) 958 if isfile(current_vars_file): 959 sticky_vars.files.append(current_vars_file) 960 print "Using saved variables file %s" % current_vars_file 961 else: 962 # Build dir-specific variables file doesn't exist. 963 964 # Make sure the directory is there so we can create it later 965 opt_dir = dirname(current_vars_file) 966 if not isdir(opt_dir): 967 mkdir(opt_dir) 968 969 # Get default build variables from source tree. Variables are 970 # normally determined by name of $VARIANT_DIR, but can be 971 # overridden by '--default=' arg on command line. 972 default = GetOption('default') 973 opts_dir = joinpath(main.root.abspath, 'build_opts') 974 if default: 975 default_vars_files = [joinpath(build_root, 'variables', default), 976 joinpath(opts_dir, default)] 977 else: 978 default_vars_files = [joinpath(opts_dir, variant_dir)] 979 existing_files = filter(isfile, default_vars_files) 980 if existing_files: 981 default_vars_file = existing_files[0] 982 sticky_vars.files.append(default_vars_file) 983 print "Variables file %s not found,\n using defaults in %s" \ 984 % (current_vars_file, default_vars_file) 985 else: 986 print "Error: cannot find variables file %s or " \ 987 "default file(s) %s" \ 988 % (current_vars_file, ' or '.join(default_vars_files)) 989 Exit(1) 990 991 # Apply current variable settings to env 992 sticky_vars.Update(env) 993 994 help_texts["local_vars"] += \ 995 "Build variables for %s:\n" % variant_dir \ 996 + sticky_vars.GenerateHelpText(env) 997 998 # Process variable settings. 999 1000 if not have_fenv and env['USE_FENV']: 1001 print "Warning: <fenv.h> not available; " \ 1002 "forcing USE_FENV to False in", variant_dir + "." 1003 env['USE_FENV'] = False 1004 1005 if not env['USE_FENV']: 1006 print "Warning: No IEEE FP rounding mode control in", variant_dir + "." 1007 print " FP results may deviate slightly from other platforms." 1008 1009 if env['EFENCE']: 1010 env.Append(LIBS=['efence']) 1011 1012 # Save sticky variable settings back to current variables file 1013 sticky_vars.Save(current_vars_file, env) 1014 1015 if env['USE_SSE2']: 1016 env.Append(CCFLAGS=['-msse2']) 1017 1018 # The src/SConscript file sets up the build rules in 'env' according 1019 # to the configured variables. It returns a list of environments, 1020 # one for each variant build (debug, opt, etc.) 1021 envList = SConscript('src/SConscript', variant_dir = variant_path, 1022 exports = 'env') 1023 1024 # Set up the regression tests for each build. 1025 for e in envList: 1026 SConscript('tests/SConscript', 1027 variant_dir = joinpath(variant_path, 'tests', e.Label), 1028 exports = { 'env' : e }, duplicate = False) 1029 1030# base help text 1031Help(''' 1032Usage: scons [scons options] [build variables] [target(s)] 1033 1034Extra scons options: 1035%(options)s 1036 1037Global build variables: 1038%(global_vars)s 1039 1040%(local_vars)s 1041''' % help_texts) 1042