• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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