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