dev-arm: Conditionally enable HDLcd when doing DTB autogen
[gem5.git] / SConstruct
index b382d33770fabdf4d30df9d370405f6ebf9bfba1..39e7ccc065c58788142557a85d5009418e7872ac 100755 (executable)
@@ -1,6 +1,6 @@
 # -*- mode:python -*-
 
-# Copyright (c) 2013, 2015-2017 ARM Limited
+# Copyright (c) 2013, 2015-2019 ARM Limited
 # All rights reserved.
 #
 # The license below extends only to copyright in the software and shall
@@ -92,10 +92,12 @@ from os import mkdir, environ
 from os.path import abspath, basename, dirname, expanduser, normpath
 from os.path import exists,  isdir, isfile
 from os.path import join as joinpath, split as splitpath
+from re import match
 
 # SCons includes
 import SCons
 import SCons.Node
+import SCons.Node.FS
 
 from m5.util import compareVersions, readCommand
 
@@ -145,6 +147,8 @@ 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',
@@ -212,6 +216,19 @@ def makePathListAbsolute(path_list, root=GetLaunchDir()):
     return [abspath(joinpath(root, expanduser(str(p))))
             for p in path_list]
 
+def find_first_prog(prog_names):
+    """Find the absolute path to the first existing binary in prog_names"""
+
+    if not isinstance(prog_names, (list, tuple)):
+        prog_names = [ prog_names ]
+
+    for p in prog_names:
+        p = main.WhereIs(p)
+        if p is not None:
+            return p
+
+    return None
+
 # 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/ALPHA_SE/arch/alpha/blah.do' we
@@ -273,6 +290,10 @@ global_vars = Variables(global_vars_file, args=ARGUMENTS)
 global_vars.AddVariables(
     ('CC', 'C compiler', environ.get('CC', main['CC'])),
     ('CXX', 'C++ compiler', environ.get('CXX', main['CXX'])),
+    ('CCFLAGS_EXTRA', 'Extra C and C++ compiler flags', ''),
+    ('LDFLAGS_EXTRA', 'Extra linker flags', ''),
+    ('PYTHON_CONFIG', 'Python config binary to use',
+     [ 'python2.7-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'),
@@ -357,6 +378,8 @@ if main['GCC'] or main['CLANG']:
 
     main['FILTER_PSHLINKFLAGS'] = lambda x: str(x).replace(' -shared', '')
     main['PSHLINKFLAGS'] = main.subst('${FILTER_PSHLINKFLAGS(SHLINKFLAGS)}')
+    if GetOption('gold_linker'):
+        main.Append(LINKFLAGS='-fuse-ld=gold')
     main['PLINKFLAGS'] = main.subst('${LINKFLAGS}')
     shared_partial_flags = ['-r', '-nostdlib']
     main.Append(PSHLINKFLAGS=shared_partial_flags)
@@ -421,27 +444,6 @@ if main['GCC']:
             main.Append(PSHLINKFLAGS='-flinker-output=rel')
             main.Append(PLINKFLAGS='-flinker-output=rel')
 
-    # gcc from version 4.8 and above generates "rep; ret" instructions
-    # to avoid performance penalties on certain AMD chips. Older
-    # assemblers detect this as an error, "Error: expecting string
-    # instruction after `rep'"
-    as_version_raw = readCommand([main['AS'], '-v', '/dev/null',
-                                  '-o', '/dev/null'],
-                                 exception=False).split()
-
-    # version strings may contain extra distro-specific
-    # qualifiers, so play it safe and keep only what comes before
-    # the first hyphen
-    as_version = as_version_raw[-1].split('-')[0] if as_version_raw else None
-
-    if not as_version or compareVersions(as_version, "2.23") < 0:
-        print(termcap.Yellow + termcap.Bold +
-            'Warning: This combination of gcc and binutils have' +
-            ' known incompatibilities.\n' +
-            '         If you encounter build problems, please update ' +
-            'binutils to 2.23.' +
-            termcap.Normal)
-
     # Make sure we warn if the user has requested to compile with the
     # Undefined Benahvior Sanitizer and this version of gcc does not
     # support it.
@@ -484,11 +486,11 @@ if main['GCC']:
                 compareVersions(main['GCC_VERSION'], '4.9') >= 0:
             main.Append(CCFLAGS=['-fsanitize=address,undefined',
                                  '-fno-omit-frame-pointer'],
-                       LINKFLAGS='-fsanitize=address,undefined')
+                        LINKFLAGS='-fsanitize=address,undefined')
         else:
             main.Append(CCFLAGS=['-fsanitize=address',
                                  '-fno-omit-frame-pointer'],
-                       LINKFLAGS='-fsanitize=address')
+                        LINKFLAGS='-fsanitize=address')
     # Only gcc >= 4.9 supports UBSan, so check both the version
     # and the command-line option before adding the compiler and
     # linker flags.
