# Copyright (c) 2017-2019 Arm Limited.
#
# SPDX-License-Identifier: MIT
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import SCons
import os.path

Import('env')
Import('vars')
Import('install_bin')

# vars is imported from arm_compute:
variables = [
    BoolVariable("benchmark_examples", "Build benchmark examples programs", True),
    BoolVariable("validate_examples", "Build validate examples programs", True),
    BoolVariable("reference_openmp", "Build reference validation with openmp", True),
    BoolVariable("validation_tests", "Build validation test programs", False),
    BoolVariable("benchmark_tests", "Build benchmark test programs", False),
    ("test_filter", "Pattern to specify the tests' filenames to be compiled", "*.cpp")
]

# We need a separate set of Variables for the Help message (Otherwise the global variables will get displayed twice)
new_options = Variables('scons')

for v in variables:
    new_options.Add(v)
    vars.Add(v)

# Clone the environment to make sure we're not polluting the arm_compute one:
test_env = env.Clone()
vars.Update(test_env)

Help(new_options.GenerateHelpText(test_env))

# Check if we need to build the test framework
build_test_framework = False
for opt in new_options.keys():
    option_value = test_env[opt]
    if type(option_value) is bool and option_value:
        build_test_framework = True
        break

if not build_test_framework:
    Return()
else:
    SConscript('./framework/SConscript', duplicate=0)

Import("arm_compute_test_framework")
test_env.Append(LIBS = arm_compute_test_framework)

# Disable floating-point expression contraction (e.g. fused multiply-add operations)
test_env.Append(CXXFLAGS = ['-ffp-contract=off'])

# Remove -Wnoexcept from tests
if 'g++' in test_env['CXX'] and '-Wnoexcept' in test_env['CXXFLAGS']:
    test_env['CXXFLAGS'].remove("-Wnoexcept")

if env['os'] in ['android', 'bare_metal'] or env['standalone']:
    Import("arm_compute_a")
    Import("arm_compute_core_a")
    Import("arm_compute_graph_a")
    test_env.Append(LIBS = [arm_compute_graph_a, arm_compute_a, arm_compute_core_a])
    arm_compute_lib = arm_compute_graph_a
else:
    Import("arm_compute_graph_so")
    Import("arm_compute_core_a")
    test_env.Append(LIBS = ["arm_compute_graph", "arm_compute", "arm_compute_core"])
    arm_compute_lib = arm_compute_graph_so

if env['os'] in ['bare_metal']:
    Import("bootcode_o")

test_env.Append(CPPPATH = ["#3rdparty/include"])
test_env.Append(LIBPATH = ["#3rdparty/%s/%s" % (env['os'], env['arch'])])

common_files = Glob('*.cpp')
common_objects = [test_env.StaticObject(f) for f in common_files]

files_benchmark = Glob('benchmark/*.cpp')

# Add unit tests
files_validation = Glob('validation/UNIT/*/*.cpp')
files_validation += Glob('validation/UNIT/*.cpp')

# Add CPP tests
filter_pattern = test_env['test_filter']
files_validation += Glob('validation/CPP/' + filter_pattern)

if env['opencl']:
    filter_pattern = test_env['test_filter']

    test_env.Append(CPPDEFINES=['ARM_COMPUTE_CL'])

    files_benchmark += Glob('benchmark/CL/*/' + filter_pattern)
    files_benchmark += Glob('benchmark/CL/' + filter_pattern)
    files_validation += Glob('validation/CL/*/' + filter_pattern)
    files_validation += Glob('validation/CL/' + filter_pattern)

if env['neon']:
    filter_pattern = test_env['test_filter']
    files_benchmark += Glob('benchmark/NEON/*/' + filter_pattern)
    files_benchmark += Glob('benchmark/NEON/' + filter_pattern)
    files_validation += Glob('validation/NEON/' + filter_pattern)
    if env['os'] == 'bare_metal':
        files_validation += Glob('validation/NEON/UNIT/MemoryManager.cpp' + filter_pattern)
        files_validation += Glob('validation/NEON/UNIT/DynamicTensor.cpp' + filter_pattern)
        files_validation += Glob('validation/NEON/UNIT/TensorAllocator.cpp' + filter_pattern)
    else:
        files_validation += Glob('validation/NEON/*/' + filter_pattern)


if env['gles_compute']:
    test_env.Append(CPPDEFINES=['ARM_COMPUTE_GC'])

    files_benchmark += Glob('benchmark/GLES_COMPUTE/*/*.cpp')
    files_benchmark += Glob('benchmark/GLES_COMPUTE/*.cpp')

    files_validation += Glob('validation/GLES_COMPUTE/*/*.cpp')
    files_validation += Glob('validation/GLES_COMPUTE/*.cpp')

