1#!/usr/bin/python 2# -*- coding: utf-8 -*- 3 4# Copyright (c) 2017-2022 Arm Limited. 5# 6# SPDX-License-Identifier: MIT 7# 8# Permission is hereby granted, free of charge, to any person obtaining a copy 9# of this software and associated documentation files (the "Software"), to 10# deal in the Software without restriction, including without limitation the 11# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12# sell copies of the Software, and to permit persons to whom the Software is 13# furnished to do so, subject to the following conditions: 14# 15# The above copyright notice and this permission notice shall be included in all 16# copies or substantial portions of the Software. 17# 18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24# SOFTWARE. 25import os.path 26 27Import('env') 28Import('vars') 29Import('install_bin') 30 31# vars is imported from arm_compute: 32variables = [ 33 BoolVariable("benchmark_examples", "Build benchmark examples programs", False), 34 BoolVariable("validate_examples", "Build validate examples programs", False), 35 BoolVariable("reference_openmp", "Build reference validation with openmp", True), 36 BoolVariable("validation_tests", "Build validation test programs", False), 37 BoolVariable("benchmark_tests", "Build benchmark test programs", False), 38 ("test_filter", "Pattern to specify the tests' filenames to be compiled", "*.cpp") 39] 40 41# We need a separate set of Variables for the Help message (Otherwise the global variables will get displayed twice) 42new_options = Variables('scons') 43 44for v in variables: 45 new_options.Add(v) 46 vars.Add(v) 47 48# Clone the environment to make sure we're not polluting the arm_compute one: 49test_env = env.Clone() 50vars.Update(test_env) 51 52Help(new_options.GenerateHelpText(test_env)) 53 54# Check if we need to build the test framework 55build_test_framework = False 56for opt in new_options.keys(): 57 option_value = test_env[opt] 58 if type(option_value) is bool and option_value: 59 build_test_framework = True 60 break 61 62if not build_test_framework: 63 Return() 64else: 65 SConscript('./framework/SConscript', duplicate=0) 66 67Import("arm_compute_test_framework") 68test_env.Append(LIBS = arm_compute_test_framework) 69 70# Disable floating-point expression contraction (e.g. fused multiply-add operations) 71if not 'windows' in env['os']: 72 test_env.Append(CXXFLAGS = ['-ffp-contract=off']) 73 74# Remove -Wnoexcept from tests 75if 'g++' in test_env['CXX'] and '-Wnoexcept' in test_env['CXXFLAGS']: 76 test_env['CXXFLAGS'].remove("-Wnoexcept") 77 78load_whole_archive = '-Wl,--whole-archive' 79noload_whole_archive = '-Wl,--no-whole-archive' 80if 'macos' in test_env['os']: 81 load_whole_archive = '-Wl,-force_load' 82 noload_whole_archive = '-Wl,-noall_load' 83 84if env['os'] in ['android', 'macos', 'bare_metal'] or env['standalone']: 85 Import("arm_compute_a") 86 Import("arm_compute_core_a") 87 Import("arm_compute_graph_a") 88 if env['os']=='windows': 89 test_env.Append(LIBS = [arm_compute_graph_a, arm_compute_a]) 90 else: 91 test_env.Append(LIBS = [arm_compute_graph_a, arm_compute_a, arm_compute_core_a]) 92 arm_compute_lib = arm_compute_graph_a 93else: 94 Import("arm_compute_graph_so") 95 Import("arm_compute_core_a") 96 test_env.Append(LIBS = ["arm_compute_graph", "arm_compute", "arm_compute_core"]) 97 arm_compute_lib = arm_compute_graph_so 98 99if env['os'] in ['bare_metal']: 100 Import("bootcode_o") 101 102if env['external_tests_dir']: 103 test_env.Append(CPPPATH = [env['external_tests_dir'] + "/include"]) 104 test_env.Append(LIBPATH = [env['external_tests_dir'] + "/%s/%s" % (env['os'], env['arch'])]) 105 106common_files = Glob('*.cpp') 107common_objects = [test_env.StaticObject(f) for f in common_files] 108 109files_benchmark = Glob('benchmark/*.cpp') 110if env['external_tests_dir']: 111 files_benchmark += Glob(env['external_tests_dir'] + '/tests/benchmark/*.cpp') 112 113# Add unit tests 114files_validation = Glob('validation/UNIT/*/*.cpp') 115files_validation += Glob('validation/UNIT/*.cpp') 116 117# Add CPP tests 118filter_pattern = test_env['test_filter'] 119files_validation += Glob('validation/CPP/' + filter_pattern) 120 121if env['opencl']: 122 if env['experimental_dynamic_fusion']: 123 files_validation += Glob('validation/dynamic_fusion/gpu/' + filter_pattern) 124 files_validation += Glob('validation/dynamic_fusion/gpu/cl/' + filter_pattern) 125 126 filter_pattern = test_env['test_filter'] 127 128 test_env.Append(CPPDEFINES=['ARM_COMPUTE_CL']) 129 130 files_benchmark += Glob('benchmark/CL/*/' + filter_pattern) 131 files_benchmark += Glob('benchmark/CL/' + filter_pattern) 132 if env['external_tests_dir']: 133 files_benchmark += Glob(env['external_tests_dir'] + '/tests/benchmark/CL/' + filter_pattern) 134 135 files_validation += Glob('validation/CL/*/' + filter_pattern) 136 files_validation += Glob('validation/CL/' + filter_pattern) 137 138 if env['external_tests_dir']: 139 files_validation += Glob(env['external_tests_dir'] + '/tests/validation/CL/' + filter_pattern) 140 files_validation += Glob('validation/gpu/unit/*.cpp') 141 142if env['neon']: 143 filter_pattern = test_env['test_filter'] 144 files_benchmark += Glob('benchmark/NEON/*/' + filter_pattern) 145 files_benchmark += Glob('benchmark/NEON/' + filter_pattern) 146 test_env.Append(CPPPATH = ["#/src/cpu/kernels/assembly/"]) 147 if env['external_tests_dir']: 148 files_benchmark += Glob(env['external_tests_dir'] + '/tests/benchmark/NEON/' + filter_pattern) 149 150 files_validation += Glob('validation/NEON/' + filter_pattern) 151 if env['os'] == 'bare_metal': 152 files_validation += Glob('validation/NEON/UNIT/MemoryManager.cpp' + filter_pattern) 153 files_validation += Glob('validation/NEON/UNIT/DynamicTensor.cpp' + filter_pattern) 154 files_validation += Glob('validation/NEON/UNIT/TensorAllocator.cpp' + filter_pattern) 155 else: 156 files_validation += Glob('validation/NEON/*/' + filter_pattern) 157 if env['external_tests_dir']: 158 files_validation += Glob(env['external_tests_dir'] + '/tests/validation/NEON/' + filter_pattern) 159 files_validation += Glob('validation/cpu/unit/*.cpp') 160 161extra_link_flags = [] 162if env['os'] == 'android': 163 test_env.Append(LIBS = ["log"]) 164elif env['os'] not in ['windows','bare_metal', 'macos']: 165 test_env.Append(LIBS = ["rt"]) 166 extra_link_flags += ['-fstack-protector-strong'] 167 168if test_env['benchmark_tests']: 169 arm_compute_benchmark = test_env.Program('arm_compute_benchmark', files_benchmark + common_objects) 170 arm_compute_benchmark = install_bin(arm_compute_benchmark) 171 Depends(arm_compute_benchmark, arm_compute_test_framework) 172 Depends(arm_compute_benchmark, arm_compute_lib) 173 Default(arm_compute_benchmark) 174 Export('arm_compute_benchmark') 175 176bm_link_flags = [] 177if test_env['linker_script']: 178 bm_link_flags += ['-Wl,--build-id=none', '-T', env['linker_script']] 179 180if test_env['reference_openmp'] and env['os'] not in ['bare_metal', 'macos','windows']: 181 test_env['CXXFLAGS'].append('-fopenmp') 182 test_env['LINKFLAGS'].append('-fopenmp') 183 184 if 'ndk_above_r21' in env: 185 test_env['LINKFLAGS'].append('-static-openmp') 186 187# Testing for fixed format GEMM kernels. 188if env['experimental_fixed_format_kernels'] and test_env['validation_tests']: 189 test_env.Append(CPPDEFINES = ['ARM_COMPUTE_ENABLE_FIXED_FORMAT_KERNELS']) 190 191if test_env['validation_tests']: 192 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]) 193 Depends(arm_compute_validation_framework , arm_compute_test_framework) 194 Depends(arm_compute_validation_framework , arm_compute_core_a) 195 196 program_objects = files_validation + common_objects 197 if test_env['os'] == 'bare_metal': 198 Depends(arm_compute_validation_framework , bootcode_o) 199 program_objects += bootcode_o 200 201 202 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) 203 arm_compute_validation = install_bin(arm_compute_validation) 204 Depends(arm_compute_validation, arm_compute_validation_framework) 205 Depends(arm_compute_validation, arm_compute_test_framework) 206 Depends(arm_compute_validation, arm_compute_lib) 207 208 Default(arm_compute_validation) 209 Export('arm_compute_validation') 210 211 if test_env['validate_examples']: 212 files_validate_examples = [ test_env.Object('validate_examples/RunExample.cpp') ] + [ x for x in common_objects if not "main.o" in str(x)] 213 if test_env['os'] == 'bare_metal': 214 files_validate_examples += bootcode_o 215 216 arm_compute_validate_examples = [] 217 if test_env['neon']: 218 for file in Glob("validate_examples/neon_*.cpp"): 219 example = "validate_" + os.path.basename(os.path.splitext(str(file))[0]) 220 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) ] 221 if test_env['opencl']: 222 cl_examples = [] 223 files = Glob("validate_examples/cl_*.cpp") 224 if test_env['neon']: 225 files += Glob("validate_examples/neoncl_*.cpp") 226 for file in files: 227 example = "validate_" + os.path.basename(os.path.splitext(str(file))[0]) 228 cl_examples += [ test_env.Program(example, [ test_env.Object(source=file, target=example) ] + files_validate_examples, LIBS = test_env["LIBS"] + [ arm_compute_validation_framework ]) ] 229 arm_compute_validate_examples += cl_examples 230 if test_env['opencl'] and test_env['neon']: 231 graph_utils = test_env.Object(source="../utils/GraphUtils.cpp", target="GraphUtils") 232 for file in Glob("validate_examples/graph_*.cpp"): 233 example = "validate_" + os.path.basename(os.path.splitext(str(file))[0]) 234 if env['os'] in ['android', 'macos', 'bare_metal'] or env['standalone']: 235 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"]+[load_whole_archive, arm_compute_lib, noload_whole_archive] + bm_link_flags + extra_link_flags) 236 arm_compute_validate_examples += [ prog ] 237 else: 238 #-Wl,--allow-shlib-undefined: Ignore dependencies of dependencies 239 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'] ) 240 arm_compute_validate_examples += [ prog ] 241 arm_compute_validate_examples = install_bin(arm_compute_validate_examples) 242 Depends(arm_compute_validate_examples, arm_compute_validation_framework) 243 Depends(arm_compute_validate_examples, arm_compute_test_framework) 244 Depends(arm_compute_validate_examples, arm_compute_lib) 245 Default(arm_compute_validate_examples) 246 Export('arm_compute_validate_examples') 247 248if test_env['benchmark_examples']: 249 files_benchmark_examples = test_env.Object('benchmark_examples/RunExample.cpp') 250 if test_env['os'] == 'bare_metal': 251 files_benchmark_examples += bootcode_o 252 graph_utils = test_env.Object(source="../utils/GraphUtils.cpp", target="GraphUtils") 253 graph_params = test_env.Object(source="../utils/CommonGraphOptions.cpp", target="CommonGraphOptions") 254 arm_compute_benchmark_examples = [] 255 all_examples_folders = ["../examples"] 256 if env['external_tests_dir']: 257 all_examples_folders.append(env['external_tests_dir'] + "/examples") 258 for examples_folder in all_examples_folders: 259 if test_env['neon']: 260 for file in Glob("%s/neon_*.cpp" % examples_folder): 261 example = "benchmark_" + os.path.basename(os.path.splitext(str(file))[0]) 262 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) ] 263 if test_env['opencl']: 264 cl_examples = [] 265 files = Glob("%s/cl_*.cpp" % examples_folder) 266 if test_env['neon']: 267 files += Glob("%s/neoncl_*.cpp" % examples_folder) 268 for file in files: 269 example = "benchmark_" + os.path.basename(os.path.splitext(str(file))[0]) 270 cl_examples += [ test_env.Program(example, [ test_env.Object(source=file, target=example) ] + files_benchmark_examples, LIBS = test_env["LIBS"]) ] 271 arm_compute_benchmark_examples += cl_examples 272 273 if test_env['gemm_tuner'] and test_env['opencl']: 274 gemm_tuner_examples = [] 275 gemm_tuner_common_options = test_env.Object(source="../examples/gemm_tuner/CommonGemmExampleOptions.cpp", target="CommonGemmExampleOptions") 276 files = Glob("%s/gemm_tuner/cl_*.cpp" % examples_folder) 277 for file in files: 278 example = "benchmark_" + os.path.basename(os.path.splitext(str(file))[0]) 279 example = os.path.join("gemm_tuner", example) 280 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"]) ] 281 arm_compute_benchmark_examples += gemm_tuner_examples 282 283 # Graph examples 284 for file in Glob("%s/graph_*.cpp" % examples_folder ): 285 example = "benchmark_" + os.path.basename(os.path.splitext(str(file))[0]) 286 if env['os'] in ['android', 'macos', 'bare_metal'] or env['standalone']: 287 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"]+[load_whole_archive, arm_compute_lib, noload_whole_archive] + bm_link_flags + extra_link_flags) 288 arm_compute_benchmark_examples += [ prog ] 289 else: 290 #-Wl,--allow-shlib-undefined: Ignore dependencies of dependencies 291 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']) 292 arm_compute_benchmark_examples += [ prog ] 293 294 arm_compute_benchmark_examples = install_bin(arm_compute_benchmark_examples) 295 Depends(arm_compute_benchmark_examples, arm_compute_test_framework) 296 Depends(arm_compute_benchmark_examples, arm_compute_lib) 297 Default(arm_compute_benchmark_examples) 298 Export('arm_compute_benchmark_examples') 299