# Copyright 2020 Google, Inc.
#
# 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.

import copy
import os

main = Environment()

gem5_root = Dir('..').Dir('..')

# Includes which are shared with gem5 itself.
common_include = gem5_root.Dir('include')

ext_dir = gem5_root.Dir('ext')
googletest_dir = ext_dir.Dir('googletest')

src_dir = Dir('src')
build_dir = Dir('build')

main.SConsignFile(build_dir.File("sconsign").abspath)

def abspath(d):
    return os.path.abspath(str(d))

AddOption('--debug-build', dest='debug_build', action='store_true',
          help='Build with debug info, and disable optimizations.')
AddOption('--run-tests', dest='run_tests', action='store_true',
          help='Enable test output xml files as build targets.')
AddOption('--verbose', dest='verbose', action='store_true')

# Universal settings.
if GetOption('debug_build'):
    main.Append(CXXFLAGS=[ '-O0', '-g' ])
    main.Append(CCFLAGS=[ '-O0', '-g' ])
else:
    main.Append(CXXFLAGS=[ '-O2' ])
    main.Append(CCFLAGS=[ '-O2' ])
main.Append(CPPPATH=[ common_include ])
main.Append(CXXFLAGS=[ '-std=c++14' ])

if not GetOption('verbose'):
    # A functor which returns a shorter summary string to replace the normal
    # scons output when running a command.
    class ComStr(object):
        def __init__(self, cmd):
            self.cmd = cmd

        def __call__(self, target, source, env, for_signature=None):
            tgts = list([str(t).strip() for t in target])
            return self.cmd + ' ' + ', '.join(tgts)
    main['CXXCOMSTR'] = ComStr('CXX')
    main['SHCXXCOMSTR'] = ComStr('SHCXX')
    main['CCCOMSTR'] = ComStr('CC')
    main['SHCCCOMSTR'] = ComStr('SHCC')
    main['LINKCOMSTR'] = ComStr('LINK')
    main['SHLINKCOMSTR'] = ComStr('SHLINK')
    main['ASCOMSTR'] = ComStr('AS')
    main['ASPPCOMSTR'] = ComStr('ASPP')
    main['ARCOMSTR'] = ComStr('AR')
    main['RANLIBCOMSTR'] = ComStr('RANLIB')
    main['JARCOMSTR'] = ComStr('JAR')

    def MakeAction(action, string, *args, **kwargs):
        def func(target, source, env, executor):
            tgts = list([str(t).strip() for t in target])
            return string + ' ' + ', '.join(tgts)
        return Action(action, func, *args, **kwargs)
else:
    def MakeAction(action, string, *args, **kwargs):
        return Action(action, *args, **kwargs)

# Propogate the environment's PATH setting.
main['ENV']['PATH'] = os.environ['PATH']
# Pass through terminal information to, for instance, enable color output.
if 'TERM' in os.environ:
    main['ENV']['TERM'] = os.environ['TERM']
# Pass through the java CLASSPATH (if it exists) so we can find libraries.
main['ENV']['CLASSPATH'] = os.environ.get('CLASSPATH', '')

# Detect some dependencies of some forms of the m5 utility/library.
def CheckForJavaPkg(context, pkg_name):
    context.Message('Checking for java package %s...' % pkg_name)
    result = main['HAVE_JAVA'] and \
             context.TryAction('${JAVAC} ${JAVACFLAGS} ${SOURCES}',
                               'import %s.*;' % pkg_name, '.java')[0]
    context.Result(result)
    return result

def CheckForPkgConfigPackage(context, package):
    context.Message('Checking for pkg-config package %s...' % package)
    result = main['HAVE_PKG_CONFIG'] and \
             os.system('pkg-config --exists %s' % package) == 0
    context.Result(result)
    return result;

conf = Configure(main, conf_dir=build_dir.Dir('.scons_config'),
        log_file=build_dir.File('scons_config.log'), custom_tests={
        'CheckForJavaPkg' : CheckForJavaPkg,
        'CheckForPkgConfigPackage' : CheckForPkgConfigPackage
})
main['HAVE_JAVA'] = all(key in main for key in ('JAVAC', 'JAR'))
if not main['HAVE_JAVA']:
    print('javac and/or jar not detected, not building java wrapper.')

main['HAVE_JUNIT'] = conf.CheckForJavaPkg('org.junit')
if main['HAVE_JAVA'] and not main['HAVE_JUNIT']:
    print('junit test framework not found, not build java wrapper test')

main['HAVE_PKG_CONFIG'] = conf.CheckProg('pkg-config')
if not main['HAVE_PKG_CONFIG']:
    print("pkg-config not detected, can't check for lua51.")

main['HAVE_LUA51'] = conf.CheckForPkgConfigPackage('lua51')
if not main['HAVE_LUA51']:
    print('lua 5.1 not detected, not building lua wrapper.')

conf.Finish()

# Put the sconsign file in the build dir so everything can be deleted at once.
main.SConsignFile(os.path.join(abspath(build_dir), 'sconsign'))
# Use soft links instead of hard links when setting up a build directory.
main.SetOption('duplicate', 'soft-copy')

