# 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')

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

# Universal settings.
main.Append(CXXFLAGS=[ '-O2' ])
main.Append(CCFLAGS=[ '-O2' ])
main.Append(CPPPATH=[ common_include ])

# Propogate the environment's PATH setting.
main['ENV']['PATH'] = os.environ['PATH']

# Detect some dependencies of some forms of the m5 utility/library.
main['HAVE_JAVA'] = all(key in main for key in ('JAVAC', 'JAR'))
main['HAVE_PKG_CONFIG'] = main.Detect('pkg-config') is not None
main['HAVE_LUA51'] = (main['HAVE_PKG_CONFIG'] and
                      os.system('pkg-config --exists lua51') == 0)

# 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' ]
    env['GTEST_ENV'].Program('test/%s' % name, srcs, **kwargs)

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={ 'main': 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'

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 get_abi_opt(name, default):
            var_name = env.subst('${ABI}.%s' % name)
            env[name] = os.environ.get(
                    var_name, ARGUMENTS.get(var_name, default))

        # 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' ])

        # 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={ 'main': env })
        env.SConscript(src_dir.File('SConscript'),
                       variant_dir=abi_dir, exports='env')
