1*c217d954SCole Faust# -*- coding: utf-8 -*- 2*c217d954SCole Faust 3*c217d954SCole Faust# Copyright (c) 2016-2023 Arm Limited. 4*c217d954SCole Faust# 5*c217d954SCole Faust# SPDX-License-Identifier: MIT 6*c217d954SCole Faust# 7*c217d954SCole Faust# Permission is hereby granted, free of charge, to any person obtaining a copy 8*c217d954SCole Faust# of this software and associated documentation files (the "Software"), to 9*c217d954SCole Faust# deal in the Software without restriction, including without limitation the 10*c217d954SCole Faust# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11*c217d954SCole Faust# sell copies of the Software, and to permit persons to whom the Software is 12*c217d954SCole Faust# furnished to do so, subject to the following conditions: 13*c217d954SCole Faust# 14*c217d954SCole Faust# The above copyright notice and this permission notice shall be included in all 15*c217d954SCole Faust# copies or substantial portions of the Software. 16*c217d954SCole Faust# 17*c217d954SCole Faust# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18*c217d954SCole Faust# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19*c217d954SCole Faust# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20*c217d954SCole Faust# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21*c217d954SCole Faust# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22*c217d954SCole Faust# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23*c217d954SCole Faust# SOFTWARE. 24*c217d954SCole Faust 25*c217d954SCole Faustimport SCons 26*c217d954SCole Faustimport json 27*c217d954SCole Faustimport os 28*c217d954SCole Faustfrom subprocess import check_output 29*c217d954SCole Faust 30*c217d954SCole Faustdef version_at_least(version, required): 31*c217d954SCole Faust 32*c217d954SCole Faust version_list = version.split('.') 33*c217d954SCole Faust required_list = required.split('.') 34*c217d954SCole Faust end = min(len(version_list), len(required_list)) 35*c217d954SCole Faust for i in range(0, end): 36*c217d954SCole Faust if int(version_list[i]) < int(required_list[i]): 37*c217d954SCole Faust return False 38*c217d954SCole Faust elif int(version_list[i]) > int(required_list[i]): 39*c217d954SCole Faust return True 40*c217d954SCole Faust 41*c217d954SCole Faust return True 42*c217d954SCole Faust 43*c217d954SCole Faustdef read_build_config_json(build_config): 44*c217d954SCole Faust build_config_contents = {} 45*c217d954SCole Faust custom_types = [] 46*c217d954SCole Faust custom_layouts = [] 47*c217d954SCole Faust if os.path.isfile(build_config): 48*c217d954SCole Faust with open(build_config) as f: 49*c217d954SCole Faust try: 50*c217d954SCole Faust build_config_contents = json.load(f) 51*c217d954SCole Faust except: 52*c217d954SCole Faust print("Warning: Build configuration file is of invalid JSON format!") 53*c217d954SCole Faust else: 54*c217d954SCole Faust try: 55*c217d954SCole Faust build_config_contents = json.loads(build_config) 56*c217d954SCole Faust except: 57*c217d954SCole Faust print("Warning: Build configuration string is of invalid JSON format!") 58*c217d954SCole Faust if build_config_contents: 59*c217d954SCole Faust custom_types = build_config_contents.get("data_types", []) 60*c217d954SCole Faust custom_layouts = build_config_contents.get("data_layouts", []) 61*c217d954SCole Faust return custom_types, custom_layouts 62*c217d954SCole Faust 63*c217d954SCole Faustdef update_data_type_layout_flags(env, data_types, data_layouts): 64*c217d954SCole Faust # Manage data-types 65*c217d954SCole Faust if any(i in data_types for i in ['all', 'fp16']): 66*c217d954SCole Faust env.Append(CXXFLAGS = ['-DENABLE_FP16_KERNELS']) 67*c217d954SCole Faust if any(i in data_types for i in ['all', 'fp32']): 68*c217d954SCole Faust env.Append(CXXFLAGS = ['-DENABLE_FP32_KERNELS']) 69*c217d954SCole Faust if any(i in data_types for i in ['all', 'qasymm8']): 70*c217d954SCole Faust env.Append(CXXFLAGS = ['-DENABLE_QASYMM8_KERNELS']) 71*c217d954SCole Faust if any(i in data_types for i in ['all', 'qasymm8_signed']): 72*c217d954SCole Faust env.Append(CXXFLAGS = ['-DENABLE_QASYMM8_SIGNED_KERNELS']) 73*c217d954SCole Faust if any(i in data_types for i in ['all', 'qsymm16']): 74*c217d954SCole Faust env.Append(CXXFLAGS = ['-DENABLE_QSYMM16_KERNELS']) 75*c217d954SCole Faust if any(i in data_types for i in ['all', 'integer']): 76*c217d954SCole Faust env.Append(CXXFLAGS = ['-DENABLE_INTEGER_KERNELS']) 77*c217d954SCole Faust 78*c217d954SCole Faust # Manage data-layouts 79*c217d954SCole Faust if any(i in data_layouts for i in ['all', 'nhwc']): 80*c217d954SCole Faust env.Append(CXXFLAGS = ['-DENABLE_NHWC_KERNELS']) 81*c217d954SCole Faust if any(i in data_layouts for i in ['all', 'nchw']): 82*c217d954SCole Faust env.Append(CXXFLAGS = ['-DENABLE_NCHW_KERNELS']) 83*c217d954SCole Faust 84*c217d954SCole Faust return env 85*c217d954SCole Faust 86*c217d954SCole Faust 87*c217d954SCole Faustvars = Variables("scons") 88*c217d954SCole Faustvars.AddVariables( 89*c217d954SCole Faust BoolVariable("debug", "Debug", False), 90*c217d954SCole Faust BoolVariable("asserts", "Enable asserts (this flag is forced to 1 for debug=1)", False), 91*c217d954SCole Faust BoolVariable("logging", "Enable Logging", False), 92*c217d954SCole Faust EnumVariable("arch", "Target Architecture. The x86_32 and x86_64 targets can only be used with neon=0 and opencl=1.", "armv7a", 93*c217d954SCole Faust allowed_values=("armv7a", "armv7a-hf", "arm64-v8a", "arm64-v8.2-a", "arm64-v8.2-a-sve", "arm64-v8.2-a-sve2", "x86_32", "x86_64", 94*c217d954SCole Faust "armv8a", "armv8.2-a", "armv8.2-a-sve", "armv8.6-a", "armv8.6-a-sve", "armv8.6-a-sve2", "armv8.6-a-sve2-sme2", "armv8r64", "x86")), 95*c217d954SCole Faust EnumVariable("estate", "Execution State", "auto", allowed_values=("auto", "32", "64")), 96*c217d954SCole Faust EnumVariable("os", "Target OS. With bare metal selected, only Arm® Neon™ (not OpenCL) can be used, static libraries get built and Neon™'s multi-threading support is disabled.", "linux", allowed_values=("linux", "android", "tizen", "macos", "bare_metal", "openbsd","windows")), 97*c217d954SCole Faust EnumVariable("build", "Either build directly on your device (native) or cross compile from your desktop machine (cross-compile). In both cases make sure the compiler is available in your path.", "cross_compile", allowed_values=("native", "cross_compile", "embed_only")), 98*c217d954SCole Faust BoolVariable("examples", "Build example programs", True), 99*c217d954SCole Faust BoolVariable("gemm_tuner", "Build gemm_tuner programs", True), 100*c217d954SCole Faust BoolVariable("Werror", "Enable/disable the -Werror compilation flag", True), 101*c217d954SCole Faust BoolVariable("multi_isa", "Build Multi ISA binary version of library. Note works only for armv8.2-a", False), 102*c217d954SCole Faust BoolVariable("standalone", "Builds the tests as standalone executables, links statically with libgcc, libstdc++ and libarm_compute", False), 103*c217d954SCole Faust BoolVariable("opencl", "Enable OpenCL support", True), 104*c217d954SCole Faust BoolVariable("neon", "Enable Arm® Neon™ support", False), 105*c217d954SCole Faust BoolVariable("embed_kernels", "Enable if you want the OpenCL kernels to be built in the library's binaries instead of being read from separate '.cl' / '.cs' files. If embed_kernels is set to 0 then the application can set the path to the folder containing the OpenCL kernel files by calling CLKernelLibrary::init(). By default the path is set to './cl_kernels'.", True), 106*c217d954SCole Faust BoolVariable("compress_kernels", "Compress embedded OpenCL kernels in library binary using zlib. Useful for reducing the binary size. embed_kernels should be enabled", False), 107*c217d954SCole Faust BoolVariable("set_soname", "If enabled the library will contain a SONAME and SHLIBVERSION and some symlinks will automatically be created between the objects. (requires SCons 2.4 or above)", False), 108*c217d954SCole Faust BoolVariable("openmp", "Enable OpenMP backend. Only works when building with g++ and not clang++", False), 109*c217d954SCole Faust BoolVariable("cppthreads", "Enable C++11 threads backend", True), 110*c217d954SCole Faust PathVariable("build_dir", "Specify sub-folder for the build", ".", PathVariable.PathAccept), 111*c217d954SCole Faust PathVariable("install_dir", "Specify sub-folder for the install", "", PathVariable.PathAccept), 112*c217d954SCole Faust BoolVariable("exceptions", "Enable/disable C++ exception support", True), 113*c217d954SCole Faust BoolVariable("high_priority", "Generate a library containing only the high priority operators", False), 114*c217d954SCole Faust PathVariable("linker_script", "Use an external linker script", "", PathVariable.PathAccept), 115*c217d954SCole Faust PathVariable("external_tests_dir", """Add examples, benchmarks and tests to the tests suite from an external path. In order to use this option, the external tests directory must have the following structure: 116*c217d954SCole Faust EXTERNAL_TESTS_DIR: 117*c217d954SCole Faust └── tests 118*c217d954SCole Faust ├── benchmark 119*c217d954SCole Faust │ ├── CL 120*c217d954SCole Faust │ ├── datasets 121*c217d954SCole Faust │ ├── fixtures 122*c217d954SCole Faust │ └── Neon 123*c217d954SCole Faust └── validation 124*c217d954SCole Faust ├── CL 125*c217d954SCole Faust ├── datasets 126*c217d954SCole Faust ├── fixtures 127*c217d954SCole Faust └── Neon\n""", "", PathVariable.PathAccept), 128*c217d954SCole Faust BoolVariable("experimental_dynamic_fusion", "Build the experimental dynamic fusion files", False), 129*c217d954SCole Faust BoolVariable("experimental_fixed_format_kernels", "Enable fixed format kernels for GEMM", False), 130*c217d954SCole Faust BoolVariable("mapfile", "Generate a map file", False), 131*c217d954SCole Faust ListVariable("custom_options", "Custom options that can be used to turn on/off features", "none", ["disable_mmla_fp"]), 132*c217d954SCole Faust ListVariable("data_type_support", "Enable a list of data types to support", "all", ["qasymm8", "qasymm8_signed", "qsymm16", "fp16", "fp32", "integer"]), 133*c217d954SCole Faust ListVariable("data_layout_support", "Enable a list of data layout to support", "all", ["nhwc", "nchw"]), 134*c217d954SCole Faust ("toolchain_prefix", "Override the toolchain prefix; used by all toolchain components: compilers, linker, assembler etc. If unspecified, use default(auto) prefixes; if passed an empty string '' prefixes would be disabled", "auto"), 135*c217d954SCole Faust ("compiler_prefix", "Override the compiler prefix; used by just compilers (CC,CXX); further overrides toolchain_prefix for compilers; this is for when the compiler prefixes are different from that of the linkers, archivers etc. If unspecified, this is the same as toolchain_prefix; if passed an empty string '' prefixes would be disabled", "auto"), 136*c217d954SCole Faust ("extra_cxx_flags", "Extra CXX flags to be appended to the build command", ""), 137*c217d954SCole Faust ("extra_link_flags", "Extra LD flags to be appended to the build command", ""), 138*c217d954SCole Faust ("compiler_cache", "Command to prefix to the C and C++ compiler (e.g ccache)", ""), 139*c217d954SCole Faust ("specs_file", "Specs file to use (e.g. rdimon.specs)", ""), 140*c217d954SCole Faust ("build_config", "Operator/Data-type/Data-layout configuration to use for tailored ComputeLibrary builds. Can be a JSON file or a JSON formatted string", "") 141*c217d954SCole Faust) 142*c217d954SCole Faust 143*c217d954SCole Faust 144*c217d954SCole Faustenv = Environment(variables=vars, ENV = os.environ) 145*c217d954SCole Faust 146*c217d954SCole Faust 147*c217d954SCole Faustbuild_path = env['build_dir'] 148*c217d954SCole Faust# If build_dir is a relative path then add a #build/ prefix: 149*c217d954SCole Faustif not env['build_dir'].startswith('/'): 150*c217d954SCole Faust SConsignFile('build/%s/.scons' % build_path) 151*c217d954SCole Faust build_path = "#build/%s" % build_path 152*c217d954SCole Faustelse: 153*c217d954SCole Faust SConsignFile('%s/.scons' % build_path) 154*c217d954SCole Faust 155*c217d954SCole Faustinstall_path = env['install_dir'] 156*c217d954SCole Faust#If the install_dir is a relative path then assume it's from inside build_dir 157*c217d954SCole Faustif not env['install_dir'].startswith('/') and install_path != "": 158*c217d954SCole Faust install_path = "%s/%s" % (build_path, install_path) 159*c217d954SCole Faust 160*c217d954SCole Faustenv.Append(LIBPATH = [build_path]) 161*c217d954SCole FaustExport('env') 162*c217d954SCole FaustExport('vars') 163*c217d954SCole Faust 164*c217d954SCole Faustdef install_lib( lib ): 165*c217d954SCole Faust # If there is no install folder, then there is nothing to do: 166*c217d954SCole Faust if install_path == "": 167*c217d954SCole Faust return lib 168*c217d954SCole Faust return env.Install( "%s/lib/" % install_path, lib) 169*c217d954SCole Faustdef install_bin( bin ): 170*c217d954SCole Faust # If there is no install folder, then there is nothing to do: 171*c217d954SCole Faust if install_path == "": 172*c217d954SCole Faust return bin 173*c217d954SCole Faust return env.Install( "%s/bin/" % install_path, bin) 174*c217d954SCole Faustdef install_include( inc ): 175*c217d954SCole Faust if install_path == "": 176*c217d954SCole Faust return inc 177*c217d954SCole Faust return env.Install( "%s/include/" % install_path, inc) 178*c217d954SCole Faust 179*c217d954SCole FaustExport('install_lib') 180*c217d954SCole FaustExport('install_bin') 181*c217d954SCole Faust 182*c217d954SCole FaustHelp(vars.GenerateHelpText(env)) 183*c217d954SCole Faust 184*c217d954SCole Faustif 'armv7a' in env['arch'] and env['os'] == 'android': 185*c217d954SCole Faust print("WARNING: armv7a on Android is no longer maintained") 186*c217d954SCole Faust 187*c217d954SCole Faustif env['linker_script'] and env['os'] != 'bare_metal': 188*c217d954SCole Faust print("Linker script is only supported for bare_metal builds") 189*c217d954SCole Faust Exit(1) 190*c217d954SCole Faust 191*c217d954SCole Faustif env['build'] == "embed_only": 192*c217d954SCole Faust SConscript('./SConscript', variant_dir=build_path, duplicate=0) 193*c217d954SCole Faust Return() 194*c217d954SCole Faust 195*c217d954SCole Faustif env['neon'] and 'x86' in env['arch']: 196*c217d954SCole Faust print("Cannot compile Arm® Neon™ for x86") 197*c217d954SCole Faust Exit(1) 198*c217d954SCole Faust 199*c217d954SCole Faustif env['set_soname'] and not version_at_least(SCons.__version__, "2.4"): 200*c217d954SCole Faust print("Setting the library's SONAME / SHLIBVERSION requires SCons 2.4 or above") 201*c217d954SCole Faust print("Update your version of SCons or use set_soname=0") 202*c217d954SCole Faust Exit(1) 203*c217d954SCole Faust 204*c217d954SCole Faustif env['os'] == 'bare_metal': 205*c217d954SCole Faust if env['cppthreads'] or env['openmp']: 206*c217d954SCole Faust print("ERROR: OpenMP and C++11 threads not supported in bare_metal. Use cppthreads=0 openmp=0") 207*c217d954SCole Faust Exit(1) 208*c217d954SCole Faust 209*c217d954SCole Faustif env['opencl'] and env['embed_kernels'] and env['compress_kernels'] and env['os'] not in ['android']: 210*c217d954SCole Faust print("Compressed kernels are supported only for android builds") 211*c217d954SCole Faust Exit(1) 212*c217d954SCole Faust 213*c217d954SCole Faustif not env['exceptions']: 214*c217d954SCole Faust if env['opencl']: 215*c217d954SCole Faust print("ERROR: OpenCL is not supported when building without exceptions. Use opencl=0") 216*c217d954SCole Faust Exit(1) 217*c217d954SCole Faust 218*c217d954SCole Faust env.Append(CPPDEFINES = ['ARM_COMPUTE_EXCEPTIONS_DISABLED']) 219*c217d954SCole Faust env.Append(CXXFLAGS = ['-fno-exceptions']) 220*c217d954SCole Faust 221*c217d954SCole Faustenv.Append(CXXFLAGS = ['-DARCH_ARM', 222*c217d954SCole Faust '-Wextra','-Wdisabled-optimization','-Wformat=2', 223*c217d954SCole Faust '-Winit-self','-Wstrict-overflow=2','-Wswitch-default', 224*c217d954SCole Faust '-Woverloaded-virtual', '-Wformat-security', 225*c217d954SCole Faust '-Wctor-dtor-privacy','-Wsign-promo','-Weffc++','-Wno-overlength-strings']) 226*c217d954SCole Faust 227*c217d954SCole Faustif not 'windows' in env['os']: 228*c217d954SCole Faust env.Append(CXXFLAGS = ['-Wall','-std=c++14', '-pedantic' ]) 229*c217d954SCole Faust 230*c217d954SCole Faustenv.Append(CPPDEFINES = ['_GLIBCXX_USE_NANOSLEEP']) 231*c217d954SCole Faust 232*c217d954SCole Faustcpp_tool = {'linux': 'g++', 'android' : 'clang++', 233*c217d954SCole Faust 'tizen': 'g++', 'macos':'clang++', 234*c217d954SCole Faust 'bare_metal':'g++', 'openbsd':'g++','windows':'clang-cl'} 235*c217d954SCole Faust 236*c217d954SCole Faustc_tool = {'linux':'gcc', 'android': 'clang', 'tizen':'gcc', 237*c217d954SCole Faust 'macos':'clang','bare_metal':'gcc', 238*c217d954SCole Faust 'openbsd':'gcc','windows':'clang-cl'} 239*c217d954SCole Faust 240*c217d954SCole Faustdefault_cpp_compiler = cpp_tool[env['os']] 241*c217d954SCole Faustdefault_c_compiler = c_tool[env['os']] 242*c217d954SCole Faustcpp_compiler = os.environ.get('CXX', default_cpp_compiler) 243*c217d954SCole Faustc_compiler = os.environ.get('CC', default_c_compiler) 244*c217d954SCole Faust 245*c217d954SCole Faustif env['os'] == 'android' and ( 'clang++' not in cpp_compiler or 'clang' not in c_compiler ): 246*c217d954SCole Faust print( "WARNING: Only clang is officially supported to build the Compute Library for Android") 247*c217d954SCole Faust 248*c217d954SCole Faustif 'clang++' in cpp_compiler: 249*c217d954SCole Faust env.Append(CXXFLAGS = ['-Wno-vla-extension']) 250*c217d954SCole Faustelif 'armclang' in cpp_compiler: 251*c217d954SCole Faust pass 252*c217d954SCole Faustelif not 'windows' in env['os']: 253*c217d954SCole Faust env.Append(CXXFLAGS = ['-Wlogical-op','-Wnoexcept','-Wstrict-null-sentinel','-Wno-misleading-indentation']) 254*c217d954SCole Faust 255*c217d954SCole Faustif cpp_compiler == 'g++': 256*c217d954SCole Faust # Don't strip comments that could include markers 257*c217d954SCole Faust env.Append(CXXFLAGS = ['-C']) 258*c217d954SCole Faust 259*c217d954SCole Faustif env['cppthreads']: 260*c217d954SCole Faust env.Append(CPPDEFINES = [('ARM_COMPUTE_CPP_SCHEDULER', 1)]) 261*c217d954SCole Faust 262*c217d954SCole Faustif env['openmp']: 263*c217d954SCole Faust env.Append(CPPDEFINES = [('ARM_COMPUTE_OPENMP_SCHEDULER', 1)]) 264*c217d954SCole Faust env.Append(CXXFLAGS = ['-fopenmp']) 265*c217d954SCole Faust env.Append(LINKFLAGS = ['-fopenmp']) 266*c217d954SCole Faust 267*c217d954SCole Faust# Validate and define state 268*c217d954SCole Faustif env['estate'] == 'auto': 269*c217d954SCole Faust if 'v7a' in env['arch']: 270*c217d954SCole Faust env['estate'] = '32' 271*c217d954SCole Faust else: 272*c217d954SCole Faust env['estate'] = '64' 273*c217d954SCole Faust 274*c217d954SCole Faust# Map legacy arch 275*c217d954SCole Faustif 'arm64' in env['arch']: 276*c217d954SCole Faust env['estate'] = '64' 277*c217d954SCole Faust 278*c217d954SCole Faustif 'v7a' in env['estate'] and env['estate'] == '64': 279*c217d954SCole Faust print("ERROR: armv7a architecture has only 32-bit execution state") 280*c217d954SCole Faust Exit(1) 281*c217d954SCole Faust 282*c217d954SCole Faustenv.Append(CPPDEFINES = ['ENABLE_NEON', 'ARM_COMPUTE_ENABLE_NEON']) 283*c217d954SCole Faust 284*c217d954SCole Faustif 'sve' in env['arch']: 285*c217d954SCole Faust env.Append(CPPDEFINES = ['ENABLE_SVE', 'ARM_COMPUTE_ENABLE_SVE']) 286*c217d954SCole Faust if 'sve2' in env['arch']: 287*c217d954SCole Faust env.Append(CPPDEFINES = ['ARM_COMPUTE_ENABLE_SVE2']) 288*c217d954SCole Faust 289*c217d954SCole Faustif 'sme' in env['arch']: 290*c217d954SCole Faust env.Append(CPPDEFINES = ['ENABLE_SME', 'ARM_COMPUTE_ENABLE_SME']) 291*c217d954SCole Faust if 'sme2' in env['arch']: 292*c217d954SCole Faust env.Append(CPPDEFINES = ['ARM_COMPUTE_ENABLE_SME2']) 293*c217d954SCole Faust 294*c217d954SCole Faust# Add architecture specific flags 295*c217d954SCole Faustif env['multi_isa']: 296*c217d954SCole Faust # assert arch version is v8 297*c217d954SCole Faust if 'v8' not in env['arch']: 298*c217d954SCole Faust print("Currently Multi ISA binary is only supported for arm v8 family") 299*c217d954SCole Faust Exit(1) 300*c217d954SCole Faust 301*c217d954SCole Faust if 'v8.6-a' in env['arch']: 302*c217d954SCole Faust if "disable_mmla_fp" not in env['custom_options']: 303*c217d954SCole Faust env.Append(CPPDEFINES = ['ARM_COMPUTE_ENABLE_SVEF32MM']) 304*c217d954SCole Faust 305*c217d954SCole Faust env.Append(CXXFLAGS = ['-march=armv8.2-a+fp16']) # explicitly enable fp16 extension otherwise __ARM_FEATURE_FP16_VECTOR_ARITHMETIC is undefined 306*c217d954SCole Faust 307*c217d954SCole Faustelse: # NONE "multi_isa" builds 308*c217d954SCole Faust 309*c217d954SCole Faust if 'v7a' in env['arch']: 310*c217d954SCole Faust env.Append(CXXFLAGS = ['-march=armv7-a', '-mthumb', '-mfpu=neon']) 311*c217d954SCole Faust if (env['os'] == 'android' or env['os'] == 'tizen') and not 'hf' in env['arch']: 312*c217d954SCole Faust env.Append(CXXFLAGS = ['-mfloat-abi=softfp']) 313*c217d954SCole Faust else: 314*c217d954SCole Faust env.Append(CXXFLAGS = ['-mfloat-abi=hard']) 315*c217d954SCole Faust elif 'v8.6-a' in env['arch']: 316*c217d954SCole Faust if 'armv8.6-a-sve2' in env['arch']: 317*c217d954SCole Faust env.Append(CXXFLAGS = ['-march=armv8.6-a+sve2']) 318*c217d954SCole Faust elif 'armv8.6-a-sve' == env['arch']: 319*c217d954SCole Faust env.Append(CXXFLAGS = ['-march=armv8.6-a+sve']) 320*c217d954SCole Faust elif 'armv8.6-a' == env['arch']: 321*c217d954SCole Faust env.Append(CXXFLAGS = ['-march=armv8.6-a+fp16']) 322*c217d954SCole Faust 323*c217d954SCole Faust env.Append(CPPDEFINES = ['ARM_COMPUTE_ENABLE_I8MM', 'ARM_COMPUTE_ENABLE_BF16','ARM_COMPUTE_ENABLE_FP16']) 324*c217d954SCole Faust if "disable_mmla_fp" not in env['custom_options']: 325*c217d954SCole Faust env.Append(CPPDEFINES = ['ARM_COMPUTE_ENABLE_SVEF32MM']) 326*c217d954SCole Faust elif 'v8' in env['arch']: 327*c217d954SCole Faust # Preserve the V8 archs for non-multi-ISA variants 328*c217d954SCole Faust if 'sve2' in env['arch']: 329*c217d954SCole Faust env.Append(CXXFLAGS = ['-march=armv8.2-a+sve2+fp16+dotprod']) 330*c217d954SCole Faust elif 'sve' in env['arch']: 331*c217d954SCole Faust env.Append(CXXFLAGS = ['-march=armv8.2-a+sve+fp16+dotprod']) 332*c217d954SCole Faust elif 'armv8r64' in env['arch']: 333*c217d954SCole Faust env.Append(CXXFLAGS = ['-march=armv8.4-a']) 334*c217d954SCole Faust elif 'v8.' in env['arch']: 335*c217d954SCole Faust env.Append(CXXFLAGS = ['-march=armv8.2-a+fp16']) # explicitly enable fp16 extension otherwise __ARM_FEATURE_FP16_VECTOR_ARITHMETIC is undefined 336*c217d954SCole Faust else: 337*c217d954SCole Faust env.Append(CXXFLAGS = ['-march=armv8-a']) 338*c217d954SCole Faust 339*c217d954SCole Faust if 'v8.' in env['arch']: 340*c217d954SCole Faust env.Append(CPPDEFINES = ['ARM_COMPUTE_ENABLE_FP16']) 341*c217d954SCole Faust 342*c217d954SCole Faust elif 'x86' in env['arch']: 343*c217d954SCole Faust if env['estate'] == '32': 344*c217d954SCole Faust env.Append(CCFLAGS = ['-m32']) 345*c217d954SCole Faust env.Append(LINKFLAGS = ['-m32']) 346*c217d954SCole Faust else: 347*c217d954SCole Faust env.Append(CXXFLAGS = ['-fPIC']) 348*c217d954SCole Faust env.Append(CCFLAGS = ['-m64']) 349*c217d954SCole Faust env.Append(LINKFLAGS = ['-m64']) 350*c217d954SCole Faust 351*c217d954SCole Faust# Define toolchain 352*c217d954SCole Faust# The reason why we distinguish toolchain_prefix from compiler_prefix is for cases where the linkers/archivers use a 353*c217d954SCole Faust# different prefix than the compilers. An example is the NDK r20 toolchain 354*c217d954SCole Faustauto_toolchain_prefix = "" 355*c217d954SCole Faustif 'x86' not in env['arch']: 356*c217d954SCole Faust if env['estate'] == '32': 357*c217d954SCole Faust if env['os'] == 'linux': 358*c217d954SCole Faust auto_toolchain_prefix = "arm-linux-gnueabihf-" if 'v7' in env['arch'] else "armv8l-linux-gnueabihf-" 359*c217d954SCole Faust elif env['os'] == 'bare_metal': 360*c217d954SCole Faust auto_toolchain_prefix = "arm-eabi-" 361*c217d954SCole Faust elif env['os'] == 'android': 362*c217d954SCole Faust auto_toolchain_prefix = "arm-linux-androideabi-" 363*c217d954SCole Faust elif env['os'] == 'tizen': 364*c217d954SCole Faust auto_toolchain_prefix = "armv7l-tizen-linux-gnueabi-" 365*c217d954SCole Faust elif env['estate'] == '64' and 'v8' in env['arch']: 366*c217d954SCole Faust if env['os'] == 'linux': 367*c217d954SCole Faust auto_toolchain_prefix = "aarch64-linux-gnu-" 368*c217d954SCole Faust elif env['os'] == 'bare_metal': 369*c217d954SCole Faust auto_toolchain_prefix = "aarch64-elf-" 370*c217d954SCole Faust elif env['os'] == 'android': 371*c217d954SCole Faust auto_toolchain_prefix = "aarch64-linux-android-" 372*c217d954SCole Faust elif env['os'] == 'tizen': 373*c217d954SCole Faust auto_toolchain_prefix = "aarch64-tizen-linux-gnu-" 374*c217d954SCole Faust 375*c217d954SCole Faustif env['build'] == 'native' or env["toolchain_prefix"] == "": 376*c217d954SCole Faust toolchain_prefix = "" 377*c217d954SCole Faustelif env["toolchain_prefix"] == "auto": 378*c217d954SCole Faust toolchain_prefix = auto_toolchain_prefix 379*c217d954SCole Faustelse: 380*c217d954SCole Faust toolchain_prefix = env["toolchain_prefix"] 381*c217d954SCole Faust 382*c217d954SCole Faustif env['build'] == 'native' or env["compiler_prefix"] == "": 383*c217d954SCole Faust compiler_prefix = "" 384*c217d954SCole Faustelif env["compiler_prefix"] == "auto": 385*c217d954SCole Faust compiler_prefix = toolchain_prefix 386*c217d954SCole Faustelse: 387*c217d954SCole Faust compiler_prefix = env["compiler_prefix"] 388*c217d954SCole Faust 389*c217d954SCole Faustenv['CC'] = env['compiler_cache']+ " " + compiler_prefix + c_compiler 390*c217d954SCole Faustenv['CXX'] = env['compiler_cache']+ " " + compiler_prefix + cpp_compiler 391*c217d954SCole Faustenv['LD'] = toolchain_prefix + "ld" 392*c217d954SCole Faustenv['AS'] = toolchain_prefix + "as" 393*c217d954SCole Faust 394*c217d954SCole Faustif env['os'] == 'windows': 395*c217d954SCole Faust env['AR'] = "llvm-lib" 396*c217d954SCole Faust env['RANLIB'] = "llvm-ranlib" 397*c217d954SCole Faustelse: 398*c217d954SCole Faust env['AR'] = toolchain_prefix + "ar" 399*c217d954SCole Faust 400*c217d954SCole Faustenv['RANLIB'] = toolchain_prefix + "ranlib" 401*c217d954SCole Faust 402*c217d954SCole Faustprint("Using compilers:") 403*c217d954SCole Faustprint("CC", env['CC']) 404*c217d954SCole Faustprint("CXX", env['CXX']) 405*c217d954SCole Faust 406*c217d954SCole Faustif not GetOption("help"): 407*c217d954SCole Faust try: 408*c217d954SCole Faust if env['os'] == 'windows': 409*c217d954SCole Faust compiler_ver = check_output("clang++ -dumpversion").decode().strip() 410*c217d954SCole Faust else: 411*c217d954SCole Faust compiler_ver = check_output(env['CXX'].split() + ["-dumpversion"]).decode().strip() 412*c217d954SCole Faust except OSError: 413*c217d954SCole Faust print("ERROR: Compiler '%s' not found" % env['CXX']) 414*c217d954SCole Faust Exit(1) 415*c217d954SCole Faust 416*c217d954SCole Faust if 'armclang' in cpp_compiler: 417*c217d954SCole Faust pass 418*c217d954SCole Faust elif 'clang++' not in cpp_compiler: 419*c217d954SCole Faust if env['arch'] == 'arm64-v8.2-a' and not version_at_least(compiler_ver, '6.2.1'): 420*c217d954SCole Faust print("GCC 6.2.1 or newer is required to compile armv8.2-a code") 421*c217d954SCole Faust Exit(1) 422*c217d954SCole Faust elif env['arch'] == 'arm64-v8a' and not version_at_least(compiler_ver, '4.9'): 423*c217d954SCole Faust print("GCC 4.9 or newer is required to compile Arm® Neon™ code for AArch64") 424*c217d954SCole Faust Exit(1) 425*c217d954SCole Faust 426*c217d954SCole Faust if version_at_least(compiler_ver, '6.1'): 427*c217d954SCole Faust env.Append(CXXFLAGS = ['-Wno-ignored-attributes']) 428*c217d954SCole Faust 429*c217d954SCole Faust if compiler_ver == '4.8.3': 430*c217d954SCole Faust env.Append(CXXFLAGS = ['-Wno-array-bounds']) 431*c217d954SCole Faust 432*c217d954SCole Faust if not version_at_least(compiler_ver, '7.0.0') and env['os'] == 'bare_metal': 433*c217d954SCole Faust env.Append(LINKFLAGS = ['-fstack-protector-strong']) 434*c217d954SCole Faust 435*c217d954SCole Faust # Add Android NDK toolchain specific flags 436*c217d954SCole Faust if 'clang++' in cpp_compiler and env['os'] == 'android': 437*c217d954SCole Faust # For NDK >= r21, clang 9 or above is used 438*c217d954SCole Faust if version_at_least(compiler_ver, '9.0.0'): 439*c217d954SCole Faust env['ndk_above_r21'] = True 440*c217d954SCole Faust 441*c217d954SCole Faust if env['openmp']: 442*c217d954SCole Faust env.Append(LINKFLAGS = ['-static-openmp']) 443*c217d954SCole Faust 444*c217d954SCole Faust # For NDK >= r23, clang 12 or above is used. This condition detects NDK < r23 445*c217d954SCole Faust if not version_at_least(compiler_ver, '12.0.0'): 446*c217d954SCole Faust # System assembler is deprecated and integrated assembler is preferred since r23. 447*c217d954SCole Faust # However integrated assembler has always been suppressed for NDK < r23. 448*c217d954SCole Faust # Thus for backward compatibility, we include this flag only for NDK < r23 449*c217d954SCole Faust env.Append(CXXFLAGS = ['-no-integrated-as']) 450*c217d954SCole Faust 451*c217d954SCole Faustif env['high_priority'] and env['build_config']: 452*c217d954SCole Faust print("The high priority library cannot be built in conjunction with a user-specified build configuration") 453*c217d954SCole Faust Exit(1) 454*c217d954SCole Faust 455*c217d954SCole Faustif not env['high_priority'] and not env['build_config']: 456*c217d954SCole Faust env.Append(CPPDEFINES = ['ARM_COMPUTE_GRAPH_ENABLED']) 457*c217d954SCole Faust 458*c217d954SCole Faustdata_types = [] 459*c217d954SCole Faustdata_layouts = [] 460*c217d954SCole Faust 461*c217d954SCole Faust# Set correct data types / layouts to build 462*c217d954SCole Faustif env['high_priority']: 463*c217d954SCole Faust data_types = ['all'] 464*c217d954SCole Faust data_layouts = ['all'] 465*c217d954SCole Faustelif env['build_config']: 466*c217d954SCole Faust data_types, data_layouts = read_build_config_json(env['build_config']) 467*c217d954SCole Faustelse: 468*c217d954SCole Faust data_types = env['data_type_support'] 469*c217d954SCole Faust data_layouts = env['data_layout_support'] 470*c217d954SCole Faust 471*c217d954SCole Faustenv = update_data_type_layout_flags(env, data_types, data_layouts) 472*c217d954SCole Faust 473*c217d954SCole Faustif env['standalone']: 474*c217d954SCole Faust if not 'windows' in env['os']: 475*c217d954SCole Faust env.Append(CXXFLAGS = ['-fPIC']) 476*c217d954SCole Faust env.Append(LINKFLAGS = ['-static-libgcc','-static-libstdc++']) 477*c217d954SCole Faust 478*c217d954SCole Faustif env['Werror']: 479*c217d954SCole Faust env.Append(CXXFLAGS = ['-Werror']) 480*c217d954SCole Faust 481*c217d954SCole Faustif env['os'] == 'android': 482*c217d954SCole Faust env.Append(CPPDEFINES = ['ANDROID']) 483*c217d954SCole Faust env.Append(LINKFLAGS = ['-pie', '-static-libstdc++', '-ldl']) 484*c217d954SCole Faustelif env['os'] == 'bare_metal': 485*c217d954SCole Faust env.Append(LINKFLAGS = ['-static']) 486*c217d954SCole Faust env.Append(CXXFLAGS = ['-fPIC']) 487*c217d954SCole Faust if env['specs_file'] == "": 488*c217d954SCole Faust env.Append(LINKFLAGS = ['-specs=rdimon.specs']) 489*c217d954SCole Faust env.Append(CPPDEFINES = ['NO_MULTI_THREADING']) 490*c217d954SCole Faust env.Append(CPPDEFINES = ['BARE_METAL']) 491*c217d954SCole Faustif env['os'] == 'linux' and env['arch'] == 'armv7a': 492*c217d954SCole Faust env.Append(CXXFLAGS = [ '-Wno-psabi' ]) 493*c217d954SCole Faustif env['os'] == 'windows': 494*c217d954SCole Faust env.Append(CXXFLAGS = [ '/std:c++14','/EHa']) 495*c217d954SCole Faust env.Append(CXXFLAGS = [ '-Wno-c++98-compat', '-Wno-covered-switch-default','-Wno-c++98-compat-pedantic']) 496*c217d954SCole Faust env.Append(CXXFLAGS = [ '-Wno-shorten-64-to-32', '-Wno-sign-conversion','-Wno-documentation']) 497*c217d954SCole Faust env.Append(CXXFLAGS = [ '-Wno-extra-semi-stmt', '-Wno-float-equal','-Wno-implicit-int-conversion']) 498*c217d954SCole Faust env.Append(CXXFLAGS = [ '-Wno-documentation-pedantic', '-Wno-extra-semi','-Wno-shadow-field-in-constructor']) 499*c217d954SCole Faust env.Append(CXXFLAGS = [ '-Wno-float-conversion', '-Wno-switch-enum','-Wno-comma']) 500*c217d954SCole Faust env.Append(CXXFLAGS = [ '-Wno-implicit-float-conversion', '-Wno-deprecated-declarations','-Wno-old-style-cast']) 501*c217d954SCole Faust env.Append(CXXFLAGS = [ '-Wno-zero-as-null-pointer-constant', '-Wno-inconsistent-missing-destructor-override']) 502*c217d954SCole Faust env.Append(CXXFLAGS = [ '-Wno-asm-operand-widths']) 503*c217d954SCole Faust 504*c217d954SCole Faust 505*c217d954SCole Faustif env['specs_file'] != "": 506*c217d954SCole Faust env.Append(LINKFLAGS = ['-specs='+env['specs_file']]) 507*c217d954SCole Faust 508*c217d954SCole Faustif env['neon']: 509*c217d954SCole Faust env.Append(CPPDEFINES = ['ARM_COMPUTE_CPU_ENABLED']) 510*c217d954SCole Faust 511*c217d954SCole Faustif env['opencl']: 512*c217d954SCole Faust env.Append(CPPDEFINES = ['ARM_COMPUTE_OPENCL_ENABLED']) 513*c217d954SCole Faust if env['os'] in ['bare_metal'] or env['standalone']: 514*c217d954SCole Faust print("Cannot link OpenCL statically, which is required for bare metal / standalone builds") 515*c217d954SCole Faust Exit(1) 516*c217d954SCole Faust 517*c217d954SCole Faustif env["os"] not in ["windows","android", "bare_metal"] and (env['opencl'] or env['cppthreads']): 518*c217d954SCole Faust env.Append(LIBS = ['pthread']) 519*c217d954SCole Faust 520*c217d954SCole Faustif env['os'] == 'openbsd': 521*c217d954SCole Faust env.Append(LIBS = ['c']) 522*c217d954SCole Faust env.Append(CXXFLAGS = ['-fPIC']) 523*c217d954SCole Faust 524*c217d954SCole Faustif env['opencl']: 525*c217d954SCole Faust if env['embed_kernels']: 526*c217d954SCole Faust env.Append(CPPDEFINES = ['EMBEDDED_KERNELS']) 527*c217d954SCole Faust if env['compress_kernels']: 528*c217d954SCole Faust env.Append(CPPDEFINES = ['ARM_COMPUTE_COMPRESSED_KERNELS']) 529*c217d954SCole Faust env.Append(LIBS = ['z']) 530*c217d954SCole Faust 531*c217d954SCole Faustif env['debug']: 532*c217d954SCole Faust env['asserts'] = True 533*c217d954SCole Faust if not 'windows' in env['os']: 534*c217d954SCole Faust env.Append(CXXFLAGS = ['-O0','-g','-gdwarf-2']) 535*c217d954SCole Faust else: 536*c217d954SCole Faust env.Append(CXXFLAGS = ['-Z7','-MTd','-fms-compatibility','-fdelayed-template-parsing']) 537*c217d954SCole Faust env.Append(LINKFLAGS = ['-DEBUG']) 538*c217d954SCole Faust 539*c217d954SCole Faust env.Append(CPPDEFINES = ['ARM_COMPUTE_DEBUG_ENABLED']) 540*c217d954SCole Faustelse: 541*c217d954SCole Faust if not 'windows' in env['os']: 542*c217d954SCole Faust env.Append(CXXFLAGS = ['-O3']) 543*c217d954SCole Faust else: 544*c217d954SCole Faust # on windows we use clang-cl which does not support the option -O3 545*c217d954SCole Faust env.Append(CXXFLAGS = ['-O2']) 546*c217d954SCole Faust 547*c217d954SCole Faustif env['asserts']: 548*c217d954SCole Faust env.Append(CPPDEFINES = ['ARM_COMPUTE_ASSERTS_ENABLED']) 549*c217d954SCole Faust if not 'windows' in env['os']: 550*c217d954SCole Faust env.Append(CXXFLAGS = ['-fstack-protector-strong']) 551*c217d954SCole Faust 552*c217d954SCole Faustif env['logging']: 553*c217d954SCole Faust env.Append(CPPDEFINES = ['ARM_COMPUTE_LOGGING_ENABLED']) 554*c217d954SCole Faust 555*c217d954SCole Faustenv.Append(CPPPATH = ['#/include', "#"]) 556*c217d954SCole Faustenv.Append(CXXFLAGS = env['extra_cxx_flags']) 557*c217d954SCole Faustenv.Append(LINKFLAGS = env['extra_link_flags']) 558*c217d954SCole Faust 559*c217d954SCole FaustDefault( install_include("arm_compute")) 560*c217d954SCole FaustDefault( install_include("support")) 561*c217d954SCole FaustDefault( install_include("utils")) 562*c217d954SCole Faustfor dirname in os.listdir("./include"): 563*c217d954SCole Faust Default( install_include("include/%s" % dirname)) 564*c217d954SCole Faust 565*c217d954SCole FaustExport('version_at_least') 566*c217d954SCole Faust 567*c217d954SCole FaustSConscript('./SConscript', variant_dir=build_path, duplicate=0) 568*c217d954SCole Faust 569*c217d954SCole Faustif env['examples'] and (env['build_config'] or env['high_priority']): 570*c217d954SCole Faust print("WARNING: Building examples for selected operators not supported. Use examples=0") 571*c217d954SCole Faust Return() 572*c217d954SCole Faust 573*c217d954SCole Faustif env['examples'] and env['exceptions']: 574*c217d954SCole Faust if env['os'] == 'bare_metal' and env['arch'] == 'armv7a': 575*c217d954SCole Faust print("WARNING: Building examples for bare metal and armv7a is not supported. Use examples=0") 576*c217d954SCole Faust Return() 577*c217d954SCole Faust SConscript('./examples/SConscript', variant_dir='%s/examples' % build_path, duplicate=0) 578*c217d954SCole Faust 579*c217d954SCole Faustif env['exceptions']: 580*c217d954SCole Faust if env['build_config'] or env['high_priority']: 581*c217d954SCole Faust print("WARNING: Building tests for selected operators not supported") 582*c217d954SCole Faust Return() 583*c217d954SCole Faust if env['os'] == 'bare_metal' and env['arch'] == 'armv7a': 584*c217d954SCole Faust print("WARNING: Building tests for bare metal and armv7a is not supported") 585*c217d954SCole Faust Return() 586*c217d954SCole Faust SConscript('./tests/SConscript', variant_dir='%s/tests' % build_path, duplicate=0) 587*c217d954SCole Faust 588*c217d954SCole Faust# Unknown variables are not allowed 589*c217d954SCole Faust# Note: we must delay the call of UnknownVariables until after 590*c217d954SCole Faust# we have applied the Variables object to the construction environment 591*c217d954SCole Faustunknown = vars.UnknownVariables() 592*c217d954SCole Faustif unknown: 593*c217d954SCole Faust print("Unknown variables: %s" % " ".join(unknown.keys())) 594*c217d954SCole Faust Exit(1) 595