def GTest(env, name, *srcs, **kwargs):
    if 'GTEST_ENV' not in env:
        gtest_env = env.Clone(OBJSUFFIX='.to', SHOBJSUFFIX='.sto')
        gtest_env.Append(CPPFLAGS=[ '${GTEST_CPPFLAGS}' ])
        gtest_env.Append(LIBS=[ '${GTEST_LIBS}' ])
        env['GTEST_ENV'] = gtest_env

    if not srcs:
        srcs = [ name + '.cc', name + '.test.cc' ]
    test_bin = env['GTEST_ENV'].Program('test/bin/%s' % name, srcs, **kwargs)

    # The native environment doesn't need QEMU, and doesn't define HAVE_QEMU.
    need_qemu_to_run = 'HAVE_QEMU' in env;

    # If we can run this test...
    if GetOption('run_tests') and (not need_qemu_to_run or env['HAVE_QEMU']):
        # An XML file which holds the results of the test.
        xml = Dir('test').Dir('result').File('%s.xml' % name)
        # The basic command line for the test.
        cmd = '${SOURCES[0]} --gtest_output=xml:${TARGETS[0]}'
        cmd_str = 'TEST'
        if need_qemu_to_run:
            # A prefix that runs it in QEMU if necessary.
            cmd = '${QEMU} -L ${QEMU_SYSROOT} -- ' + cmd
            cmd_str = 'QEMU_TEST'
        AlwaysBuild(env.Command(xml, test_bin, MakeAction(cmd, cmd_str)))

Export('MakeAction')

main.AddMethod(GTest)

native = main.Clone()
native_dir = build_dir.Dir('native')

# Bring in the googletest sources.
native.SConscript(googletest_dir.File('SConscript'),
        variant_dir=native_dir.Dir('googletest'), exports={ 'env': native })

native.SConscript(src_dir.File('SConscript.native'),
        variant_dir=native_dir, exports={ 'env': native })

main['CC'] = '${CROSS_COMPILE}gcc'
main['CXX'] = '${CROSS_COMPILE}g++'
main['AS'] = '${CROSS_COMPILE}as'
main['LD'] = '${CROSS_COMPILE}ld'
main['AR'] = '${CROSS_COMPILE}ar'
main['QEMU'] = 'qemu-${QEMU_ARCH}'

class CallType(object):
    def __init__(self, name):
        self.name = name
        self.impl_file = None
        self.enabled = False
        self.verifier = None
        self.default = False

    def impl(self, impl, verifier=None, default=False):
        self.impl_file = impl
        self.enabled = True
        self.verifier = verifier
        self.default = default

    # Being the default can be disabled for testing purposes, so we can tell if
    # a call type was selected because it was chosen, or because nobody else
    # was.
    def setup_env(self, env, allow_default=True):
        env = env.Clone()
        is_default = 'true' if self.default and allow_default else 'false'
        env.Append(CXXFLAGS=[ '-DCALL_TYPE_IS_DEFAULT=%s' % is_default ])
        return env

call_types = {
    # Magic instruction.
    'inst': CallType('inst'),
    # Magic address.
    'addr': CallType('addr'),
    # Semihosting extension.
    'semi': CallType('semi'),
}

for root, dirs, files in os.walk(abspath(src_dir)):
    # Each SConsopts file describes an ABI of the m5 utility.
    if 'SConsopts' in files:
        env = main.Clone()

        env['CALL_TYPE'] = copy.deepcopy(call_types)

        # The user may override ABI settings by setting environment
        # variables of the form ${ABI}.${OPTION}. For instance, to set the
        # CROSS_COMPILE prefix for abi foo to bar-, the user would set an
        # environment variable foo.CROSS_COMPILE=bar-.
        #
        # This also considers scons command line settings which may look like
        # environment variables, but are set after "scons" on the command line.
        def _extract_abi_opt_val(name, default):
            var_name = env.subst('${ABI}.%s' % name)
            return os.environ.get(var_name, ARGUMENTS.get(var_name, default))
        def get_abi_opt(name, default):
            env[name] = _extract_abi_opt_val(name, default)
        def append_abi_opt(name):
            env.Append(**{ name: _extract_abi_opt_val(name, '') })

        # Process the ABI's settings in the SConsopts file, storing them
        # in a copy of the primary environment.
        env.SConscript(Dir(root).File('SConsopts'),
                       exports=[ 'env', 'get_abi_opt' ])

        # The user can pass extra build flags for each ABI
        append_abi_opt('CCFLAGS')
        append_abi_opt('CXXFLAGS')
        append_abi_opt('LINKFLAGS')

        # Check if this version of QEMU is available for running unit tests.
        env['HAVE_QEMU'] = env.Detect('${QEMU}') is not None
        if env['HAVE_QEMU'] and env.Detect('${CC}'):
            sysroot_cmd = env.subst('${CC} -print-sysroot')
            sysroot = os.popen(sysroot_cmd).read().strip()
            env['QEMU_SYSROOT'] = sysroot

        # Once all the options have been configured, set up build targets for
        # this abi.
        abi_dir = build_dir.Dir(env.subst('${ABI}'))
        # Bring in the googletest sources.
        env.SConscript(googletest_dir.File('SConscript'),
                variant_dir=abi_dir.Dir('googletest'),
                exports='env')
        env.SConscript(src_dir.File('SConscript'),
                       variant_dir=abi_dir, exports='env')
