SConstruct revision 13706:4c1d26d1766e
1# -*- mode:python -*- 2 3# Copyright (c) 2013, 2015-2017 ARM Limited 4# All rights reserved. 5# 6# The license below extends only to copyright in the software and shall 7# not be construed as granting a license to any other intellectual 8# property including but not limited to intellectual property relating 9# to a hardware implementation of the functionality of the software 10# licensed hereunder. You may use the software subject to the license 11# terms below provided that you ensure that this notice is replicated 12# unmodified and in its entirety in all distributions of the software, 13# modified or unmodified, in source code or in binary form. 14# 15# Copyright (c) 2011 Advanced Micro Devices, Inc. 16# Copyright (c) 2009 The Hewlett-Packard Development Company 17# Copyright (c) 2004-2005 The Regents of The University of Michigan 18# All rights reserved. 19# 20# Redistribution and use in source and binary forms, with or without 21# modification, are permitted provided that the following conditions are 22# met: redistributions of source code must retain the above copyright 23# notice, this list of conditions and the following disclaimer; 24# redistributions in binary form must reproduce the above copyright 25# notice, this list of conditions and the following disclaimer in the 26# documentation and/or other materials provided with the distribution; 27# neither the name of the copyright holders nor the names of its 28# contributors may be used to endorse or promote products derived from 29# this software without specific prior written permission. 30# 31# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 36# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 37# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 38# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 39# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 40# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 41# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42# 43# Authors: Steve Reinhardt 44# Nathan Binkert 45 46################################################### 47# 48# SCons top-level build description (SConstruct) file. 49# 50# While in this directory ('gem5'), just type 'scons' to build the default 51# configuration (see below), or type 'scons build/<CONFIG>/<binary>' 52# to build some other configuration (e.g., 'build/ALPHA/gem5.opt' for 53# the optimized full-system version). 54# 55# You can build gem5 in a different directory as long as there is a 56# 'build/<CONFIG>' somewhere along the target path. The build system 57# expects that all configs under the same build directory are being 58# built for the same host system. 59# 60# Examples: 61# 62# The following two commands are equivalent. The '-u' option tells 63# scons to search up the directory tree for this SConstruct file. 64# % cd <path-to-src>/gem5 ; scons build/ALPHA/gem5.debug 65# % cd <path-to-src>/gem5/build/ALPHA; scons -u gem5.debug 66# 67# The following two commands are equivalent and demonstrate building 68# in a directory outside of the source tree. The '-C' option tells 69# scons to chdir to the specified directory to find this SConstruct 70# file. 71# % cd <path-to-src>/gem5 ; scons /local/foo/build/ALPHA/gem5.debug 72# % cd /local/foo/build/ALPHA; scons -C <path-to-src>/gem5 gem5.debug 73# 74# You can use 'scons -H' to print scons options. If you're in this 75# 'gem5' directory (or use -u or -C to tell scons where to find this 76# file), you can use 'scons -h' to print all the gem5-specific build 77# options as well. 78# 79################################################### 80 81from __future__ import print_function 82 83# Global Python includes 84import itertools 85import os 86import re 87import shutil 88import subprocess 89import sys 90 91from os import mkdir, environ 92from os.path import abspath, basename, dirname, expanduser, normpath 93from os.path import exists, isdir, isfile 94from os.path import join as joinpath, split as splitpath 95from re import match 96 97# SCons includes 98import SCons 99import SCons.Node 100 101from m5.util import compareVersions, readCommand 102 103help_texts = { 104 "options" : "", 105 "global_vars" : "", 106 "local_vars" : "" 107} 108 109Export("help_texts") 110 111 112# There's a bug in scons in that (1) by default, the help texts from 113# AddOption() are supposed to be displayed when you type 'scons -h' 114# and (2) you can override the help displayed by 'scons -h' using the 115# Help() function, but these two features are incompatible: once 116# you've overridden the help text using Help(), there's no way to get 117# at the help texts from AddOptions. See: 118# http://scons.tigris.org/issues/show_bug.cgi?id=2356 119# http://scons.tigris.org/issues/show_bug.cgi?id=2611 120# This hack lets us extract the help text from AddOptions and 121# re-inject it via Help(). Ideally someday this bug will be fixed and 122# we can just use AddOption directly. 123def AddLocalOption(*args, **kwargs): 124 col_width = 30 125 126 help = " " + ", ".join(args) 127 if "help" in kwargs: 128 length = len(help) 129 if length >= col_width: 130 help += "\n" + " " * col_width 131 else: 132 help += " " * (col_width - length) 133 help += kwargs["help"] 134 help_texts["options"] += help + "\n" 135 136 AddOption(*args, **kwargs) 137 138AddLocalOption('--colors', dest='use_colors', action='store_true', 139 help="Add color to abbreviated scons output") 140AddLocalOption('--no-colors', dest='use_colors', action='store_false', 141 help="Don't add color to abbreviated scons output") 142AddLocalOption('--with-cxx-config', dest='with_cxx_config', 143 action='store_true', 144 help="Build with support for C++-based configuration") 145AddLocalOption('--default', dest='default', type='string', action='store', 146 help='Override which build_opts file to use for defaults') 147AddLocalOption('--ignore-style', dest='ignore_style', action='store_true', 148 help='Disable style checking hooks') 149AddLocalOption('--gold-linker', dest='gold_linker', action='store_true', 150 help='Use the gold linker') 151AddLocalOption('--no-lto', dest='no_lto', action='store_true', 152 help='Disable Link-Time Optimization for fast') 153AddLocalOption('--force-lto', dest='force_lto', action='store_true', 154 help='Use Link-Time Optimization instead of partial linking' + 155 ' when the compiler doesn\'t support using them together.') 156AddLocalOption('--update-ref', dest='update_ref', action='store_true', 157 help='Update test reference outputs') 158AddLocalOption('--verbose', dest='verbose', action='store_true', 159 help='Print full tool command lines') 160AddLocalOption('--without-python', dest='without_python', 161 action='store_true', 162 help='Build without Python configuration support') 163AddLocalOption('--without-tcmalloc', dest='without_tcmalloc', 164 action='store_true', 165 help='Disable linking against tcmalloc') 166AddLocalOption('--with-ubsan', dest='with_ubsan', action='store_true', 167 help='Build with Undefined Behavior Sanitizer if available') 168AddLocalOption('--with-asan', dest='with_asan', action='store_true', 169 help='Build with Address Sanitizer if available') 170 171if GetOption('no_lto') and GetOption('force_lto'): 172 print('--no-lto and --force-lto are mutually exclusive') 173 Exit(1) 174 175######################################################################## 176# 177# Set up the main build environment. 178# 179######################################################################## 180 181main = Environment() 182 183from gem5_scons import Transform 184from gem5_scons.util import get_termcap 185termcap = get_termcap() 186 187main_dict_keys = main.Dictionary().keys() 188 189# Check that we have a C/C++ compiler 190if not ('CC' in main_dict_keys and 'CXX' in main_dict_keys): 191 print("No C++ compiler installed (package g++ on Ubuntu and RedHat)") 192 Exit(1) 193 194################################################### 195# 196# Figure out which configurations to set up based on the path(s) of 197# the target(s). 198# 199################################################### 200 201# Find default configuration & binary. 202Default(environ.get('M5_DEFAULT_BINARY', 'build/ALPHA/gem5.debug')) 203 204# helper function: find last occurrence of element in list 205def rfind(l, elt, offs = -1): 206 for i in range(len(l)+offs, 0, -1): 207 if l[i] == elt: 208 return i 209 raise ValueError, "element not found" 210 211# Take a list of paths (or SCons Nodes) and return a list with all 212# paths made absolute and ~-expanded. Paths will be interpreted 213# relative to the launch directory unless a different root is provided 214def makePathListAbsolute(path_list, root=GetLaunchDir()): 215 return [abspath(joinpath(root, expanduser(str(p)))) 216 for p in path_list] 217 218# Each target must have 'build' in the interior of the path; the 219# directory below this will determine the build parameters. For 220# example, for target 'foo/bar/build/ALPHA_SE/arch/alpha/blah.do' we 221# recognize that ALPHA_SE specifies the configuration because it 222# follow 'build' in the build path. 223 224# The funky assignment to "[:]" is needed to replace the list contents 225# in place rather than reassign the symbol to a new list, which 226# doesn't work (obviously!). 227BUILD_TARGETS[:] = makePathListAbsolute(BUILD_TARGETS) 228 229# Generate a list of the unique build roots and configs that the 230# collected targets reference. 231variant_paths = [] 232build_root = None 233for t in BUILD_TARGETS: 234 path_dirs = t.split('/') 235 try: 236 build_top = rfind(path_dirs, 'build', -2) 237 except: 238 print("Error: no non-leaf 'build' dir found on target path", t) 239 Exit(1) 240 this_build_root = joinpath('/',*path_dirs[:build_top+1]) 241 if not build_root: 242 build_root = this_build_root 243 else: 244 if this_build_root != build_root: 245 print("Error: build targets not under same build root\n" 246 " %s\n %s" % (build_root, this_build_root)) 247 Exit(1) 248 variant_path = joinpath('/',*path_dirs[:build_top+2]) 249 if variant_path not in variant_paths: 250 variant_paths.append(variant_path) 251 252# Make sure build_root exists (might not if this is the first build there) 253if not isdir(build_root): 254 mkdir(build_root) 255main['BUILDROOT'] = build_root 256 257Export('main') 258 259main.SConsignFile(joinpath(build_root, "sconsign")) 260 261# Default duplicate option is to use hard links, but this messes up 262# when you use emacs to edit a file in the target dir, as emacs moves 263# file to file~ then copies to file, breaking the link. Symbolic 264# (soft) links work better. 265main.SetOption('duplicate', 'soft-copy') 266 267# 268# Set up global sticky variables... these are common to an entire build 269# tree (not specific to a particular build like ALPHA_SE) 270# 271 272global_vars_file = joinpath(build_root, 'variables.global') 273 274global_vars = Variables(global_vars_file, args=ARGUMENTS) 275 276global_vars.AddVariables( 277 ('CC', 'C compiler', environ.get('CC', main['CC'])), 278 ('CXX', 'C++ compiler', environ.get('CXX', main['CXX'])), 279 ('PROTOC', 'protoc tool', environ.get('PROTOC', 'protoc')), 280 ('BATCH', 'Use batch pool for build and tests', False), 281 ('BATCH_CMD', 'Batch pool submission command name', 'qdo'), 282 ('M5_BUILD_CACHE', 'Cache built objects in this directory', False), 283 ('EXTRAS', 'Add extra directories to the compilation', '') 284 ) 285 286# Update main environment with values from ARGUMENTS & global_vars_file 287global_vars.Update(main) 288help_texts["global_vars"] += global_vars.GenerateHelpText(main) 289 290# Save sticky variable settings back to current variables file 291global_vars.Save(global_vars_file, main) 292 293# Parse EXTRAS variable to build list of all directories where we're 294# look for sources etc. This list is exported as extras_dir_list. 295base_dir = main.srcdir.abspath 296if main['EXTRAS']: 297 extras_dir_list = makePathListAbsolute(main['EXTRAS'].split(':')) 298else: 299 extras_dir_list = [] 300 301Export('base_dir') 302Export('extras_dir_list') 303 304# the ext directory should be on the #includes path 305main.Append(CPPPATH=[Dir('ext')]) 306 307# Add shared top-level headers 308main.Prepend(CPPPATH=Dir('include')) 309 310if GetOption('verbose'): 311 def MakeAction(action, string, *args, **kwargs): 312 return Action(action, *args, **kwargs) 313else: 314 MakeAction = Action 315 main['CCCOMSTR'] = Transform("CC") 316 main['CXXCOMSTR'] = Transform("CXX") 317 main['ASCOMSTR'] = Transform("AS") 318 main['ARCOMSTR'] = Transform("AR", 0) 319 main['LINKCOMSTR'] = Transform("LINK", 0) 320 main['SHLINKCOMSTR'] = Transform("SHLINK", 0) 321 main['RANLIBCOMSTR'] = Transform("RANLIB", 0) 322 main['M4COMSTR'] = Transform("M4") 323 main['SHCCCOMSTR'] = Transform("SHCC") 324 main['SHCXXCOMSTR'] = Transform("SHCXX") 325Export('MakeAction') 326 327# Initialize the Link-Time Optimization (LTO) flags 328main['LTO_CCFLAGS'] = [] 329main['LTO_LDFLAGS'] = [] 330 331# According to the readme, tcmalloc works best if the compiler doesn't 332# assume that we're using the builtin malloc and friends. These flags 333# are compiler-specific, so we need to set them after we detect which 334# compiler we're using. 335main['TCMALLOC_CCFLAGS'] = [] 336 337CXX_version = readCommand([main['CXX'],'--version'], exception=False) 338CXX_V = readCommand([main['CXX'],'-V'], exception=False) 339 340main['GCC'] = CXX_version and CXX_version.find('g++') >= 0 341main['CLANG'] = CXX_version and CXX_version.find('clang') >= 0 342if main['GCC'] + main['CLANG'] > 1: 343 print('Error: How can we have two at the same time?') 344 Exit(1) 345 346# Set up default C++ compiler flags 347if main['GCC'] or main['CLANG']: 348 # As gcc and clang share many flags, do the common parts here 349 main.Append(CCFLAGS=['-pipe']) 350 main.Append(CCFLAGS=['-fno-strict-aliasing']) 351 # Enable -Wall and -Wextra and then disable the few warnings that 352 # we consistently violate 353 main.Append(CCFLAGS=['-Wall', '-Wundef', '-Wextra', 354 '-Wno-sign-compare', '-Wno-unused-parameter']) 355 # We always compile using C++11 356 main.Append(CXXFLAGS=['-std=c++11']) 357 if sys.platform.startswith('freebsd'): 358 main.Append(CCFLAGS=['-I/usr/local/include']) 359 main.Append(CXXFLAGS=['-I/usr/local/include']) 360 361 main['FILTER_PSHLINKFLAGS'] = lambda x: str(x).replace(' -shared', '') 362 main['PSHLINKFLAGS'] = main.subst('${FILTER_PSHLINKFLAGS(SHLINKFLAGS)}') 363 if GetOption('gold_linker'): 364 main.Append(LINKFLAGS='-fuse-ld=gold') 365 main['PLINKFLAGS'] = main.subst('${LINKFLAGS}') 366 shared_partial_flags = ['-r', '-nostdlib'] 367 main.Append(PSHLINKFLAGS=shared_partial_flags) 368 main.Append(PLINKFLAGS=shared_partial_flags) 369 370 # Treat warnings as errors but white list some warnings that we 371 # want to allow (e.g., deprecation warnings). 372 main.Append(CCFLAGS=['-Werror', 373 '-Wno-error=deprecated-declarations', 374 '-Wno-error=deprecated', 375 ]) 376else: 377 print(termcap.Yellow + termcap.Bold + 'Error' + termcap.Normal, end=' ') 378 print("Don't know what compiler options to use for your compiler.") 379 print(termcap.Yellow + ' compiler:' + termcap.Normal, main['CXX']) 380 print(termcap.Yellow + ' version:' + termcap.Normal, end = ' ') 381 if not CXX_version: 382 print(termcap.Yellow + termcap.Bold + "COMMAND NOT FOUND!" + 383 termcap.Normal) 384 else: 385 print(CXX_version.replace('\n', '<nl>')) 386 print(" If you're trying to use a compiler other than GCC") 387 print(" or clang, there appears to be something wrong with your") 388 print(" environment.") 389 print(" ") 390 print(" If you are trying to use a compiler other than those listed") 391 print(" above you will need to ease fix SConstruct and ") 392 print(" src/SConscript to support that compiler.") 393 Exit(1) 394 395if main['GCC']: 396 # Check for a supported version of gcc. >= 4.8 is chosen for its 397 # level of c++11 support. See 398 # http://gcc.gnu.org/projects/cxx0x.html for details. 399 gcc_version = readCommand([main['CXX'], '-dumpversion'], exception=False) 400 if compareVersions(gcc_version, "4.8") < 0: 401 print('Error: gcc version 4.8 or newer required.') 402 print(' Installed version: ', gcc_version) 403 Exit(1) 404 405 main['GCC_VERSION'] = gcc_version 406 407 if compareVersions(gcc_version, '4.9') >= 0: 408 # Incremental linking with LTO is currently broken in gcc versions 409 # 4.9 and above. A version where everything works completely hasn't 410 # yet been identified. 411 # 412 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67548 413 main['BROKEN_INCREMENTAL_LTO'] = True 414 if compareVersions(gcc_version, '6.0') >= 0: 415 # gcc versions 6.0 and greater accept an -flinker-output flag which 416 # selects what type of output the linker should generate. This is 417 # necessary for incremental lto to work, but is also broken in 418 # current versions of gcc. It may not be necessary in future 419 # versions. We add it here since it might be, and as a reminder that 420 # it exists. It's excluded if lto is being forced. 421 # 422 # https://gcc.gnu.org/gcc-6/changes.html 423 # https://gcc.gnu.org/ml/gcc-patches/2015-11/msg03161.html 424 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69866 425 if not GetOption('force_lto'): 426 main.Append(PSHLINKFLAGS='-flinker-output=rel') 427 main.Append(PLINKFLAGS='-flinker-output=rel') 428 429 # Make sure we warn if the user has requested to compile with the 430 # Undefined Benahvior Sanitizer and this version of gcc does not 431 # support it. 432 if GetOption('with_ubsan') and \ 433 compareVersions(gcc_version, '4.9') < 0: 434 print(termcap.Yellow + termcap.Bold + 435 'Warning: UBSan is only supported using gcc 4.9 and later.' + 436 termcap.Normal) 437 438 disable_lto = GetOption('no_lto') 439 if not disable_lto and main.get('BROKEN_INCREMENTAL_LTO', False) and \ 440 not GetOption('force_lto'): 441 print(termcap.Yellow + termcap.Bold + 442 'Warning: Your compiler doesn\'t support incremental linking' + 443 ' and lto at the same time, so lto is being disabled. To force' + 444 ' lto on anyway, use the --force-lto option. That will disable' + 445 ' partial linking.' + 446 termcap.Normal) 447 disable_lto = True 448 449 # Add the appropriate Link-Time Optimization (LTO) flags 450 # unless LTO is explicitly turned off. Note that these flags 451 # are only used by the fast target. 452 if not disable_lto: 453 # Pass the LTO flag when compiling to produce GIMPLE 454 # output, we merely create the flags here and only append 455 # them later 456 main['LTO_CCFLAGS'] = ['-flto=%d' % GetOption('num_jobs')] 457 458 # Use the same amount of jobs for LTO as we are running 459 # scons with 460 main['LTO_LDFLAGS'] = ['-flto=%d' % GetOption('num_jobs')] 461 462 main.Append(TCMALLOC_CCFLAGS=['-fno-builtin-malloc', '-fno-builtin-calloc', 463 '-fno-builtin-realloc', '-fno-builtin-free']) 464 465 # The address sanitizer is available for gcc >= 4.8 466 if GetOption('with_asan'): 467 if GetOption('with_ubsan') and \ 468 compareVersions(main['GCC_VERSION'], '4.9') >= 0: 469 main.Append(CCFLAGS=['-fsanitize=address,undefined', 470 '-fno-omit-frame-pointer'], 471 LINKFLAGS='-fsanitize=address,undefined') 472 else: 473 main.Append(CCFLAGS=['-fsanitize=address', 474 '-fno-omit-frame-pointer'], 475 LINKFLAGS='-fsanitize=address') 476 # Only gcc >= 4.9 supports UBSan, so check both the version 477 # and the command-line option before adding the compiler and 478 # linker flags. 479 elif GetOption('with_ubsan') and \ 480 compareVersions(main['GCC_VERSION'], '4.9') >= 0: 481 main.Append(CCFLAGS='-fsanitize=undefined') 482 main.Append(LINKFLAGS='-fsanitize=undefined') 483 484elif main['CLANG']: 485 # Check for a supported version of clang, >= 3.1 is needed to 486 # support similar features as gcc 4.8. See 487 # http://clang.llvm.org/cxx_status.html for details 488 clang_version_re = re.compile(".* version (\d+\.\d+)") 489 clang_version_match = clang_version_re.search(CXX_version) 490 if (clang_version_match): 491 clang_version = clang_version_match.groups()[0] 492 if compareVersions(clang_version, "3.1") < 0: 493 print('Error: clang version 3.1 or newer required.') 494 print(' Installed version:', clang_version) 495 Exit(1) 496 else: 497 print('Error: Unable to determine clang version.') 498 Exit(1) 499 500 # clang has a few additional warnings that we disable, extraneous 501 # parantheses are allowed due to Ruby's printing of the AST, 502 # finally self assignments are allowed as the generated CPU code 503 # is relying on this 504 main.Append(CCFLAGS=['-Wno-parentheses', 505 '-Wno-self-assign', 506 # Some versions of libstdc++ (4.8?) seem to 507 # use struct hash and class hash 508 # interchangeably. 509 '-Wno-mismatched-tags', 510 ]) 511 512 main.Append(TCMALLOC_CCFLAGS=['-fno-builtin']) 513 514 # On Mac OS X/Darwin we need to also use libc++ (part of XCode) as 515 # opposed to libstdc++, as the later is dated. 516 if sys.platform == "darwin": 517 main.Append(CXXFLAGS=['-stdlib=libc++']) 518 main.Append(LIBS=['c++']) 519 520 # On FreeBSD we need libthr. 521 if sys.platform.startswith('freebsd'): 522 main.Append(LIBS=['thr']) 523 524 # We require clang >= 3.1, so there is no need to check any 525 # versions here. 526 if GetOption('with_ubsan'): 527 if GetOption('with_asan'): 528 main.Append(CCFLAGS=['-fsanitize=address,undefined', 529 '-fno-omit-frame-pointer'], 530 LINKFLAGS='-fsanitize=address,undefined') 531 else: 532 main.Append(CCFLAGS='-fsanitize=undefined', 533 LINKFLAGS='-fsanitize=undefined') 534 535 elif GetOption('with_asan'): 536 main.Append(CCFLAGS=['-fsanitize=address', 537 '-fno-omit-frame-pointer'], 538 LINKFLAGS='-fsanitize=address') 539 540else: 541 print(termcap.Yellow + termcap.Bold + 'Error' + termcap.Normal, end=' ') 542 print("Don't know what compiler options to use for your compiler.") 543 print(termcap.Yellow + ' compiler:' + termcap.Normal, main['CXX']) 544 print(termcap.Yellow + ' version:' + termcap.Normal, end=' ') 545 if not CXX_version: 546 print(termcap.Yellow + termcap.Bold + "COMMAND NOT FOUND!" + 547 termcap.Normal) 548 else: 549 print(CXX_version.replace('\n', '<nl>')) 550 print(" If you're trying to use a compiler other than GCC") 551 print(" or clang, there appears to be something wrong with your") 552 print(" environment.") 553 print(" ") 554 print(" If you are trying to use a compiler other than those listed") 555 print(" above you will need to ease fix SConstruct and ") 556 print(" src/SConscript to support that compiler.") 557 Exit(1) 558 559# Set up common yacc/bison flags (needed for Ruby) 560main['YACCFLAGS'] = '-d' 561main['YACCHXXFILESUFFIX'] = '.hh' 562 563# Do this after we save setting back, or else we'll tack on an 564# extra 'qdo' every time we run scons. 565if main['BATCH']: 566 main['CC'] = main['BATCH_CMD'] + ' ' + main['CC'] 567 main['CXX'] = main['BATCH_CMD'] + ' ' + main['CXX'] 568 main['AS'] = main['BATCH_CMD'] + ' ' + main['AS'] 569 main['AR'] = main['BATCH_CMD'] + ' ' + main['AR'] 570 main['RANLIB'] = main['BATCH_CMD'] + ' ' + main['RANLIB'] 571 572if sys.platform == 'cygwin': 573 # cygwin has some header file issues... 574 main.Append(CCFLAGS=["-Wno-uninitialized"]) 575 576# Check for the protobuf compiler 577protoc_version = readCommand([main['PROTOC'], '--version'], 578 exception='').split() 579 580# First two words should be "libprotoc x.y.z" 581if len(protoc_version) < 2 or protoc_version[0] != 'libprotoc': 582 print(termcap.Yellow + termcap.Bold + 583 'Warning: Protocol buffer compiler (protoc) not found.\n' + 584 ' Please install protobuf-compiler for tracing support.' + 585 termcap.Normal) 586 main['PROTOC'] = False 587else: 588 # Based on the availability of the compress stream wrappers, 589 # require 2.1.0 590 min_protoc_version = '2.1.0' 591 if compareVersions(protoc_version[1], min_protoc_version) < 0: 592 print(termcap.Yellow + termcap.Bold + 593 'Warning: protoc version', min_protoc_version, 594 'or newer required.\n' + 595 ' Installed version:', protoc_version[1], 596 termcap.Normal) 597 main['PROTOC'] = False 598 else: 599 # Attempt to determine the appropriate include path and 600 # library path using pkg-config, that means we also need to 601 # check for pkg-config. Note that it is possible to use 602 # protobuf without the involvement of pkg-config. Later on we 603 # check go a library config check and at that point the test 604 # will fail if libprotobuf cannot be found. 605 if readCommand(['pkg-config', '--version'], exception=''): 606 try: 607 # Attempt to establish what linking flags to add for protobuf 608 # using pkg-config 609 main.ParseConfig('pkg-config --cflags --libs-only-L protobuf') 610 except: 611 print(termcap.Yellow + termcap.Bold + 612 'Warning: pkg-config could not get protobuf flags.' + 613 termcap.Normal) 614 615 616# Check for 'timeout' from GNU coreutils. If present, regressions will 617# be run with a time limit. We require version 8.13 since we rely on 618# support for the '--foreground' option. 619if sys.platform.startswith('freebsd'): 620 timeout_lines = readCommand(['gtimeout', '--version'], 621 exception='').splitlines() 622else: 623 timeout_lines = readCommand(['timeout', '--version'], 624 exception='').splitlines() 625# Get the first line and tokenize it 626timeout_version = timeout_lines[0].split() if timeout_lines else [] 627main['TIMEOUT'] = timeout_version and \ 628 compareVersions(timeout_version[-1], '8.13') >= 0 629 630# Add a custom Check function to test for structure members. 631def CheckMember(context, include, decl, member, include_quotes="<>"): 632 context.Message("Checking for member %s in %s..." % 633 (member, decl)) 634 text = """ 635#include %(header)s 636int main(){ 637 %(decl)s test; 638 (void)test.%(member)s; 639 return 0; 640}; 641""" % { "header" : include_quotes[0] + include + include_quotes[1], 642 "decl" : decl, 643 "member" : member, 644 } 645 646 ret = context.TryCompile(text, extension=".cc") 647 context.Result(ret) 648 return ret 649 650# Platform-specific configuration. Note again that we assume that all 651# builds under a given build root run on the same host platform. 652conf = Configure(main, 653 conf_dir = joinpath(build_root, '.scons_config'), 654 log_file = joinpath(build_root, 'scons_config.log'), 655 custom_tests = { 656 'CheckMember' : CheckMember, 657 }) 658 659# Check if we should compile a 64 bit binary on Mac OS X/Darwin 660try: 661 import platform 662 uname = platform.uname() 663 if uname[0] == 'Darwin' and compareVersions(uname[2], '9.0.0') >= 0: 664 if int(readCommand('sysctl -n hw.cpu64bit_capable')[0]): 665 main.Append(CCFLAGS=['-arch', 'x86_64']) 666 main.Append(CFLAGS=['-arch', 'x86_64']) 667 main.Append(LINKFLAGS=['-arch', 'x86_64']) 668 main.Append(ASFLAGS=['-arch', 'x86_64']) 669except: 670 pass 671 672# Recent versions of scons substitute a "Null" object for Configure() 673# when configuration isn't necessary, e.g., if the "--help" option is 674# present. Unfortuantely this Null object always returns false, 675# breaking all our configuration checks. We replace it with our own 676# more optimistic null object that returns True instead. 677if not conf: 678 def NullCheck(*args, **kwargs): 679 return True 680 681 class NullConf: 682 def __init__(self, env): 683 self.env = env 684 def Finish(self): 685 return self.env 686 def __getattr__(self, mname): 687 return NullCheck 688 689 conf = NullConf(main) 690 691# Cache build files in the supplied directory. 692if main['M5_BUILD_CACHE']: 693 print('Using build cache located at', main['M5_BUILD_CACHE']) 694 CacheDir(main['M5_BUILD_CACHE']) 695 696main['USE_PYTHON'] = not GetOption('without_python') 697if main['USE_PYTHON']: 698 # Find Python include and library directories for embedding the 699 # interpreter. We rely on python-config to resolve the appropriate 700 # includes and linker flags. ParseConfig does not seem to understand 701 # the more exotic linker flags such as -Xlinker and -export-dynamic so 702 # we add them explicitly below. If you want to link in an alternate 703 # version of python, see above for instructions on how to invoke 704 # scons with the appropriate PATH set. 705 # 706 # First we check if python2-config exists, else we use python-config 707 python_config = readCommand(['which', 'python2-config'], 708 exception='').strip() 709 if not os.path.exists(python_config): 710 python_config = readCommand(['which', 'python-config'], 711 exception='').strip() 712 py_includes = readCommand([python_config, '--includes'], 713 exception='').split() 714 py_includes = filter(lambda s: match(r'.*\/include\/.*',s), py_includes) 715 # Strip the -I from the include folders before adding them to the 716 # CPPPATH 717 py_includes = map(lambda s: s[2:] if s.startswith('-I') else s, py_includes) 718 main.Append(CPPPATH=py_includes) 719 720 # Read the linker flags and split them into libraries and other link 721 # flags. The libraries are added later through the call the CheckLib. 722 py_ld_flags = readCommand([python_config, '--ldflags'], 723 exception='').split() 724 py_libs = [] 725 for lib in py_ld_flags: 726 if not lib.startswith('-l'): 727 main.Append(LINKFLAGS=[lib]) 728 else: 729 lib = lib[2:] 730 if lib not in py_libs: 731 py_libs.append(lib) 732 733 # verify that this stuff works 734 if not conf.CheckHeader('Python.h', '<>'): 735 print("Error: Check failed for Python.h header in", py_includes) 736 print("Two possible reasons:") 737 print("1. Python headers are not installed (You can install the " 738 "package python-dev on Ubuntu and RedHat)") 739 print("2. SCons is using a wrong C compiler. This can happen if " 740 "CC has the wrong value.") 741 print("CC = %s" % main['CC']) 742 Exit(1) 743 744 for lib in py_libs: 745 if not conf.CheckLib(lib): 746 print("Error: can't find library %s required by python" % lib) 747 Exit(1) 748 749# On Solaris you need to use libsocket for socket ops 750if not conf.CheckLibWithHeader(None, 'sys/socket.h', 'C++', 'accept(0,0,0);'): 751 if not conf.CheckLibWithHeader('socket', 'sys/socket.h', 'C++', 'accept(0,0,0);'): 752 print("Can't find library with socket calls (e.g. accept())") 753 Exit(1) 754 755# Check for zlib. If the check passes, libz will be automatically 756# added to the LIBS environment variable. 757if not conf.CheckLibWithHeader('z', 'zlib.h', 'C++','zlibVersion();'): 758 print('Error: did not find needed zlib compression library ' 759 'and/or zlib.h header file.') 760 print(' Please install zlib and try again.') 761 Exit(1) 762 763# If we have the protobuf compiler, also make sure we have the 764# development libraries. If the check passes, libprotobuf will be 765# automatically added to the LIBS environment variable. After 766# this, we can use the HAVE_PROTOBUF flag to determine if we have 767# got both protoc and libprotobuf available. 768main['HAVE_PROTOBUF'] = main['PROTOC'] and \ 769 conf.CheckLibWithHeader('protobuf', 'google/protobuf/message.h', 770 'C++', 'GOOGLE_PROTOBUF_VERIFY_VERSION;') 771 772# Valgrind gets much less confused if you tell it when you're using 773# alternative stacks. 774main['HAVE_VALGRIND'] = conf.CheckCHeader('valgrind/valgrind.h') 775 776# If we have the compiler but not the library, print another warning. 777if main['PROTOC'] and not main['HAVE_PROTOBUF']: 778 print(termcap.Yellow + termcap.Bold + 779 'Warning: did not find protocol buffer library and/or headers.\n' + 780 ' Please install libprotobuf-dev for tracing support.' + 781 termcap.Normal) 782 783# Check for librt. 784have_posix_clock = \ 785 conf.CheckLibWithHeader(None, 'time.h', 'C', 786 'clock_nanosleep(0,0,NULL,NULL);') or \ 787 conf.CheckLibWithHeader('rt', 'time.h', 'C', 788 'clock_nanosleep(0,0,NULL,NULL);') 789 790have_posix_timers = \ 791 conf.CheckLibWithHeader([None, 'rt'], [ 'time.h', 'signal.h' ], 'C', 792 'timer_create(CLOCK_MONOTONIC, NULL, NULL);') 793 794if not GetOption('without_tcmalloc'): 795 if conf.CheckLib('tcmalloc'): 796 main.Append(CCFLAGS=main['TCMALLOC_CCFLAGS']) 797 elif conf.CheckLib('tcmalloc_minimal'): 798 main.Append(CCFLAGS=main['TCMALLOC_CCFLAGS']) 799 else: 800 print(termcap.Yellow + termcap.Bold + 801 "You can get a 12% performance improvement by " 802 "installing tcmalloc (libgoogle-perftools-dev package " 803 "on Ubuntu or RedHat)." + termcap.Normal) 804 805 806# Detect back trace implementations. The last implementation in the 807# list will be used by default. 808backtrace_impls = [ "none" ] 809 810backtrace_checker = 'char temp;' + \ 811 ' backtrace_symbols_fd((void*)&temp, 0, 0);' 812if conf.CheckLibWithHeader(None, 'execinfo.h', 'C', backtrace_checker): 813 backtrace_impls.append("glibc") 814elif conf.CheckLibWithHeader('execinfo', 'execinfo.h', 'C', 815 backtrace_checker): 816 # NetBSD and FreeBSD need libexecinfo. 817 backtrace_impls.append("glibc") 818 main.Append(LIBS=['execinfo']) 819 820if backtrace_impls[-1] == "none": 821 default_backtrace_impl = "none" 822 print(termcap.Yellow + termcap.Bold + 823 "No suitable back trace implementation found." + 824 termcap.Normal) 825 826if not have_posix_clock: 827 print("Can't find library for POSIX clocks.") 828 829# Check for <fenv.h> (C99 FP environment control) 830have_fenv = conf.CheckHeader('fenv.h', '<>') 831if not have_fenv: 832 print("Warning: Header file <fenv.h> not found.") 833 print(" This host has no IEEE FP rounding mode control.") 834 835# Check for <png.h> (libpng library needed if wanting to dump 836# frame buffer image in png format) 837have_png = conf.CheckHeader('png.h', '<>') 838if not have_png: 839 print("Warning: Header file <png.h> not found.") 840 print(" This host has no libpng library.") 841 print(" Disabling support for PNG framebuffers.") 842 843# Check if we should enable KVM-based hardware virtualization. The API 844# we rely on exists since version 2.6.36 of the kernel, but somehow 845# the KVM_API_VERSION does not reflect the change. We test for one of 846# the types as a fall back. 847have_kvm = conf.CheckHeader('linux/kvm.h', '<>') 848if not have_kvm: 849 print("Info: Compatible header file <linux/kvm.h> not found, " 850 "disabling KVM support.") 851 852# Check if the TUN/TAP driver is available. 853have_tuntap = conf.CheckHeader('linux/if_tun.h', '<>') 854if not have_tuntap: 855 print("Info: Compatible header file <linux/if_tun.h> not found.") 856 857# x86 needs support for xsave. We test for the structure here since we 858# won't be able to run new tests by the time we know which ISA we're 859# targeting. 860have_kvm_xsave = conf.CheckTypeSize('struct kvm_xsave', 861 '#include <linux/kvm.h>') != 0 862 863# Check if the requested target ISA is compatible with the host 864def is_isa_kvm_compatible(isa): 865 try: 866 import platform 867 host_isa = platform.machine() 868 except: 869 print("Warning: Failed to determine host ISA.") 870 return False 871 872 if not have_posix_timers: 873 print("Warning: Can not enable KVM, host seems to lack support " 874 "for POSIX timers") 875 return False 876 877 if isa == "arm": 878 return host_isa in ( "armv7l", "aarch64" ) 879 elif isa == "x86": 880 if host_isa != "x86_64": 881 return False 882 883 if not have_kvm_xsave: 884 print("KVM on x86 requires xsave support in kernel headers.") 885 return False 886 887 return True 888 else: 889 return False 890 891 892# Check if the exclude_host attribute is available. We want this to 893# get accurate instruction counts in KVM. 894main['HAVE_PERF_ATTR_EXCLUDE_HOST'] = conf.CheckMember( 895 'linux/perf_event.h', 'struct perf_event_attr', 'exclude_host') 896 897 898###################################################################### 899# 900# Finish the configuration 901# 902main = conf.Finish() 903 904###################################################################### 905# 906# Collect all non-global variables 907# 908 909# Define the universe of supported ISAs 910all_isa_list = [ ] 911all_gpu_isa_list = [ ] 912Export('all_isa_list') 913Export('all_gpu_isa_list') 914 915class CpuModel(object): 916 '''The CpuModel class encapsulates everything the ISA parser needs to 917 know about a particular CPU model.''' 918 919 # Dict of available CPU model objects. Accessible as CpuModel.dict. 920 dict = {} 921 922 # Constructor. Automatically adds models to CpuModel.dict. 923 def __init__(self, name, default=False): 924 self.name = name # name of model 925 926 # This cpu is enabled by default 927 self.default = default 928 929 # Add self to dict 930 if name in CpuModel.dict: 931 raise AttributeError, "CpuModel '%s' already registered" % name 932 CpuModel.dict[name] = self 933 934Export('CpuModel') 935 936# Sticky variables get saved in the variables file so they persist from 937# one invocation to the next (unless overridden, in which case the new 938# value becomes sticky). 939sticky_vars = Variables(args=ARGUMENTS) 940Export('sticky_vars') 941 942# Sticky variables that should be exported 943export_vars = [] 944Export('export_vars') 945 946# For Ruby 947all_protocols = [] 948Export('all_protocols') 949protocol_dirs = [] 950Export('protocol_dirs') 951slicc_includes = [] 952Export('slicc_includes') 953 954# Walk the tree and execute all SConsopts scripts that wil add to the 955# above variables 956if GetOption('verbose'): 957 print("Reading SConsopts") 958for bdir in [ base_dir ] + extras_dir_list: 959 if not isdir(bdir): 960 print("Error: directory '%s' does not exist" % bdir) 961 Exit(1) 962 for root, dirs, files in os.walk(bdir): 963 if 'SConsopts' in files: 964 if GetOption('verbose'): 965 print("Reading", joinpath(root, 'SConsopts')) 966 SConscript(joinpath(root, 'SConsopts')) 967 968all_isa_list.sort() 969all_gpu_isa_list.sort() 970 971sticky_vars.AddVariables( 972 EnumVariable('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list), 973 EnumVariable('TARGET_GPU_ISA', 'Target GPU ISA', 'hsail', all_gpu_isa_list), 974 ListVariable('CPU_MODELS', 'CPU models', 975 sorted(n for n,m in CpuModel.dict.iteritems() if m.default), 976 sorted(CpuModel.dict.keys())), 977 BoolVariable('EFENCE', 'Link with Electric Fence malloc debugger', 978 False), 979 BoolVariable('SS_COMPATIBLE_FP', 980 'Make floating-point results compatible with SimpleScalar', 981 False), 982 BoolVariable('USE_SSE2', 983 'Compile for SSE2 (-msse2) to get IEEE FP on x86 hosts', 984 False), 985 BoolVariable('USE_POSIX_CLOCK', 'Use POSIX Clocks', have_posix_clock), 986 BoolVariable('USE_FENV', 'Use <fenv.h> IEEE mode control', have_fenv), 987 BoolVariable('USE_PNG', 'Enable support for PNG images', have_png), 988 BoolVariable('CP_ANNOTATE', 'Enable critical path annotation capability', 989 False), 990 BoolVariable('USE_KVM', 'Enable hardware virtualized (KVM) CPU models', 991 have_kvm), 992 BoolVariable('USE_TUNTAP', 993 'Enable using a tap device to bridge to the host network', 994 have_tuntap), 995 BoolVariable('BUILD_GPU', 'Build the compute-GPU model', False), 996 EnumVariable('PROTOCOL', 'Coherence protocol for Ruby', 'None', 997 all_protocols), 998 EnumVariable('BACKTRACE_IMPL', 'Post-mortem dump implementation', 999 backtrace_impls[-1], backtrace_impls) 1000 ) 1001 1002# These variables get exported to #defines in config/*.hh (see src/SConscript). 1003export_vars += ['USE_FENV', 'SS_COMPATIBLE_FP', 'TARGET_ISA', 'TARGET_GPU_ISA', 1004 'CP_ANNOTATE', 'USE_POSIX_CLOCK', 'USE_KVM', 'USE_TUNTAP', 1005 'PROTOCOL', 'HAVE_PROTOBUF', 'HAVE_VALGRIND', 1006 'HAVE_PERF_ATTR_EXCLUDE_HOST', 'USE_PNG'] 1007 1008################################################### 1009# 1010# Define a SCons builder for configuration flag headers. 1011# 1012################################################### 1013 1014# This function generates a config header file that #defines the 1015# variable symbol to the current variable setting (0 or 1). The source 1016# operands are the name of the variable and a Value node containing the 1017# value of the variable. 1018def build_config_file(target, source, env): 1019 (variable, value) = [s.get_contents() for s in source] 1020 f = file(str(target[0]), 'w') 1021 print('#define', variable, value, file=f) 1022 f.close() 1023 return None 1024 1025# Combine the two functions into a scons Action object. 1026config_action = MakeAction(build_config_file, Transform("CONFIG H", 2)) 1027 1028# The emitter munges the source & target node lists to reflect what 1029# we're really doing. 1030def config_emitter(target, source, env): 1031 # extract variable name from Builder arg 1032 variable = str(target[0]) 1033 # True target is config header file 1034 target = joinpath('config', variable.lower() + '.hh') 1035 val = env[variable] 1036 if isinstance(val, bool): 1037 # Force value to 0/1 1038 val = int(val) 1039 elif isinstance(val, str): 1040 val = '"' + val + '"' 1041 1042 # Sources are variable name & value (packaged in SCons Value nodes) 1043 return ([target], [Value(variable), Value(val)]) 1044 1045config_builder = Builder(emitter = config_emitter, action = config_action) 1046 1047main.Append(BUILDERS = { 'ConfigFile' : config_builder }) 1048 1049################################################### 1050# 1051# Builders for static and shared partially linked object files. 1052# 1053################################################### 1054 1055partial_static_builder = Builder(action=SCons.Defaults.LinkAction, 1056 src_suffix='$OBJSUFFIX', 1057 src_builder=['StaticObject', 'Object'], 1058 LINKFLAGS='$PLINKFLAGS', 1059 LIBS='') 1060 1061def partial_shared_emitter(target, source, env): 1062 for tgt in target: 1063 tgt.attributes.shared = 1 1064 return (target, source) 1065partial_shared_builder = Builder(action=SCons.Defaults.ShLinkAction, 1066 emitter=partial_shared_emitter, 1067 src_suffix='$SHOBJSUFFIX', 1068 src_builder='SharedObject', 1069 SHLINKFLAGS='$PSHLINKFLAGS', 1070 LIBS='') 1071 1072main.Append(BUILDERS = { 'PartialShared' : partial_shared_builder, 1073 'PartialStatic' : partial_static_builder }) 1074 1075def add_local_rpath(env, *targets): 1076 '''Set up an RPATH for a library which lives in the build directory. 1077 1078 The construction environment variable BIN_RPATH_PREFIX should be set to 1079 the relative path of the build directory starting from the location of the 1080 binary.''' 1081 for target in targets: 1082 target = env.Entry(target) 1083 if not target.isdir(): 1084 target = target.dir 1085 relpath = os.path.relpath(target.abspath, env['BUILDDIR']) 1086 components = [ 1087 '\\$$ORIGIN', 1088 '${BIN_RPATH_PREFIX}', 1089 relpath 1090 ] 1091 env.Append(RPATH=[env.Literal(os.path.join(*components))]) 1092 1093main.Append(LINKFLAGS=Split('-z origin')) 1094main.AddMethod(add_local_rpath, 'AddLocalRPATH') 1095 1096# builds in ext are shared across all configs in the build root. 1097ext_dir = abspath(joinpath(str(main.root), 'ext')) 1098ext_build_dirs = [] 1099for root, dirs, files in os.walk(ext_dir): 1100 if 'SConscript' in files: 1101 build_dir = os.path.relpath(root, ext_dir) 1102 ext_build_dirs.append(build_dir) 1103 main.SConscript(joinpath(root, 'SConscript'), 1104 variant_dir=joinpath(build_root, build_dir)) 1105 1106gdb_xml_dir = joinpath(ext_dir, 'gdb-xml') 1107Export('gdb_xml_dir') 1108 1109main.Prepend(CPPPATH=Dir('ext/pybind11/include/')) 1110 1111################################################### 1112# 1113# This builder and wrapper method are used to set up a directory with 1114# switching headers. Those are headers which are in a generic location and 1115# that include more specific headers from a directory chosen at build time 1116# based on the current build settings. 1117# 1118################################################### 1119 1120def build_switching_header(target, source, env): 1121 path = str(target[0]) 1122 subdir = str(source[0]) 1123 dp, fp = os.path.split(path) 1124 dp = os.path.relpath(os.path.realpath(dp), 1125 os.path.realpath(env['BUILDDIR'])) 1126 with open(path, 'w') as hdr: 1127 print('#include "%s/%s/%s"' % (dp, subdir, fp), file=hdr) 1128 1129switching_header_action = MakeAction(build_switching_header, 1130 Transform('GENERATE')) 1131 1132switching_header_builder = Builder(action=switching_header_action, 1133 source_factory=Value, 1134 single_source=True) 1135 1136main.Append(BUILDERS = { 'SwitchingHeader': switching_header_builder }) 1137 1138def switching_headers(self, headers, source): 1139 for header in headers: 1140 self.SwitchingHeader(header, source) 1141 1142main.AddMethod(switching_headers, 'SwitchingHeaders') 1143 1144################################################### 1145# 1146# Define build environments for selected configurations. 1147# 1148################################################### 1149 1150for variant_path in variant_paths: 1151 if not GetOption('silent'): 1152 print("Building in", variant_path) 1153 1154 # Make a copy of the build-root environment to use for this config. 1155 env = main.Clone() 1156 env['BUILDDIR'] = variant_path 1157 1158 # variant_dir is the tail component of build path, and is used to 1159 # determine the build parameters (e.g., 'ALPHA_SE') 1160 (build_root, variant_dir) = splitpath(variant_path) 1161 1162 # Set env variables according to the build directory config. 1163 sticky_vars.files = [] 1164 # Variables for $BUILD_ROOT/$VARIANT_DIR are stored in 1165 # $BUILD_ROOT/variables/$VARIANT_DIR so you can nuke 1166 # $BUILD_ROOT/$VARIANT_DIR without losing your variables settings. 1167 current_vars_file = joinpath(build_root, 'variables', variant_dir) 1168 if isfile(current_vars_file): 1169 sticky_vars.files.append(current_vars_file) 1170 if not GetOption('silent'): 1171 print("Using saved variables file %s" % current_vars_file) 1172 elif variant_dir in ext_build_dirs: 1173 # Things in ext are built without a variant directory. 1174 continue 1175 else: 1176 # Build dir-specific variables file doesn't exist. 1177 1178 # Make sure the directory is there so we can create it later 1179 opt_dir = dirname(current_vars_file) 1180 if not isdir(opt_dir): 1181 mkdir(opt_dir) 1182 1183 # Get default build variables from source tree. Variables are 1184 # normally determined by name of $VARIANT_DIR, but can be 1185 # overridden by '--default=' arg on command line. 1186 default = GetOption('default') 1187 opts_dir = joinpath(main.root.abspath, 'build_opts') 1188 if default: 1189 default_vars_files = [joinpath(build_root, 'variables', default), 1190 joinpath(opts_dir, default)] 1191 else: 1192 default_vars_files = [joinpath(opts_dir, variant_dir)] 1193 existing_files = filter(isfile, default_vars_files) 1194 if existing_files: 1195 default_vars_file = existing_files[0] 1196 sticky_vars.files.append(default_vars_file) 1197 print("Variables file %s not found,\n using defaults in %s" 1198 % (current_vars_file, default_vars_file)) 1199 else: 1200 print("Error: cannot find variables file %s or " 1201 "default file(s) %s" 1202 % (current_vars_file, ' or '.join(default_vars_files))) 1203 Exit(1) 1204 1205 # Apply current variable settings to env 1206 sticky_vars.Update(env) 1207 1208 help_texts["local_vars"] += \ 1209 "Build variables for %s:\n" % variant_dir \ 1210 + sticky_vars.GenerateHelpText(env) 1211 1212 # Process variable settings. 1213 1214 if not have_fenv and env['USE_FENV']: 1215 print("Warning: <fenv.h> not available; " 1216 "forcing USE_FENV to False in", variant_dir + ".") 1217 env['USE_FENV'] = False 1218 1219 if not env['USE_FENV']: 1220 print("Warning: No IEEE FP rounding mode control in", 1221 variant_dir + ".") 1222 print(" FP results may deviate slightly from other platforms.") 1223 1224 if not have_png and env['USE_PNG']: 1225 print("Warning: <png.h> not available; " 1226 "forcing USE_PNG to False in", variant_dir + ".") 1227 env['USE_PNG'] = False 1228 1229 if env['USE_PNG']: 1230 env.Append(LIBS=['png']) 1231 1232 if env['EFENCE']: 1233 env.Append(LIBS=['efence']) 1234 1235 if env['USE_KVM']: 1236 if not have_kvm: 1237 print("Warning: Can not enable KVM, host seems to " 1238 "lack KVM support") 1239 env['USE_KVM'] = False 1240 elif not is_isa_kvm_compatible(env['TARGET_ISA']): 1241 print("Info: KVM support disabled due to unsupported host and " 1242 "target ISA combination") 1243 env['USE_KVM'] = False 1244 1245 if env['USE_TUNTAP']: 1246 if not have_tuntap: 1247 print("Warning: Can't connect EtherTap with a tap device.") 1248 env['USE_TUNTAP'] = False 1249 1250 if env['BUILD_GPU']: 1251 env.Append(CPPDEFINES=['BUILD_GPU']) 1252 1253 # Warn about missing optional functionality 1254 if env['USE_KVM']: 1255 if not main['HAVE_PERF_ATTR_EXCLUDE_HOST']: 1256 print("Warning: perf_event headers lack support for the " 1257 "exclude_host attribute. KVM instruction counts will " 1258 "be inaccurate.") 1259 1260 # Save sticky variable settings back to current variables file 1261 sticky_vars.Save(current_vars_file, env) 1262 1263 if env['USE_SSE2']: 1264 env.Append(CCFLAGS=['-msse2']) 1265 1266 # The src/SConscript file sets up the build rules in 'env' according 1267 # to the configured variables. It returns a list of environments, 1268 # one for each variant build (debug, opt, etc.) 1269 SConscript('src/SConscript', variant_dir = variant_path, exports = 'env') 1270 1271# base help text 1272Help(''' 1273Usage: scons [scons options] [build variables] [target(s)] 1274 1275Extra scons options: 1276%(options)s 1277 1278Global build variables: 1279%(global_vars)s 1280 1281%(local_vars)s 1282''' % help_texts) 1283