mem: Stop "using namespace std"
[gem5.git] / SConstruct
index 142800e60620eb4a45a2cb3b98c486d7c5830c39..4cf2f1059e58c231b8a460d1205ea513aa60a5d5 100755 (executable)
@@ -75,8 +75,6 @@
 #
 ###################################################
 
-from __future__ import print_function
-
 # Global Python includes
 import atexit
 import itertools
@@ -99,75 +97,34 @@ import SCons.Node.FS
 
 from m5.util import compareVersions, readCommand, readCommandWithReturn
 
-help_texts = {
-    "options" : "",
-    "global_vars" : "",
-    "local_vars" : ""
-}
-
-Export("help_texts")
-
-
-# There's a bug in scons in that (1) by default, the help texts from
-# AddOption() are supposed to be displayed when you type 'scons -h'
-# and (2) you can override the help displayed by 'scons -h' using the
-# Help() function, but these two features are incompatible: once
-# you've overridden the help text using Help(), there's no way to get
-# at the help texts from AddOptions.  See:
-#     http://scons.tigris.org/issues/show_bug.cgi?id=2356
-#     http://scons.tigris.org/issues/show_bug.cgi?id=2611
-# This hack lets us extract the help text from AddOptions and
-# re-inject it via Help().  Ideally someday this bug will be fixed and
-# we can just use AddOption directly.
-def AddLocalOption(*args, **kwargs):
-    col_width = 30
-
-    help = "  " + ", ".join(args)
-    if "help" in kwargs:
-        length = len(help)
-        if length >= col_width:
-            help += "\n" + " " * col_width
-        else:
-            help += " " * (col_width - length)
-        help += kwargs["help"]
-    help_texts["options"] += help + "\n"
-
-    AddOption(*args, **kwargs)
-
-AddLocalOption('--colors', dest='use_colors', action='store_true',
-               help="Add color to abbreviated scons output")
-AddLocalOption('--no-colors', dest='use_colors', action='store_false',
-               help="Don't add color to abbreviated scons output")
-AddLocalOption('--with-cxx-config', dest='with_cxx_config',
-               action='store_true',
-               help="Build with support for C++-based configuration")
-AddLocalOption('--default', dest='default', type='string', action='store',
-               help='Override which build_opts file to use for defaults')
-AddLocalOption('--ignore-style', dest='ignore_style', action='store_true',
-               help='Disable style checking hooks')
-AddLocalOption('--gold-linker', dest='gold_linker', action='store_true',
-               help='Use the gold linker')
-AddLocalOption('--no-lto', dest='no_lto', action='store_true',
-               help='Disable Link-Time Optimization for fast')
-AddLocalOption('--force-lto', dest='force_lto', action='store_true',
-               help='Use Link-Time Optimization instead of partial linking' +
-                    ' when the compiler doesn\'t support using them together.')
-AddLocalOption('--update-ref', dest='update_ref', action='store_true',
-               help='Update test reference outputs')
-AddLocalOption('--verbose', dest='verbose', action='store_true',
-               help='Print full tool command lines')
-AddLocalOption('--without-python', dest='without_python',
-               action='store_true',
-               help='Build without Python configuration support')
-AddLocalOption('--without-tcmalloc', dest='without_tcmalloc',
-               action='store_true',
-               help='Disable linking against tcmalloc')
-AddLocalOption('--with-ubsan', dest='with_ubsan', action='store_true',
-               help='Build with Undefined Behavior Sanitizer if available')
-AddLocalOption('--with-asan', dest='with_asan', action='store_true',
-               help='Build with Address Sanitizer if available')
-AddLocalOption('--with-systemc-tests', dest='with_systemc_tests',
-               action='store_true', help='Build systemc tests')
+AddOption('--colors', dest='use_colors', action='store_true',
+          help="Add color to abbreviated scons output")
+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('--gold-linker', action='store_true', help='Use the gold linker')
+AddOption('--no-lto', action='store_true',
+          help='Disable Link-Time Optimization for fast')
+AddOption('--force-lto', action='store_true',
+          help='Use Link-Time Optimization instead of partial linking' +
+               ' when the compiler doesn\'t support using them together.')
+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')
 
 from gem5_scons import Transform, error, warning, summarize_warnings
 
@@ -180,7 +137,7 @@ if GetOption('no_lto') and GetOption('force_lto'):
 #
 ########################################################################
 
-main = Environment()
+main = Environment(tools=['default', 'git'])
 
 from gem5_scons.util import get_termcap
 termcap = get_termcap()
