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

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

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

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

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

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

main['CC'] = '${CROSS_COMPILE}gcc'
main['AS'] = '${CROSS_COMPILE}as'
main['LD'] = '${CROSS_COMPILE}ld'
main['AR'] = '${CROSS_COMPILE}ar'

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

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

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

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 a variant of the m5 utility.
    if 'SConsopts' in files:
        env = main.Clone()

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

        # The user may override variant settings by setting environment
        # variables of the form ${VARIANT}.${OPTION}. For instance, to set the
        # CROSS_COMPILE prefix for variant 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_variant_opt(name, default):
            var_name = env.subst('${VARIANT}.%s' % name)
            env[name] = os.environ.get(
                    var_name, ARGUMENTS.get(var_name, default))

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

        # Once all the options have been configured, set up build targets for
        # this variant.
        variant_dir = build_dir.Dir(env.subst('${VARIANT}'))
        env.SConscript(src_dir.File('SConscript'),
                       variant_dir=variant_dir, exports='env')