extra_link_flags = []
if env['os'] == 'android':
    test_env.Append(LIBS = ["log"])
elif env['os'] != 'bare_metal':
    test_env.Append(LIBS = ["rt"])
    extra_link_flags += ['-fstack-protector-strong']

if test_env['benchmark_tests']:
    arm_compute_benchmark = test_env.Program('arm_compute_benchmark', files_benchmark + common_objects)
    arm_compute_benchmark = install_bin(arm_compute_benchmark)
    Depends(arm_compute_benchmark, arm_compute_test_framework)
    Depends(arm_compute_benchmark, arm_compute_lib)
    Default(arm_compute_benchmark)
    Export('arm_compute_benchmark')

bm_link_flags = []
if test_env['linker_script']:
    bm_link_flags += ['-Wl,--build-id=none', '-T', env['linker_script']]

if test_env['reference_openmp'] and env['os'] != 'bare_metal':
   test_env['CXXFLAGS'].append('-fopenmp')
   test_env['LINKFLAGS'].append('-fopenmp')

if test_env['validation_tests']:
    arm_compute_validation_framework = env.StaticLibrary('arm_compute_validation_framework', Glob('validation/reference/*.cpp') + Glob('validation/*.cpp'), LINKFLAGS=test_env['LINKFLAGS'], CXXFLAGS=test_env['CXXFLAGS'], LIBS= [ arm_compute_test_framework, arm_compute_core_a])
    Depends(arm_compute_validation_framework , arm_compute_test_framework)
    Depends(arm_compute_validation_framework , arm_compute_core_a)

    program_objects = files_validation + common_objects
    if test_env['os'] == 'bare_metal':
        Depends(arm_compute_validation_framework , bootcode_o)
        program_objects += bootcode_o


    arm_compute_validation = test_env.Program('arm_compute_validation', program_objects, LIBS=[arm_compute_validation_framework] + test_env['LIBS'], LINKFLAGS=test_env['LINKFLAGS'] + bm_link_flags)
    arm_compute_validation = install_bin(arm_compute_validation)
    Depends(arm_compute_validation, arm_compute_validation_framework)
    Depends(arm_compute_validation, arm_compute_test_framework)
    Depends(arm_compute_validation, arm_compute_lib)

    Default(arm_compute_validation)
    Export('arm_compute_validation')

    if test_env['validate_examples']:
        files_validate_examples = [ test_env.Object('validate_examples/RunExample.cpp') ] + [ x for x in common_objects if not "main.o" in str(x)]
        if test_env['os'] == 'bare_metal':
            files_validate_examples += bootcode_o

        arm_compute_validate_examples = []
        if test_env['neon']:
            for file in Glob("validate_examples/neon_*.cpp"):
                example = "validate_" + os.path.basename(os.path.splitext(str(file))[0])
                arm_compute_validate_examples += [ test_env.Program(example, [ test_env.Object(source=file, target=example) ] + files_validate_examples, LIBS = [ arm_compute_validation_framework], LINKFLAGS=test_env['LINKFLAGS'] + bm_link_flags) ]
        if test_env['opencl']:
            cl_examples = []
            files = Glob("validate_examples/cl_*.cpp")
            if test_env['neon']:
                files += Glob("validate_examples/neoncl_*.cpp")
            for file in files:
                example = "validate_" + os.path.basename(os.path.splitext(str(file))[0])
                cl_examples += [ test_env.Program(example, [ test_env.Object(source=file, target=example) ] + files_validate_examples, LIBS = test_env["LIBS"] + [ arm_compute_validation_framework ]) ]
            arm_compute_validate_examples += cl_examples
            if test_env['opencl'] and test_env['neon']:
                graph_utils = test_env.Object(source="../utils/GraphUtils.cpp", target="GraphUtils")
                for file in Glob("validate_examples/graph_*.cpp"):
                    example = "validate_" + os.path.basename(os.path.splitext(str(file))[0])
                    if env['os'] in ['android', 'bare_metal'] or env['standalone']:
                        prog = test_env.Program(example, [ test_env.Object(source=file, target=example), graph_utils]+ files_validate_examples, LIBS = test_env["LIBS"] + [ arm_compute_validation_framework ], LINKFLAGS=test_env["LINKFLAGS"]+['-Wl,--whole-archive',arm_compute_lib,'-Wl,--no-whole-archive'] + bm_link_flags + extra_link_flags)
                        arm_compute_validate_examples += [ prog ]
                    else:
                        #-Wl,--allow-shlib-undefined: Ignore dependencies of dependencies
                        prog = test_env.Program(example, [ test_env.Object(source=file, target=example), graph_utils]+ files_validate_examples, LIBS = test_env["LIBS"] + ["arm_compute_graph", arm_compute_validation_framework], LINKFLAGS=test_env["LINKFLAGS"]+['-Wl,--allow-shlib-undefined'] )
                        arm_compute_validate_examples += [ prog ]
        arm_compute_validate_examples = install_bin(arm_compute_validate_examples)
        Depends(arm_compute_validate_examples, arm_compute_validation_framework)
        Depends(arm_compute_validate_examples, arm_compute_test_framework)
        Depends(arm_compute_validate_examples, arm_compute_lib)
        Default(arm_compute_validate_examples)
        Export('arm_compute_validate_examples')

