# Copyright (c) 2013, 2015-2020 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder.  You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2011 Advanced Micro Devices, Inc.
# Copyright (c) 2009 The Hewlett-Packard Development Company
# Copyright (c) 2004-2005 The Regents of The University of Michigan
# All rights reserved.
#
# 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 contextlib
import os

import SCons.Script
import SCons.Util

def CheckCxxFlag(context, flag, autoadd=True):
    context.Message("Checking for compiler %s support... " % flag)
    last_cxxflags = context.env['CXXFLAGS']
    context.env.Append(CXXFLAGS=[flag])
    ret = context.TryCompile('// CheckCxxFlag DO NOTHING', '.cc')
    if not (ret and autoadd):
        context.env['CXXFLAGS'] = last_cxxflags
    context.Result(ret)
    return ret

def CheckLinkFlag(context, flag, autoadd=True, set_for_shared=True):
    context.Message("Checking for linker %s support... " % flag)
    last_linkflags = context.env['LINKFLAGS']
    context.env.Append(LINKFLAGS=[flag])
    ret = context.TryLink('int main(int, char *[]) { return 0; }', '.cc')
    if not (ret and autoadd):
        context.env['LINKFLAGS'] = last_linkflags
    if (ret and set_for_shared):
        assert(autoadd)
        context.env.Append(SHLINKFLAGS=[flag])
    context.Result(ret)
    return ret

# Add a custom Check function to test for structure members.
def CheckMember(context, include, decl, member, include_quotes="<>"):
    context.Message("Checking for member %s in %s..." %
                    (member, decl))
    text = """
#include %(header)s
int main(){
  %(decl)s test;
  (void)test.%(member)s;
  return 0;
};
""" % { "header" : include_quotes[0] + include + include_quotes[1],
        "decl" : decl,
        "member" : member,
        }

    ret = context.TryCompile(text, extension=".cc")
    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(".")))

def CheckPkgConfig(context, pkgs, *args):
    if not SCons.Util.is_List(pkgs):
        pkgs = [pkgs]
    assert(pkgs)

    for pkg in pkgs:
        context.Message('Checking for pkg-config package %s... ' % pkg)
        ret = context.TryAction('pkg-config %s' % pkg)[0]
        if not ret:
            context.Result(ret)
            continue

        if len(args) == 0:
            break

        cmd = ' '.join(['pkg-config'] + list(args) + [pkg])
        try:
            context.env.ParseConfig(cmd)
            ret = 1
            context.Result(ret)
            break
        except Exception as e:
            ret = 0
            context.Result(ret)

    return ret

@contextlib.contextmanager
def Configure(env, *args, **kwargs):
    kwargs.setdefault('conf_dir',
            os.path.join(env['BUILDROOT'], '.scons_config'))
    kwargs.setdefault('log_file',
            os.path.join(env['BUILDROOT'], 'scons_config.log'))
    kwargs.setdefault('custom_tests', {})
    kwargs['custom_tests'].update({
            'CheckCxxFlag' : CheckCxxFlag,
            'CheckLinkFlag' : CheckLinkFlag,
            'CheckMember' : CheckMember,
            'CheckPkgConfig' : CheckPkgConfig,
            'CheckPythonLib' : CheckPythonLib,
    })
    conf = SCons.Script.Configure(env, *args, **kwargs)

    # Recent versions of scons substitute a "Null" object for Configure()
    # when configuration isn't necessary, e.g., if the "--help" option is
    # present.  Unfortuantely this Null object always returns false,
    # breaking all our configuration checks.  We replace it with our own
    # more optimistic null object that returns True instead.
    if not conf:
        def NullCheck(*args, **kwargs):
            return True

        class NullConf:
            def __init__(self, env):
                self.env = env
            def Finish(self):
                return self.env
            def __getattr__(self, mname):
                return NullCheck

        conf = NullConf(main)

    try:
        yield conf
    finally:
        env.Replace(**conf.Finish().Dictionary())