@@ -276,8 +233,11 @@ global_vars.AddVariables(
     ('CXX', 'C++ compiler', environ.get('CXX', main['CXX'])),
     ('CCFLAGS_EXTRA', 'Extra C and C++ compiler flags', ''),
     ('LDFLAGS_EXTRA', 'Extra linker flags', ''),
+    ('MARSHAL_CCFLAGS_EXTRA', 'Extra C and C++ marshal compiler flags', ''),
+    ('MARSHAL_LDFLAGS_EXTRA', 'Extra marshal linker flags', ''),
     ('PYTHON_CONFIG', 'Python config binary to use',
-     [ 'python2.7-config', 'python-config', 'python3-config' ]),
+     [ 'python3-config', 'python-config']
+    ),
     ('PROTOC', 'protoc tool', environ.get('PROTOC', 'protoc')),
     ('BATCH', 'Use batch pool for build and tests', False),
     ('BATCH_CMD', 'Batch pool submission command name', 'qdo'),
@@ -287,14 +247,17 @@ global_vars.AddVariables(
 
 # Update main environment with values from ARGUMENTS & global_vars_file
 global_vars.Update(main)
-help_texts["global_vars"] += global_vars.GenerateHelpText(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)
 
 # 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 = main.srcdir.abspath
+base_dir = Dir('#src').abspath
 if main['EXTRAS']:
     extras_dir_list = makePathListAbsolute(main['EXTRAS'].split(':'))
 else:
@@ -353,8 +316,8 @@ if main['GCC'] or main['CLANG']:
     # we consistently violate
     main.Append(CCFLAGS=['-Wall', '-Wundef', '-Wextra',
                          '-Wno-sign-compare', '-Wno-unused-parameter'])
-    # We always compile using C++11
-    main.Append(CXXFLAGS=['-std=c++11'])
+    # We always compile using C++14
+    main.Append(CXXFLAGS=['-std=c++14'])
     if sys.platform.startswith('freebsd'):
         main.Append(CCFLAGS=['-I/usr/local/include'])
         main.Append(CXXFLAGS=['-I/usr/local/include'])
@@ -393,24 +356,21 @@ else:
           "src/SConscript to support that compiler.")))
 
 if main['GCC']:
-    # Check for a supported version of gcc. >= 4.8 is chosen for its
-    # level of c++11 support. See
-    # http://gcc.gnu.org/projects/cxx0x.html for details.
     gcc_version = readCommand([main['CXX'], '-dumpversion'], exception=False)
-    if compareVersions(gcc_version, "4.8") < 0:
-        error('gcc version 4.8 or newer required.\n'
+    if compareVersions(gcc_version, "5") < 0:
+        error('gcc version 5 or newer required.\n'
               'Installed version:', gcc_version)
         Exit(1)
 
     main['GCC_VERSION'] = gcc_version
 
-    if compareVersions(gcc_version, '4.9') >= 0:
-        # Incremental linking with LTO is currently broken in gcc versions
-        # 4.9 and above. A version where everything works completely hasn't
-        # yet been identified.
-        #
-        # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67548
-        main['BROKEN_INCREMENTAL_LTO'] = True
+    # Incremental linking with LTO is currently broken in gcc versions
+    # 4.9 and above. A version where everything works completely hasn't
+    # yet been identified.
+    #
+    # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67548
+    main['BROKEN_INCREMENTAL_LTO'] = True
+
     if compareVersions(gcc_version, '6.0') >= 0:
         # gcc versions 6.0 and greater accept an -flinker-output flag which
         # selects what type of output the linker should generate. This is
@@ -452,15 +412,12 @@ if main['GCC']:
                                   '-fno-builtin-realloc', '-fno-builtin-free'])
 
 elif main['CLANG']:
-    # Check for a supported version of clang, >= 3.1 is needed to
-    # support similar features as gcc 4.8. See
-    # http://clang.llvm.org/cxx_status.html for details
     clang_version_re = re.compile(".* version (\d+\.\d+)")
     clang_version_match = clang_version_re.search(CXX_version)
     if (clang_version_match):
         clang_version = clang_version_match.groups()[0]
-        if compareVersions(clang_version, "3.1") < 0:
-            error('clang version 3.1 or newer required.\n'
+        if compareVersions(clang_version, "3.9") < 0:
+            error('clang version 3.9 or newer required.\n'
                   'Installed version:', clang_version)
     else:
         error('Unable to determine clang version.')
@@ -475,11 +432,14 @@ elif main['CLANG']:
                          # use struct hash and class hash
                          # interchangeably.
                          '-Wno-mismatched-tags',
-                         '-Wno-defaulted-function-deleted',
                          ])
