These are used to adapt gem5 to the system it's being built on, and so should be attached to the host via the environment rather than gem5's configuration. Change-Id: I2adfe1af484dcdeae32a48097d9aa87752a7ed2a Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/56752 Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br> Maintainer: Gabe Black <gabe.black@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
732 lines
28 KiB
Python
Executable File
732 lines
28 KiB
Python
Executable File
# -*- mode:python -*-
|
|
|
|
# Copyright (c) 2013, 2015-2020 ARM Limited
|
|
# All rights reserved.
|
|
#
|
|
# The license below extends only to copyright in the software and shall
|
|
# not be construed as granting a license to any other intellectual
|
|
# property including but not limited to intellectual property relating
|
|
# to a hardware implementation of the functionality of the software
|
|
# licensed hereunder. You may use the software subject to the license
|
|
# terms below provided that you ensure that this notice is replicated
|
|
# unmodified and in its entirety in all distributions of the software,
|
|
# modified or unmodified, in source code or in binary form.
|
|
#
|
|
# Copyright (c) 2011 Advanced Micro Devices, Inc.
|
|
# Copyright (c) 2009 The Hewlett-Packard Development Company
|
|
# Copyright (c) 2004-2005 The Regents of The University of Michigan
|
|
# All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are
|
|
# met: redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer;
|
|
# redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution;
|
|
# neither the name of the copyright holders nor the names of its
|
|
# contributors may be used to endorse or promote products derived from
|
|
# this software without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
###################################################
|
|
#
|
|
# SCons top-level build description (SConstruct) file.
|
|
#
|
|
# While in this directory ('gem5'), just type 'scons' to build the default
|
|
# configuration (see below), or type 'scons build/<CONFIG>/<binary>'
|
|
# to build some other configuration (e.g., 'build/X86/gem5.opt' for
|
|
# the optimized X86 version).
|
|
#
|
|
# You can build gem5 in a different directory as long as there is a
|
|
# 'build/<CONFIG>' somewhere along the target path. The build system
|
|
# expects that all configs under the same build directory are being
|
|
# built for the same host system.
|
|
#
|
|
# Examples:
|
|
#
|
|
# The following two commands are equivalent. The '-u' option tells
|
|
# scons to search up the directory tree for this SConstruct file.
|
|
# % cd <path-to-src>/gem5 ; scons build/X86/gem5.debug
|
|
# % cd <path-to-src>/gem5/build/X86; scons -u gem5.debug
|
|
#
|
|
# The following two commands are equivalent and demonstrate building
|
|
# in a directory outside of the source tree. The '-C' option tells
|
|
# scons to chdir to the specified directory to find this SConstruct
|
|
# file.
|
|
# % cd <path-to-src>/gem5 ; scons /local/foo/build/X86/gem5.debug
|
|
# % cd /local/foo/build/X86; scons -C <path-to-src>/gem5 gem5.debug
|
|
#
|
|
# You can use 'scons -H' to print scons options. If you're in this
|
|
# 'gem5' directory (or use -u or -C to tell scons where to find this
|
|
# file), you can use 'scons -h' to print all the gem5-specific build
|
|
# options as well.
|
|
#
|
|
###################################################
|
|
|
|
# Global Python imports
|
|
import atexit
|
|
import os
|
|
import sys
|
|
|
|
from os import mkdir, environ
|
|
from os.path import abspath, dirname, expanduser
|
|
from os.path import isdir, isfile
|
|
from os.path import join, split
|
|
|
|
# SCons imports
|
|
import SCons
|
|
import SCons.Node
|
|
import SCons.Node.FS
|
|
import SCons.Tool
|
|
|
|
|
|
########################################################################
|
|
#
|
|
# Command line options.
|
|
#
|
|
########################################################################
|
|
|
|
linker_options = ('bfd', 'gold', 'lld', 'mold')
|
|
|
|
AddOption('--no-colors', dest='use_colors', action='store_false',
|
|
help="Don't add color to abbreviated scons output")
|
|
AddOption('--with-cxx-config', action='store_true',
|
|
help="Build with support for C++-based configuration")
|
|
AddOption('--default',
|
|
help='Override which build_opts file to use for defaults')
|
|
AddOption('--ignore-style', action='store_true',
|
|
help='Disable style checking hooks')
|
|
AddOption('--linker', action='store', default=None, choices=linker_options,
|
|
help=f'Select which linker to use ({", ".join(linker_options)})')
|
|
AddOption('--gold-linker', action='store_const', const='gold', dest='linker',
|
|
help='Use the gold linker. Deprecated: Use --linker=gold')
|
|
AddOption('--no-compress-debug', action='store_true',
|
|
help="Don't compress debug info in build files")
|
|
AddOption('--with-lto', action='store_true',
|
|
help='Enable Link-Time Optimization')
|
|
AddOption('--verbose', action='store_true',
|
|
help='Print full tool command lines')
|
|
AddOption('--without-python', action='store_true',
|
|
help='Build without Python configuration support')
|
|
AddOption('--without-tcmalloc', action='store_true',
|
|
help='Disable linking against tcmalloc')
|
|
AddOption('--with-ubsan', action='store_true',
|
|
help='Build with Undefined Behavior Sanitizer if available')
|
|
AddOption('--with-asan', action='store_true',
|
|
help='Build with Address Sanitizer if available')
|
|
AddOption('--with-systemc-tests', action='store_true',
|
|
help='Build systemc tests')
|
|
AddOption('--install-hooks', action='store_true',
|
|
help='Install revision control hooks non-interactively')
|
|
AddOption('--gprof', action='store_true',
|
|
help='Enable support for the gprof profiler')
|
|
AddOption('--pprof', action='store_true',
|
|
help='Enable support for the pprof profiler')
|
|
|
|
# Inject the built_tools directory into the python path.
|
|
sys.path[1:1] = [ Dir('#build_tools').abspath ]
|
|
|
|
# Imports of gem5_scons happen here since it depends on some options which are
|
|
# declared above.
|
|
from gem5_scons import error, warning, summarize_warnings, parse_build_path
|
|
from gem5_scons import TempFileSpawn, EnvDefaults, MakeAction, MakeActionTool
|
|
import gem5_scons
|
|
from gem5_scons.builders import ConfigFile, AddLocalRPATH, SwitchingHeaders
|
|
from gem5_scons.builders import Blob
|
|
from gem5_scons.sources import TagImpliesTool
|
|
from gem5_scons.util import compareVersions, readCommand
|
|
|
|
# Disable warnings when targets can be built with multiple environments but
|
|
# with the same actions. This can happen intentionally if, for instance, a
|
|
# generated source file is used to build object files in different ways in
|
|
# different environments, but generating the source file itself is exactly the
|
|
# same. This can be re-enabled from the command line if desired.
|
|
SetOption('warn', 'no-duplicate-environment')
|
|
|
|
Export('MakeAction')
|
|
|
|
########################################################################
|
|
#
|
|
# Set up the main build environment.
|
|
#
|
|
########################################################################
|
|
|
|
main = Environment(tools=[
|
|
'default', 'git', TempFileSpawn, EnvDefaults, MakeActionTool,
|
|
ConfigFile, AddLocalRPATH, SwitchingHeaders, TagImpliesTool, Blob
|
|
])
|
|
|
|
main.Tool(SCons.Tool.FindTool(['gcc', 'clang'], main))
|
|
main.Tool(SCons.Tool.FindTool(['g++', 'clang++'], main))
|
|
|
|
Export('main')
|
|
|
|
from gem5_scons.util import get_termcap
|
|
termcap = get_termcap()
|
|
|
|
# Check that we have a C/C++ compiler
|
|
if not ('CC' in main and 'CXX' in main):
|
|
error("No C++ compiler installed (package g++ on Ubuntu and RedHat)")
|
|
|
|
# Find default configuration & binary.
|
|
Default(environ.get('M5_DEFAULT_BINARY', 'build/ARM/gem5.debug'))
|
|
|
|
|
|
########################################################################
|
|
#
|
|
# Figure out which configurations to set up based on the path(s) of
|
|
# the target(s).
|
|
#
|
|
########################################################################
|
|
|
|
# helper function: find last occurrence of element in list
|
|
def rfind(l, elt, offs = -1):
|
|
for i in range(len(l)+offs, 0, -1):
|
|
if l[i] == elt:
|
|
return i
|
|
raise ValueError("element not found")
|
|
|
|
# Take a list of paths (or SCons Nodes) and return a list with all
|
|
# paths made absolute and ~-expanded. Paths will be interpreted
|
|
# relative to the launch directory unless a different root is provided
|
|
def makePathListAbsolute(path_list, root=GetLaunchDir()):
|
|
return [abspath(os.path.join(root, expanduser(str(p))))
|
|
for p in path_list]
|
|
|
|
# Each target must have 'build' in the interior of the path; the
|
|
# directory below this will determine the build parameters. For
|
|
# example, for target 'foo/bar/build/X86/arch/x86/blah.do' we
|
|
# recognize that X86 specifies the configuration because it
|
|
# follow 'build' in the build path.
|
|
|
|
# The funky assignment to "[:]" is needed to replace the list contents
|
|
# in place rather than reassign the symbol to a new list, which
|
|
# doesn't work (obviously!).
|
|
BUILD_TARGETS[:] = makePathListAbsolute(BUILD_TARGETS)
|
|
|
|
# Generate a list of the unique build roots and configs that the
|
|
# collected targets reference.
|
|
variant_paths = set()
|
|
build_root = None
|
|
for t in BUILD_TARGETS:
|
|
this_build_root, variant = parse_build_path(t)
|
|
|
|
# Make sure all targets use the same build root.
|
|
if not build_root:
|
|
build_root = this_build_root
|
|
elif this_build_root != build_root:
|
|
error("build targets not under same build root\n %s\n %s" %
|
|
(build_root, this_build_root))
|
|
|
|
# Collect all the variants into a set.
|
|
variant_paths.add(os.path.join('/', build_root, variant))
|
|
|
|
# Make sure build_root exists (might not if this is the first build there)
|
|
if not isdir(build_root):
|
|
mkdir(build_root)
|
|
main['BUILDROOT'] = build_root
|
|
|
|
main.SConsignFile(os.path.join(build_root, "sconsign"))
|
|
|
|
|
|
########################################################################
|
|
#
|
|
# Set up global sticky variables... these are common to an entire build
|
|
# tree (not specific to a particular build like X86)
|
|
#
|
|
########################################################################
|
|
|
|
global_vars_file = os.path.join(build_root, 'variables.global')
|
|
|
|
global_vars = Variables(global_vars_file, args=ARGUMENTS)
|
|
|
|
global_vars.AddVariables(
|
|
('BATCH', 'Use batch pool for build and tests', False),
|
|
('BATCH_CMD', 'Batch pool submission command name', 'qdo'),
|
|
('M5_BUILD_CACHE', 'Cache built objects in this directory', False),
|
|
('EXTRAS', 'Add extra directories to the compilation', '')
|
|
)
|
|
|
|
# Update main environment with values from ARGUMENTS & global_vars_file
|
|
global_vars.Update(main)
|
|
Help('''
|
|
Global build variables:
|
|
{help}
|
|
'''.format(help=global_vars.GenerateHelpText(main)), append=True)
|
|
|
|
# Save sticky variable settings back to current variables file
|
|
global_vars.Save(global_vars_file, main)
|
|
|
|
|
|
########################################################################
|
|
#
|
|
# Set up various paths.
|
|
#
|
|
########################################################################
|
|
|
|
# Parse EXTRAS variable to build list of all directories where we're
|
|
# look for sources etc. This list is exported as extras_dir_list.
|
|
base_dir = Dir('#src').abspath
|
|
if main['EXTRAS']:
|
|
extras_dir_list = makePathListAbsolute(main['EXTRAS'].split(':'))
|
|
else:
|
|
extras_dir_list = []
|
|
|
|
Export('base_dir')
|
|
Export('extras_dir_list')
|
|
|
|
# the ext directory should be on the #includes path
|
|
main.Append(CPPPATH=[Dir('ext')])
|
|
|
|
# Add shared top-level headers
|
|
main.Prepend(CPPPATH=Dir('include'))
|
|
|
|
|
|
########################################################################
|
|
#
|
|
# Set command line options based on the configuration of the host and
|
|
# build settings.
|
|
#
|
|
########################################################################
|
|
|
|
# Initialize the Link-Time Optimization (LTO) flags
|
|
main['LTO_CCFLAGS'] = []
|
|
main['LTO_LINKFLAGS'] = []
|
|
|
|
# According to the readme, tcmalloc works best if the compiler doesn't
|
|
# assume that we're using the builtin malloc and friends. These flags
|
|
# are compiler-specific, so we need to set them after we detect which
|
|
# compiler we're using.
|
|
main['TCMALLOC_CCFLAGS'] = []
|
|
|
|
CXX_version = readCommand([main['CXX'], '--version'], exception=False)
|
|
|
|
main['GCC'] = CXX_version and CXX_version.find('g++') >= 0
|
|
main['CLANG'] = CXX_version and CXX_version.find('clang') >= 0
|
|
if main['GCC'] + main['CLANG'] > 1:
|
|
error('Two compilers enabled at once?')
|
|
|
|
# Set up default C++ compiler flags
|
|
if main['GCC'] or main['CLANG']:
|
|
# As gcc and clang share many flags, do the common parts here
|
|
main.Append(CCFLAGS=['-pipe'])
|
|
main.Append(CCFLAGS=['-fno-strict-aliasing'])
|
|
|
|
# Enable -Wall and -Wextra and then disable the few warnings that
|
|
# we consistently violate
|
|
main.Append(CCFLAGS=['-Wall', '-Wundef', '-Wextra',
|
|
'-Wno-sign-compare', '-Wno-unused-parameter'])
|
|
|
|
# We always compile using C++17
|
|
main.Append(CXXFLAGS=['-std=c++17'])
|
|
|
|
if sys.platform.startswith('freebsd'):
|
|
main.Append(CCFLAGS=['-I/usr/local/include'])
|
|
main.Append(CXXFLAGS=['-I/usr/local/include'])
|
|
# On FreeBSD we need libthr.
|
|
main.Append(LIBS=['thr'])
|
|
|
|
with gem5_scons.Configure(main) as conf:
|
|
conf.CheckLinkFlag('-Wl,--as-needed')
|
|
|
|
linker = GetOption('linker')
|
|
if linker:
|
|
with gem5_scons.Configure(main) as conf:
|
|
if not conf.CheckLinkFlag(f'-fuse-ld={linker}'):
|
|
error(f'Linker "{linker}" is not supported')
|
|
if linker == 'gold' and not GetOption('with_lto'):
|
|
# Tell the gold linker to use threads. The gold linker
|
|
# segfaults if both threads and LTO are enabled.
|
|
conf.CheckLinkFlag('-Wl,--threads')
|
|
conf.CheckLinkFlag(
|
|
'-Wl,--thread-count=%d' % GetOption('num_jobs'))
|
|
|
|
# Treat warnings as errors but white list some warnings that we
|
|
# want to allow (e.g., deprecation warnings).
|
|
main.Append(CCFLAGS=['-Werror',
|
|
'-Wno-error=deprecated-declarations',
|
|
'-Wno-error=deprecated',
|
|
])
|
|
|
|
else:
|
|
error('\n'.join((
|
|
"Don't know what compiler options to use for your compiler.",
|
|
"compiler: " + main['CXX'],
|
|
"version: " + CXX_version.replace('\n', '<nl>') if
|
|
CXX_version else 'COMMAND NOT FOUND!',
|
|
"If you're trying to use a compiler other than GCC",
|
|
"or clang, there appears to be something wrong with your",
|
|
"environment.",
|
|
"",
|
|
"If you are trying to use a compiler other than those listed",
|
|
"above you will need to ease fix SConstruct and ",
|
|
"src/SConscript to support that compiler.")))
|
|
|
|
if main['GCC']:
|
|
if compareVersions(main['CXXVERSION'], "7") < 0:
|
|
error('gcc version 7 or newer required.\n'
|
|
'Installed version:', main['CXXVERSION'])
|
|
|
|
with gem5_scons.Configure(main) as conf:
|
|
# This warning has a false positive in the systemc code in g++ 11.1.
|
|
conf.CheckCxxFlag('-Wno-free-nonheap-object')
|
|
|
|
# Add the appropriate Link-Time Optimization (LTO) flags if `--with-lto` is
|
|
# set.
|
|
if GetOption('with_lto'):
|
|
# g++ uses "make" to parallelize LTO. The program can be overriden with
|
|
# the environment variable "MAKE", but we currently make no attempt to
|
|
# plumb that variable through.
|
|
parallelism = ''
|
|
if main.Detect('make'):
|
|
parallelism = '=%d' % GetOption('num_jobs')
|
|
else:
|
|
warning('"make" not found, link time optimization will be '
|
|
'single threaded.')
|
|
|
|
for var in 'LTO_CCFLAGS', 'LTO_LINKFLAGS':
|
|
# Use the same amount of jobs for LTO as we are running scons with.
|
|
main[var] = ['-flto%s' % parallelism]
|
|
|
|
main.Append(TCMALLOC_CCFLAGS=['-fno-builtin-malloc', '-fno-builtin-calloc',
|
|
'-fno-builtin-realloc', '-fno-builtin-free'])
|
|
|
|
elif main['CLANG']:
|
|
if compareVersions(main['CXXVERSION'], "6") < 0:
|
|
error('clang version 6 or newer required.\n'
|
|
'Installed version:', main['CXXVERSION'])
|
|
|
|
# Set the Link-Time Optimization (LTO) flags if enabled.
|
|
if GetOption('with_lto'):
|
|
for var in 'LTO_CCFLAGS', 'LTO_LINKFLAGS':
|
|
main[var] = ['-flto']
|
|
|
|
# clang has a few additional warnings that we disable.
|
|
with gem5_scons.Configure(main) as conf:
|
|
conf.CheckCxxFlag('-Wno-c99-designator')
|
|
conf.CheckCxxFlag('-Wno-defaulted-function-deleted')
|
|
|
|
main.Append(TCMALLOC_CCFLAGS=['-fno-builtin'])
|
|
|
|
# On Mac OS X/Darwin we need to also use libc++ (part of XCode) as
|
|
# opposed to libstdc++, as the later is dated.
|
|
if sys.platform == "darwin":
|
|
main.Append(CXXFLAGS=['-stdlib=libc++'])
|
|
main.Append(LIBS=['c++'])
|
|
|
|
# Add sanitizers flags
|
|
sanitizers=[]
|
|
if GetOption('with_ubsan'):
|
|
sanitizers.append('undefined')
|
|
if GetOption('with_asan'):
|
|
# Available for gcc >= 5 or llvm >= 3.1 both a requirement
|
|
# by the build system
|
|
sanitizers.append('address')
|
|
suppressions_file = Dir('util').File('lsan-suppressions').get_abspath()
|
|
suppressions_opt = 'suppressions=%s' % suppressions_file
|
|
suppressions_opts = ':'.join([suppressions_opt, 'print_suppressions=0'])
|
|
main['ENV']['LSAN_OPTIONS'] = suppressions_opts
|
|
print()
|
|
warning('To suppress false positive leaks, set the LSAN_OPTIONS '
|
|
'environment variable to "%s" when running gem5' %
|
|
suppressions_opts)
|
|
warning('LSAN_OPTIONS=%s' % suppressions_opts)
|
|
print()
|
|
if sanitizers:
|
|
sanitizers = ','.join(sanitizers)
|
|
if main['GCC'] or main['CLANG']:
|
|
main.Append(CCFLAGS=['-fsanitize=%s' % sanitizers,
|
|
'-fno-omit-frame-pointer'],
|
|
LINKFLAGS='-fsanitize=%s' % sanitizers)
|
|
else:
|
|
warning("Don't know how to enable %s sanitizer(s) for your "
|
|
"compiler." % sanitizers)
|
|
|
|
# Do this after we save setting back, or else we'll tack on an
|
|
# extra 'qdo' every time we run scons.
|
|
if main['BATCH']:
|
|
main['CC'] = main['BATCH_CMD'] + ' ' + main['CC']
|
|
main['CXX'] = main['BATCH_CMD'] + ' ' + main['CXX']
|
|
main['AS'] = main['BATCH_CMD'] + ' ' + main['AS']
|
|
main['AR'] = main['BATCH_CMD'] + ' ' + main['AR']
|
|
main['RANLIB'] = main['BATCH_CMD'] + ' ' + main['RANLIB']
|
|
|
|
if sys.platform == 'cygwin':
|
|
# cygwin has some header file issues...
|
|
main.Append(CCFLAGS=["-Wno-uninitialized"])
|
|
|
|
|
|
# Cache build files in the supplied directory.
|
|
if main['M5_BUILD_CACHE']:
|
|
print('Using build cache located at', main['M5_BUILD_CACHE'])
|
|
CacheDir(main['M5_BUILD_CACHE'])
|
|
|
|
if not GetOption('no_compress_debug'):
|
|
with gem5_scons.Configure(main) as conf:
|
|
if not conf.CheckCxxFlag('-gz'):
|
|
warning("Can't enable object file debug section compression")
|
|
if not conf.CheckLinkFlag('-gz'):
|
|
warning("Can't enable executable debug section compression")
|
|
|
|
|
|
########################################################################
|
|
#
|
|
# Detect and configure external dependencies.
|
|
#
|
|
########################################################################
|
|
|
|
main['USE_PYTHON'] = not GetOption('without_python')
|
|
|
|
def config_embedded_python(env):
|
|
# Find Python include and library directories for embedding the
|
|
# interpreter. We rely on python-config to resolve the appropriate
|
|
# includes and linker flags. If you want to link in an alternate version
|
|
# of python, override the PYTHON_CONFIG variable.
|
|
|
|
python_config = env.Detect(env['PYTHON_CONFIG'])
|
|
if python_config is None:
|
|
error("Can't find a suitable python-config, tried "
|
|
f"{env['PYTHON_CONFIG']}")
|
|
|
|
print(f"Info: Using Python config: {python_config}")
|
|
|
|
cmd = [python_config, '--ldflags', '--includes']
|
|
|
|
# Starting in Python 3.8 the --embed flag is required. Use it if supported.
|
|
with gem5_scons.Configure(env) as conf:
|
|
if conf.TryAction(f'@{python_config} --embed')[0]:
|
|
cmd.append('--embed')
|
|
|
|
def flag_filter(env, cmd_output):
|
|
flags = cmd_output.split()
|
|
prefixes = ('-l', '-L', '-I')
|
|
is_useful = lambda x: any(x.startswith(prefix) for prefix in prefixes)
|
|
useful_flags = list(filter(is_useful, flags))
|
|
env.MergeFlags(' '.join(useful_flags))
|
|
|
|
env.ParseConfig(cmd, flag_filter)
|
|
|
|
env.Prepend(CPPPATH=Dir('ext/pybind11/include/'))
|
|
|
|
with gem5_scons.Configure(env) as conf:
|
|
# verify that this stuff works
|
|
if not conf.CheckHeader('Python.h', '<>'):
|
|
error("Check failed for Python.h header.\n",
|
|
"Two possible reasons:\n"
|
|
"1. Python headers are not installed (You can install the "
|
|
"package python-dev on Ubuntu and RedHat)\n"
|
|
"2. SCons is using a wrong C compiler. This can happen if "
|
|
"CC has the wrong value.\n"
|
|
f"CC = {env['CC']}")
|
|
py_version = conf.CheckPythonLib()
|
|
if not py_version:
|
|
error("Can't find a working Python installation")
|
|
|
|
# Found a working Python installation. Check if it meets minimum
|
|
# requirements.
|
|
ver_string = '.'.join(map(str, py_version))
|
|
if py_version[0] < 3 or (py_version[0] == 3 and py_version[1] < 6):
|
|
error('Embedded python library 3.6 or newer required, found '
|
|
f'{ver_string}.')
|
|
elif py_version[0] > 3:
|
|
warning('Embedded python library too new. '
|
|
f'Python 3 expected, found {ver_string}.')
|
|
|
|
if main['USE_PYTHON']:
|
|
config_embedded_python(main)
|
|
gem5py_env = main.Clone()
|
|
else:
|
|
gem5py_env = main.Clone()
|
|
config_embedded_python(gem5py_env)
|
|
|
|
# Bare minimum environment that only includes python
|
|
gem5py_env.Append(CCFLAGS=['${GEM5PY_CCFLAGS_EXTRA}'])
|
|
gem5py_env.Append(LINKFLAGS=['${GEM5PY_LINKFLAGS_EXTRA}'])
|
|
|
|
if GetOption('gprof') and GetOption('pprof'):
|
|
error('Only one type of profiling should be enabled at a time')
|
|
if GetOption('gprof'):
|
|
main.Append(CCFLAGS=['-g', '-pg'], LINKFLAGS=['-pg'])
|
|
if GetOption('pprof'):
|
|
main.Append(CCFLAGS=['-g'],
|
|
LINKFLAGS=['-Wl,--no-as-needed', '-lprofiler', '-Wl,--as-needed'])
|
|
|
|
main['HAVE_PKG_CONFIG'] = main.Detect('pkg-config')
|
|
|
|
with gem5_scons.Configure(main) as conf:
|
|
# On Solaris you need to use libsocket for socket ops
|
|
if not conf.CheckLibWithHeader(
|
|
[None, 'socket'], 'sys/socket.h', 'C++', 'accept(0,0,0);'):
|
|
error("Can't find library with socket calls (e.g. accept()).")
|
|
|
|
if not conf.CheckLibWithHeader('z', 'zlib.h', 'C++','zlibVersion();'):
|
|
error('Did not find needed zlib compression library '
|
|
'and/or zlib.h header file.\n'
|
|
'Please install zlib and try again.')
|
|
|
|
if not GetOption('without_tcmalloc'):
|
|
with gem5_scons.Configure(main) as conf:
|
|
if conf.CheckLib('tcmalloc'):
|
|
conf.env.Append(CCFLAGS=conf.env['TCMALLOC_CCFLAGS'])
|
|
elif conf.CheckLib('tcmalloc_minimal'):
|
|
conf.env.Append(CCFLAGS=conf.env['TCMALLOC_CCFLAGS'])
|
|
else:
|
|
warning("You can get a 12% performance improvement by "
|
|
"installing tcmalloc (libgoogle-perftools-dev package "
|
|
"on Ubuntu or RedHat).")
|
|
|
|
|
|
########################################################################
|
|
#
|
|
# Define build environments for required variants.
|
|
#
|
|
########################################################################
|
|
|
|
for variant_path in variant_paths:
|
|
if not GetOption('silent'):
|
|
print("Building in", variant_path)
|
|
|
|
# Make a copy of the build-root environment to use for this config.
|
|
env = main.Clone()
|
|
env['BUILDDIR'] = variant_path
|
|
|
|
# variant_dir is the tail component of build path, and is used to
|
|
# determine the build parameters (e.g., 'X86')
|
|
(build_root, variant_dir) = os.path.split(variant_path)
|
|
|
|
####################################################################
|
|
#
|
|
# Read and process SConsopts files. These can add new settings which
|
|
# affect each variant directory independently.
|
|
#
|
|
####################################################################
|
|
|
|
# Register a callback to call after all SConsopts files have been read.
|
|
after_sconsopts_callbacks = []
|
|
def AfterSConsopts(cb):
|
|
after_sconsopts_callbacks.append(cb)
|
|
Export('AfterSConsopts')
|
|
|
|
# Sticky variables get saved in the variables file so they persist from
|
|
# one invocation to the next (unless overridden, in which case the new
|
|
# value becomes sticky).
|
|
sticky_vars = Variables(args=ARGUMENTS)
|
|
Export('sticky_vars')
|
|
|
|
# Sticky variables that should be exported to #defines in config/*.hh
|
|
# (see src/SConscript).
|
|
export_vars = []
|
|
Export('export_vars')
|
|
|
|
# Walk the tree and execute all SConsopts scripts that wil add to the
|
|
# above variables
|
|
if GetOption('verbose'):
|
|
print("Reading SConsopts")
|
|
for bdir in [ base_dir ] + extras_dir_list:
|
|
if not isdir(bdir):
|
|
error("Directory '%s' does not exist." % bdir)
|
|
for root, dirs, files in os.walk(bdir):
|
|
if 'SConsopts' in files:
|
|
if GetOption('verbose'):
|
|
print("Reading", os.path.join(root, 'SConsopts'))
|
|
SConscript(os.path.join(root, 'SConsopts'),
|
|
exports={'main': env})
|
|
|
|
# Call any callbacks which the SConsopts files registered.
|
|
for cb in after_sconsopts_callbacks:
|
|
cb()
|
|
|
|
# Add any generic sticky variables here.
|
|
sticky_vars.Add(BoolVariable('USE_EFENCE',
|
|
'Link with Electric Fence malloc debugger', False))
|
|
|
|
# Set env variables according to the build directory config.
|
|
sticky_vars.files = []
|
|
# Variables for $BUILD_ROOT/$VARIANT_DIR are stored in
|
|
# $BUILD_ROOT/variables/$VARIANT_DIR so you can nuke
|
|
# $BUILD_ROOT/$VARIANT_DIR without losing your variables settings.
|
|
current_vars_file = os.path.join(build_root, 'variables', variant_dir)
|
|
if isfile(current_vars_file):
|
|
sticky_vars.files.append(current_vars_file)
|
|
if not GetOption('silent'):
|
|
print("Using saved variables file %s" % current_vars_file)
|
|
else:
|
|
# Variant specific variables file doesn't exist.
|
|
|
|
# Make sure the directory is there so we can create the file later.
|
|
opt_dir = dirname(current_vars_file)
|
|
if not isdir(opt_dir):
|
|
mkdir(opt_dir)
|
|
|
|
# Get default build variables from source tree. Variables are
|
|
# normally determined by name of $VARIANT_DIR, but can be
|
|
# overridden by '--default=' arg on command line.
|
|
default = GetOption('default')
|
|
opts_dir = Dir('#build_opts').abspath
|
|
if default:
|
|
default_vars_files = [
|
|
os.path.join(build_root, 'variables', default),
|
|
os.path.join(opts_dir, default)
|
|
]
|
|
else:
|
|
default_vars_files = [os.path.join(opts_dir, variant_dir)]
|
|
existing_files = list(filter(isfile, default_vars_files))
|
|
if existing_files:
|
|
default_vars_file = existing_files[0]
|
|
sticky_vars.files.append(default_vars_file)
|
|
print("Variables file %s not found,\n using defaults in %s"
|
|
% (current_vars_file, default_vars_file))
|
|
else:
|
|
error("Cannot find variables file %s or default file(s) %s"
|
|
% (current_vars_file, ' or '.join(default_vars_files)))
|
|
Exit(1)
|
|
|
|
# Apply current variable settings to env
|
|
sticky_vars.Update(env)
|
|
|
|
Help('''
|
|
Build variables for {dir}:
|
|
{help}
|
|
'''.format(dir=variant_dir, help=sticky_vars.GenerateHelpText(env)),
|
|
append=True)
|
|
|
|
# Process variable settings.
|
|
if env['USE_EFENCE']:
|
|
env.Append(LIBS=['efence'])
|
|
|
|
# Save sticky variable settings back to current variables file
|
|
sticky_vars.Save(current_vars_file, env)
|
|
|
|
env.Append(CCFLAGS='$CCFLAGS_EXTRA')
|
|
env.Append(LINKFLAGS='$LINKFLAGS_EXTRA')
|
|
|
|
exports=['env', 'gem5py_env']
|
|
|
|
ext_dir = Dir('#ext').abspath
|
|
variant_ext = os.path.join(variant_path, 'ext')
|
|
for root, dirs, files in os.walk(ext_dir):
|
|
if 'SConscript' in files:
|
|
build_dir = os.path.relpath(root, ext_dir)
|
|
SConscript(os.path.join(root, 'SConscript'),
|
|
variant_dir=os.path.join(variant_ext, build_dir),
|
|
exports=exports)
|
|
|
|
# The src/SConscript file sets up the build rules in 'env' according
|
|
# to the configured variables. It returns a list of environments,
|
|
# one for each variant build (debug, opt, etc.)
|
|
SConscript('src/SConscript', variant_dir=variant_path, exports=exports)
|
|
|
|
atexit.register(summarize_warnings)
|