if test_env['benchmark_examples']:
    files_benchmark_examples = test_env.Object('benchmark_examples/RunExample.cpp')
    if test_env['os'] == 'bare_metal':
        files_benchmark_examples += bootcode_o
    graph_utils = test_env.Object(source="../utils/GraphUtils.cpp", target="GraphUtils")
    graph_params = test_env.Object(source="../utils/CommonGraphOptions.cpp", target="CommonGraphOptions")
    arm_compute_benchmark_examples = []
    for examples_folder in [ "../examples", "../3rdparty/examples"]:
        if test_env['neon']:
            for file in Glob("%s/neon_*.cpp" % examples_folder):
                example = "benchmark_" + os.path.basename(os.path.splitext(str(file))[0])
                arm_compute_benchmark_examples += [ test_env.Program(example, [ test_env.Object(source=file, target=example) ] + files_benchmark_examples, LINKFLAGS=test_env["LINKFLAGS"]+ bm_link_flags) ]
        if test_env['opencl']:
            cl_examples = []
            files = Glob("%s/cl_*.cpp" % examples_folder)
            if test_env['neon']:
                files += Glob("%s/neoncl_*.cpp" % examples_folder)
            for file in files:
                example = "benchmark_" + os.path.basename(os.path.splitext(str(file))[0])
                cl_examples += [ test_env.Program(example, [ test_env.Object(source=file, target=example) ] + files_benchmark_examples, LIBS = test_env["LIBS"]) ]
            arm_compute_benchmark_examples += cl_examples

        if test_env['gemm_tuner'] and test_env['opencl']:
            gemm_tuner_examples = []
            gemm_tuner_common_options = test_env.Object(source="../examples/gemm_tuner/CommonGemmExampleOptions.cpp", target="CommonGemmExampleOptions")
            files = Glob("%s/gemm_tuner/cl_*.cpp" % examples_folder)
            for file in files:
                example = "benchmark_" + os.path.basename(os.path.splitext(str(file))[0])
                example = os.path.join("gemm_tuner", example)
                gemm_tuner_examples += [ test_env.Program(example, [ test_env.Object(source=file, target=example), gemm_tuner_common_options ] + files_benchmark_examples, LIBS = test_env["LIBS"]) ]
            arm_compute_benchmark_examples += gemm_tuner_examples

        # Graph examples
        for file in Glob("%s/graph_*.cpp" % examples_folder ):
            example = "benchmark_" + os.path.basename(os.path.splitext(str(file))[0])
            if env['os'] in ['android', 'bare_metal'] or env['standalone']:
                prog = test_env.Program(example, [ test_env.Object(source=file, target=example), graph_utils, graph_params]+ files_benchmark_examples, LIBS = test_env["LIBS"], LINKFLAGS=test_env["LINKFLAGS"]+['-Wl,--whole-archive',arm_compute_lib,'-Wl,--no-whole-archive'] + bm_link_flags + extra_link_flags)
                arm_compute_benchmark_examples += [ prog ]
            else:
                #-Wl,--allow-shlib-undefined: Ignore dependencies of dependencies
                prog = test_env.Program(example, [ test_env.Object(source=file, target=example), graph_utils, graph_params]+ files_benchmark_examples, LIBS = test_env["LIBS"] + ["arm_compute_graph"], LINKFLAGS=test_env["LINKFLAGS"]+['-Wl,--allow-shlib-undefined'])
                arm_compute_benchmark_examples += [ prog ]
    arm_compute_benchmark_examples = install_bin(arm_compute_benchmark_examples)
    Depends(arm_compute_benchmark_examples, arm_compute_test_framework)
    Depends(arm_compute_benchmark_examples, arm_compute_lib)
    Default(arm_compute_benchmark_examples)
    Export('arm_compute_benchmark_examples')