-    if compareVersions(clang_version, "10.0") >= 0:
+    if sys.platform != "darwin" and \
+       compareVersions(clang_version, "10.0") >= 0:
         main.Append(CCFLAGS=['-Wno-c99-designator'])
 
+    if compareVersions(clang_version, "8.0") >= 0:
+        main.Append(CCFLAGS=['-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
@@ -495,13 +455,9 @@ elif main['CLANG']:
 # Add sanitizers flags
 sanitizers=[]
 if GetOption('with_ubsan'):
-    # Only gcc >= 4.9 supports UBSan, so check both the version
-    # and the command-line option before adding the compiler and
-    # linker flags.
-    if not main['GCC'] or compareVersions(main['GCC_VERSION'], '4.9') >= 0:
-        sanitizers.append('undefined')
+    sanitizers.append('undefined')
 if GetOption('with_asan'):
-    # Available for gcc >= 4.8 or llvm >= 3.1 both a requirement
+    # 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()
@@ -617,6 +573,27 @@ int main(){
     context.Result(ret)
     return ret
 
+def CheckPythonLib(context):
+    context.Message('Checking Python version... ')
+    ret = context.TryRun(r"""
+#include <pybind11/embed.h>
+
+int
+main(int argc, char **argv) {
+    pybind11::scoped_interpreter guard{};
+    pybind11::exec(
+        "import sys\n"
+        "vi = sys.version_info\n"
+        "sys.stdout.write('%i.%i.%i' % (vi.major, vi.minor, vi.micro));\n");
+    return 0;
+}
+    """, extension=".cc")
+    context.Result(ret[1] if ret[0] == 1 else 0)
+    if ret[0] == 0:
+        return None
+    else:
+        return tuple(map(int, ret[1].split(".")))
+
 # Platform-specific configuration.  Note again that we assume that all
 # builds under a given build root run on the same host platform.
 conf = Configure(main,
@@ -624,6 +601,7 @@ conf = Configure(main,
                  log_file = joinpath(build_root, 'scons_config.log'),
                  custom_tests = {
         'CheckMember' : CheckMember,
+        'CheckPythonLib' : CheckPythonLib,
         })
 
 # Check if we should compile a 64 bit binary on Mac OS X/Darwin
@@ -679,6 +657,7 @@ if main['USE_PYTHON']:
               main['PYTHON_CONFIG'])
 
     print("Info: Using Python config: %s" % (python_config, ))
+
     py_includes = readCommand([python_config, '--includes'],
                               exception='').split()
     py_includes = list(filter(
@@ -732,7 +711,20 @@ if main['USE_PYTHON']:
 
 main.Prepend(CPPPATH=Dir('ext/pybind11/include/'))
 # Bare minimum environment that only includes python
-base_py_env = main.Clone()
+marshal_env = main.Clone()
+marshal_env.Append(CCFLAGS='$MARSHAL_CCFLAGS_EXTRA')
+marshal_env.Append(LINKFLAGS='$MARSHAL_LDFLAGS_EXTRA')
+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.
+if py_version[0] < 3 or \
+   (py_version[0] == 3 and py_version[1] < 6):
+    error('Python version too old. Version 3.6 or newer is required.')
+elif py_version[0] > 3:
+    warning('Python version too new. Python 3 expected.')
 
 # On Solaris you need to use libsocket for socket ops
 if not conf.CheckLibWithHeader(None, 'sys/socket.h', 'C++', 'accept(0,0,0);'):
@@ -986,8 +978,8 @@ all_isa_list.sort()
 all_gpu_isa_list.sort()
 
 sticky_vars.AddVariables(
-    EnumVariable('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list),
-    EnumVariable('TARGET_GPU_ISA', 'Target GPU ISA', 'hsail', all_gpu_isa_list),
+    EnumVariable('TARGET_ISA', 'Target ISA', 'null', all_isa_list),
+    EnumVariable('TARGET_GPU_ISA', 'Target GPU ISA', 'gcn3', all_gpu_isa_list),
     ListVariable('CPU_MODELS', 'CPU models',
                  sorted(n for n,m in CpuModel.dict.items() if m.default),
                  sorted(CpuModel.dict.keys())),
@@ -999,8 +991,6 @@ sticky_vars.AddVariables(
     BoolVariable('USE_POSIX_CLOCK', 'Use POSIX Clocks', have_posix_clock),
     BoolVariable('USE_FENV', 'Use <fenv.h> IEEE mode control', have_fenv),
     BoolVariable('USE_PNG',  'Enable support for PNG images', have_png),
-    BoolVariable('CP_ANNOTATE', 'Enable critical path annotation capability',
-                 False),
     BoolVariable('USE_KVM', 'Enable hardware virtualized (KVM) CPU models',
                  have_kvm),
     BoolVariable('USE_TUNTAP',
@@ -1017,7 +1007,7 @@ sticky_vars.AddVariables(
     )
 
 # These variables get exported to #defines in config/*.hh (see src/SConscript).
-export_vars += ['USE_FENV', 'TARGET_ISA', 'TARGET_GPU_ISA', 'CP_ANNOTATE',
+export_vars += ['USE_FENV', 'TARGET_ISA', 'TARGET_GPU_ISA',
                 'USE_POSIX_CLOCK', 'USE_KVM', 'USE_TUNTAP', 'PROTOCOL',
                 'HAVE_PROTOBUF', 'HAVE_VALGRIND',
                 'HAVE_PERF_ATTR_EXCLUDE_HOST', 'USE_PNG',
@@ -1035,7 +1025,7 @@ export_vars += ['USE_FENV', 'TARGET_ISA', 'TARGET_GPU_ISA', 'CP_ANNOTATE',
 # value of the variable.
 def build_config_file(target, source, env):
     (variable, value) = [s.get_contents().decode('utf-8') for s in source]
-    with open(str(target[0]), 'w') as f:
+    with open(str(target[0].abspath), 'w') as f:
         print('#define', variable, value, file=f)
     return None
 
@@ -1048,7 +1038,7 @@ def config_emitter(target, source, env):
     # extract variable name from Builder arg
     variable = str(target[0])
     # True target is config header file
-    target = joinpath('config', variable.lower() + '.hh')
+    target = Dir('config').File(variable.lower() + '.hh')
     val = env[variable]
     if isinstance(val, bool):
         # Force value to 0/1
@@ -1057,9 +1047,9 @@ def config_emitter(target, source, env):
         val = '"' + val + '"'
 
     # Sources are variable name & value (packaged in SCons Value nodes)
-    return ([target], [Value(variable), Value(val)])
+    return [target], [Value(variable), Value(val)]
 
-config_builder = Builder(emitter = config_emitter, action = config_action)
+config_builder = Builder(emitter=config_emitter, action=config_action)
 
 main.Append(BUILDERS = { 'ConfigFile' : config_builder })
 
@@ -1113,7 +1103,7 @@ if sys.platform != "darwin":
 main.AddMethod(add_local_rpath, 'AddLocalRPATH')
 
 # builds in ext are shared across all configs in the build root.
-ext_dir = abspath(joinpath(str(main.root), 'ext'))
+ext_dir = Dir('#ext').abspath
 ext_build_dirs = []
 for root, dirs, files in os.walk(ext_dir):
     if 'SConscript' in files:
@@ -1201,7 +1191,7 @@ for variant_path in variant_paths:
         # normally determined by name of $VARIANT_DIR, but can be
         # overridden by '--default=' arg on command line.
         default = GetOption('default')
-        opts_dir = joinpath(main.root.abspath, 'build_opts')
+        opts_dir = Dir('#build_opts').abspath
         if default:
             default_vars_files = [joinpath(build_root, 'variables', default),
                                   joinpath(opts_dir, default)]
@@ -1221,9 +1211,11 @@ for variant_path in variant_paths:
     # Apply current variable settings to env
     sticky_vars.Update(env)
 
-    help_texts["local_vars"] += \
-        "Build variables for %s:\n" % variant_dir \
-                 + sticky_vars.GenerateHelpText(env)
+    Help('''
+Build variables for {dir}:
+{help}
+'''.format(dir=variant_dir, help=sticky_vars.GenerateHelpText(env)),
+         append=True)
 
     # Process variable settings.
 
@@ -1283,19 +1275,6 @@ for variant_path in variant_paths:
     # 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=['env', 'base_py_env'])
-
-# base help text
-Help('''
-Usage: scons [scons options] [build variables] [target(s)]
-
-Extra scons options:
-%(options)s
-
-Global build variables:
-%(global_vars)s
-
-%(local_vars)s
-''' % help_texts)
+               exports=['env', 'marshal_env'])
 
 atexit.register(summarize_warnings)