@@ -541,16 +543,16 @@ elif main['CLANG']:
     # versions here.
     if GetOption('with_ubsan'):
         if GetOption('with_asan'):
-            env.Append(CCFLAGS=['-fsanitize=address,undefined',
-                                '-fno-omit-frame-pointer'],
+            main.Append(CCFLAGS=['-fsanitize=address,undefined',
+                                 '-fno-omit-frame-pointer'],
                        LINKFLAGS='-fsanitize=address,undefined')
         else:
-            env.Append(CCFLAGS='-fsanitize=undefined',
-                       LINKFLAGS='-fsanitize=undefined')
+            main.Append(CCFLAGS='-fsanitize=undefined',
+                        LINKFLAGS='-fsanitize=undefined')
 
     elif GetOption('with_asan'):
-        env.Append(CCFLAGS=['-fsanitize=address',
-                            '-fno-omit-frame-pointer'],
+        main.Append(CCFLAGS=['-fsanitize=address',
+                             '-fno-omit-frame-pointer'],
                    LINKFLAGS='-fsanitize=address')
 
 else:
@@ -589,6 +591,9 @@ if sys.platform == 'cygwin':
     # cygwin has some header file issues...
     main.Append(CCFLAGS=["-Wno-uninitialized"])
 
+
+have_pkg_config = readCommand(['pkg-config', '--version'], exception='')
+
 # Check for the protobuf compiler
 protoc_version = readCommand([main['PROTOC'], '--version'],
                              exception='').split()
@@ -618,7 +623,7 @@ else:
         # protobuf without the involvement of pkg-config. Later on we
         # check go a library config check and at that point the test
         # will fail if libprotobuf cannot be found.
-        if readCommand(['pkg-config', '--version'], exception=''):
+        if have_pkg_config:
             try:
                 # Attempt to establish what linking flags to add for protobuf
                 # using pkg-config
@@ -718,18 +723,21 @@ if main['USE_PYTHON']:
     # we add them explicitly below. If you want to link in an alternate
     # version of python, see above for instructions on how to invoke
     # scons with the appropriate PATH set.
-    #
-    # First we check if python2-config exists, else we use python-config
-    python_config = readCommand(['which', 'python2-config'],
-                                exception='').strip()
-    if not os.path.exists(python_config):
-        python_config = readCommand(['which', 'python-config'],
-                                    exception='').strip()
+
+    python_config = find_first_prog(main['PYTHON_CONFIG'])
+    if python_config is None:
+        print("Error: can't find a suitable python-config, tried %s" % \
+              main['PYTHON_CONFIG'])
+        Exit(1)
+
+    print("Info: Using Python config: %s" % (python_config, ))
     py_includes = readCommand([python_config, '--includes'],
                               exception='').split()
+    py_includes = filter(lambda s: match(r'.*\/include\/.*',s), py_includes)
     # Strip the -I from the include folders before adding them to the
     # CPPPATH
-    main.Append(CPPPATH=map(lambda inc: inc[2:], py_includes))
+    py_includes = map(lambda s: s[2:] if s.startswith('-I') else s, py_includes)
+    main.Append(CPPPATH=py_includes)
 
     # Read the linker flags and split them into libraries and other link
     # flags. The libraries are added later through the call the CheckLib.
@@ -746,9 +754,13 @@ if main['USE_PYTHON']:
 
     # verify that this stuff works
     if not conf.CheckHeader('Python.h', '<>'):
-        print("Error: can't find Python.h header in", py_includes)
-        print("Install Python headers (package python-dev on " +
-              "Ubuntu and RedHat)")
+        print("Error: Check failed for Python.h header in", py_includes)
+        print("Two possible reasons:")
+        print("1. Python headers are not installed (You can install the "
+              "package python-dev on Ubuntu and RedHat)")
+        print("2. SCons is using a wrong C compiler. This can happen if "
+              "CC has the wrong value.")
+        print("CC = %s" % main['CC'])
         Exit(1)
 
     for lib in py_libs:
@@ -779,6 +791,10 @@ main['HAVE_PROTOBUF'] = main['PROTOC'] and \
     conf.CheckLibWithHeader('protobuf', 'google/protobuf/message.h',
                             'C++', 'GOOGLE_PROTOBUF_VERIFY_VERSION;')
 
+# Valgrind gets much less confused if you tell it when you're using
+# alternative stacks.
+main['HAVE_VALGRIND'] = conf.CheckCHeader('valgrind/valgrind.h')
+
 # If we have the compiler but not the library, print another warning.
 if main['PROTOC'] and not main['HAVE_PROTOBUF']:
     print(termcap.Yellow + termcap.Bold +
@@ -900,6 +916,42 @@ def is_isa_kvm_compatible(isa):
 main['HAVE_PERF_ATTR_EXCLUDE_HOST'] = conf.CheckMember(
     'linux/perf_event.h', 'struct perf_event_attr', 'exclude_host')
 
+def check_hdf5():
+    return \
+        conf.CheckLibWithHeader('hdf5', 'hdf5.h', 'C',
+                                'H5Fcreate("", 0, 0, 0);') and \
+        conf.CheckLibWithHeader('hdf5_cpp', 'H5Cpp.h', 'C++',
+                                'H5::H5File("", 0);')
+
+def check_hdf5_pkg(name):
+    print("Checking for %s using pkg-config..." % name, end="")
+    if not have_pkg_config:
+        print(" pkg-config not found")
+        return False
+
+    try:
+        main.ParseConfig('pkg-config --cflags-only-I --libs-only-L %s' % name)
+        print(" yes")
+        return True
+    except:
+        print(" no")
+        return False
+
+# Check if there is a pkg-config configuration for hdf5. If we find
+# it, setup the environment to enable linking and header inclusion. We
+# don't actually try to include any headers or link with hdf5 at this
+# stage.
+if not check_hdf5_pkg('hdf5-serial'):
+    check_hdf5_pkg('hdf5')
+
+# Check if the HDF5 libraries can be found. This check respects the
+# include path and library path provided by pkg-config. We perform
+# this check even if there isn't a pkg-config configuration for hdf5
+# since some installations don't use pkg-config.
+have_hdf5 = check_hdf5()
+if not have_hdf5:
+    print("Warning: Couldn't find any HDF5 C++ libraries. Disabling")
+    print("         HDF5 support.")
 
 ######################################################################
 #
@@ -1002,14 +1054,18 @@ sticky_vars.AddVariables(
     EnumVariable('PROTOCOL', 'Coherence protocol for Ruby', 'None',
                   all_protocols),
     EnumVariable('BACKTRACE_IMPL', 'Post-mortem dump implementation',
-                 backtrace_impls[-1], backtrace_impls)
+                 backtrace_impls[-1], backtrace_impls),
+    ('NUMBER_BITS_PER_SET', 'Max elements in set (default 64)',
+                 64),
+    BoolVariable('USE_HDF5', 'Enable the HDF5 support', have_hdf5),
     )
 
 # These variables get exported to #defines in config/*.hh (see src/SConscript).
 export_vars += ['USE_FENV', 'SS_COMPATIBLE_FP', 'TARGET_ISA', 'TARGET_GPU_ISA',
                 'CP_ANNOTATE', 'USE_POSIX_CLOCK', 'USE_KVM', 'USE_TUNTAP',
-                'PROTOCOL', 'HAVE_PROTOBUF', 'HAVE_PERF_ATTR_EXCLUDE_HOST',
-                'USE_PNG']
+                'PROTOCOL', 'HAVE_PROTOBUF', 'HAVE_VALGRIND',
+                'HAVE_PERF_ATTR_EXCLUDE_HOST', 'USE_PNG',
+                'NUMBER_BITS_PER_SET', 'USE_HDF5']
 
 ###################################################
 #
@@ -1078,6 +1134,29 @@ partial_shared_builder = Builder(action=SCons.Defaults.ShLinkAction,
 main.Append(BUILDERS = { 'PartialShared' : partial_shared_builder,
                          'PartialStatic' : partial_static_builder })
 
+def add_local_rpath(env, *targets):
+    '''Set up an RPATH for a library which lives in the build directory.
+
+    The construction environment variable BIN_RPATH_PREFIX should be set to
+    the relative path of the build directory starting from the location of the
+    binary.'''
+    for target in targets:
+        target = env.Entry(target)
+        if not isinstance(target, SCons.Node.FS.Dir):
+            target = target.dir
+        relpath = os.path.relpath(target.abspath, env['BUILDDIR'])
+        components = [
+            '\\$$ORIGIN',
+            '${BIN_RPATH_PREFIX}',
+            relpath
+        ]
+        env.Append(RPATH=[env.Literal(os.path.join(*components))])
+
+if sys.platform != "darwin":
+    main.Append(LINKFLAGS=Split('-z origin'))
+
+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_build_dirs = []
@@ -1088,6 +1167,9 @@ for root, dirs, files in os.walk(ext_dir):
         main.SConscript(joinpath(root, 'SConscript'),
                         variant_dir=joinpath(build_root, build_dir))
 
+gdb_xml_dir = joinpath(ext_dir, 'gdb-xml')
+Export('gdb_xml_dir')
+
 main.Prepend(CPPPATH=Dir('ext/pybind11/include/'))
 
 ###################################################
@@ -1245,6 +1327,9 @@ for variant_path in variant_paths:
     if env['USE_SSE2']:
         env.Append(CCFLAGS=['-msse2'])
 
+    env.Append(CCFLAGS='$CCFLAGS_EXTRA')
+    env.Append(LINKFLAGS='$LDFLAGS_EXTRA')
+
     # 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.)