1b8021494Sopenharmony_ci# Copyright 2015, VIXL authors 2b8021494Sopenharmony_ci# All rights reserved. 3b8021494Sopenharmony_ci# 4b8021494Sopenharmony_ci# Redistribution and use in source and binary forms, with or without 5b8021494Sopenharmony_ci# modification, are permitted provided that the following conditions are met: 6b8021494Sopenharmony_ci# 7b8021494Sopenharmony_ci# * Redistributions of source code must retain the above copyright notice, 8b8021494Sopenharmony_ci# this list of conditions and the following disclaimer. 9b8021494Sopenharmony_ci# * Redistributions in binary form must reproduce the above copyright notice, 10b8021494Sopenharmony_ci# this list of conditions and the following disclaimer in the documentation 11b8021494Sopenharmony_ci# and/or other materials provided with the distribution. 12b8021494Sopenharmony_ci# * Neither the name of ARM Limited nor the names of its contributors may be 13b8021494Sopenharmony_ci# used to endorse or promote products derived from this software without 14b8021494Sopenharmony_ci# specific prior written permission. 15b8021494Sopenharmony_ci# 16b8021494Sopenharmony_ci# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17b8021494Sopenharmony_ci# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18b8021494Sopenharmony_ci# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19b8021494Sopenharmony_ci# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20b8021494Sopenharmony_ci# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21b8021494Sopenharmony_ci# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22b8021494Sopenharmony_ci# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23b8021494Sopenharmony_ci# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24b8021494Sopenharmony_ci# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25b8021494Sopenharmony_ci# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26b8021494Sopenharmony_ci 27b8021494Sopenharmony_ciimport glob 28b8021494Sopenharmony_ciimport itertools 29b8021494Sopenharmony_ciimport os 30b8021494Sopenharmony_cifrom os.path import join 31b8021494Sopenharmony_ciimport platform 32b8021494Sopenharmony_ciimport subprocess 33b8021494Sopenharmony_ciimport sys 34b8021494Sopenharmony_cifrom collections import OrderedDict 35b8021494Sopenharmony_ci 36b8021494Sopenharmony_ciroot_dir = os.path.dirname(File('SConstruct').rfile().abspath) 37b8021494Sopenharmony_cisys.path.insert(0, join(root_dir, 'tools')) 38b8021494Sopenharmony_ciimport config 39b8021494Sopenharmony_ciimport util 40b8021494Sopenharmony_ci 41b8021494Sopenharmony_cifrom SCons.Errors import UserError 42b8021494Sopenharmony_ci 43b8021494Sopenharmony_ci 44b8021494Sopenharmony_ciHelp(''' 45b8021494Sopenharmony_ciBuild system for the VIXL project. 46b8021494Sopenharmony_ciSee README.md for documentation and details about the build system. 47b8021494Sopenharmony_ci''') 48b8021494Sopenharmony_ci 49b8021494Sopenharmony_ci 50b8021494Sopenharmony_ci# We track top-level targets to automatically generate help and alias them. 51b8021494Sopenharmony_ciclass VIXLTargets: 52b8021494Sopenharmony_ci def __init__(self): 53b8021494Sopenharmony_ci self.targets = [] 54b8021494Sopenharmony_ci self.help_messages = [] 55b8021494Sopenharmony_ci def Add(self, target, help_message): 56b8021494Sopenharmony_ci self.targets.append(target) 57b8021494Sopenharmony_ci self.help_messages.append(help_message) 58b8021494Sopenharmony_ci def Help(self): 59b8021494Sopenharmony_ci res = "" 60b8021494Sopenharmony_ci for i in range(len(self.targets)): 61b8021494Sopenharmony_ci res += '\t{0:<{1}}{2:<{3}}\n'.format( 62b8021494Sopenharmony_ci 'scons ' + self.targets[i], 63b8021494Sopenharmony_ci len('scons ') + max(map(len, self.targets)), 64b8021494Sopenharmony_ci ' : ' + self.help_messages[i], 65b8021494Sopenharmony_ci len(' : ') + max(map(len, self.help_messages))) 66b8021494Sopenharmony_ci return res 67b8021494Sopenharmony_ci 68b8021494Sopenharmony_citop_level_targets = VIXLTargets() 69b8021494Sopenharmony_ci 70b8021494Sopenharmony_ci 71b8021494Sopenharmony_ci 72b8021494Sopenharmony_ci# Build options ---------------------------------------------------------------- 73b8021494Sopenharmony_ci 74b8021494Sopenharmony_ci# Store all the options in a dictionary. 75b8021494Sopenharmony_ci# The SConstruct will check the build variables and construct the build 76b8021494Sopenharmony_ci# environment as appropriate. 77b8021494Sopenharmony_cioptions = { 78b8021494Sopenharmony_ci 'all' : { # Unconditionally processed. 79b8021494Sopenharmony_ci 'CCFLAGS' : ['-Wall', 80b8021494Sopenharmony_ci '-Werror', 81b8021494Sopenharmony_ci '-fdiagnostics-show-option', 82b8021494Sopenharmony_ci '-Wextra', 83b8021494Sopenharmony_ci '-Wredundant-decls', 84b8021494Sopenharmony_ci '-pedantic', 85b8021494Sopenharmony_ci '-Wwrite-strings', 86b8021494Sopenharmony_ci '-Wunused', 87b8021494Sopenharmony_ci '-Wshadow', 88b8021494Sopenharmony_ci '-Wno-missing-noreturn'], 89b8021494Sopenharmony_ci 'CPPPATH' : [config.dir_src_vixl] 90b8021494Sopenharmony_ci }, 91b8021494Sopenharmony_ci# 'build_option:value' : { 92b8021494Sopenharmony_ci# 'environment_key' : 'values to append' 93b8021494Sopenharmony_ci# }, 94b8021494Sopenharmony_ci 'mode:debug' : { 95b8021494Sopenharmony_ci 'CCFLAGS' : ['-DVIXL_DEBUG', '-O0'] 96b8021494Sopenharmony_ci }, 97b8021494Sopenharmony_ci 'mode:release' : { 98b8021494Sopenharmony_ci 'CCFLAGS' : ['-O3'], 99b8021494Sopenharmony_ci }, 100b8021494Sopenharmony_ci 'simulator:aarch64' : { 101b8021494Sopenharmony_ci 'CCFLAGS' : ['-DVIXL_INCLUDE_SIMULATOR_AARCH64'], 102b8021494Sopenharmony_ci }, 103b8021494Sopenharmony_ci 'symbols:on' : { 104b8021494Sopenharmony_ci 'CCFLAGS' : ['-g'], 105b8021494Sopenharmony_ci 'LINKFLAGS' : ['-g'] 106b8021494Sopenharmony_ci }, 107b8021494Sopenharmony_ci 'negative_testing:on' : { 108b8021494Sopenharmony_ci 'CCFLAGS' : ['-DVIXL_NEGATIVE_TESTING'] 109b8021494Sopenharmony_ci }, 110b8021494Sopenharmony_ci 'code_buffer_allocator:mmap' : { 111b8021494Sopenharmony_ci 'CCFLAGS' : ['-DVIXL_CODE_BUFFER_MMAP'] 112b8021494Sopenharmony_ci }, 113b8021494Sopenharmony_ci 'code_buffer_allocator:malloc' : { 114b8021494Sopenharmony_ci 'CCFLAGS' : ['-DVIXL_CODE_BUFFER_MALLOC'] 115b8021494Sopenharmony_ci }, 116b8021494Sopenharmony_ci 'ubsan:on' : { 117b8021494Sopenharmony_ci 'CCFLAGS': ['-fsanitize=undefined'], 118b8021494Sopenharmony_ci 'LINKFLAGS': ['-fsanitize=undefined'] 119b8021494Sopenharmony_ci }, 120b8021494Sopenharmony_ci 'coverage:on' : { 121b8021494Sopenharmony_ci 'CCFLAGS': ['-fprofile-instr-generate', '-fcoverage-mapping'], 122b8021494Sopenharmony_ci 'LINKFLAGS': ['-fprofile-instr-generate', '-fcoverage-mapping'] 123b8021494Sopenharmony_ci } 124b8021494Sopenharmony_ci } 125b8021494Sopenharmony_ci 126b8021494Sopenharmony_ci 127b8021494Sopenharmony_ci# A `DefaultVariable` has a default value that depends on elements not known 128b8021494Sopenharmony_ci# when variables are first evaluated. 129b8021494Sopenharmony_ci# Each `DefaultVariable` has a handler that will compute the default value for 130b8021494Sopenharmony_ci# the given environment. 131b8021494Sopenharmony_cidef modifiable_flags_handler(env): 132b8021494Sopenharmony_ci env['modifiable_flags'] = \ 133b8021494Sopenharmony_ci 'on' if 'mode' in env and env['mode'] == 'debug' else 'off' 134b8021494Sopenharmony_ci 135b8021494Sopenharmony_ci 136b8021494Sopenharmony_cidef symbols_handler(env): 137b8021494Sopenharmony_ci env['symbols'] = 'on' if 'mode' in env and env['mode'] == 'debug' else 'off' 138b8021494Sopenharmony_ci 139b8021494Sopenharmony_cidef Is32BitHost(env): 140b8021494Sopenharmony_ci return env['host_arch'] in ['aarch32', 'i386'] 141b8021494Sopenharmony_ci 142b8021494Sopenharmony_cidef IsAArch64Host(env): 143b8021494Sopenharmony_ci return env['host_arch'] == 'aarch64' 144b8021494Sopenharmony_ci 145b8021494Sopenharmony_cidef CanTargetA32(env): 146b8021494Sopenharmony_ci return 'a32' in env['target'] 147b8021494Sopenharmony_ci 148b8021494Sopenharmony_cidef CanTargetT32(env): 149b8021494Sopenharmony_ci return 't32' in env['target'] 150b8021494Sopenharmony_ci 151b8021494Sopenharmony_cidef CanTargetAArch32(env): 152b8021494Sopenharmony_ci return CanTargetA32(env) or CanTargetT32(env) 153b8021494Sopenharmony_ci 154b8021494Sopenharmony_cidef CanTargetA64(env): 155b8021494Sopenharmony_ci return 'a64' in env['target'] 156b8021494Sopenharmony_ci 157b8021494Sopenharmony_cidef CanTargetAArch64(env): 158b8021494Sopenharmony_ci return CanTargetA64(env) 159b8021494Sopenharmony_ci 160b8021494Sopenharmony_ci 161b8021494Sopenharmony_ci# By default, include the simulator only if AArch64 is targeted and we are not 162b8021494Sopenharmony_ci# building VIXL natively for AArch64. 163b8021494Sopenharmony_cidef simulator_handler(env): 164b8021494Sopenharmony_ci if not IsAArch64Host(env) and CanTargetAArch64(env): 165b8021494Sopenharmony_ci env['simulator'] = 'aarch64' 166b8021494Sopenharmony_ci else: 167b8021494Sopenharmony_ci env['simulator'] = 'none' 168b8021494Sopenharmony_ci 169b8021494Sopenharmony_ci 170b8021494Sopenharmony_ci# 'mmap' is required for use with 'mprotect', which is needed for the tests 171b8021494Sopenharmony_ci# (when running natively), so we use it by default where we can. 172b8021494Sopenharmony_cidef code_buffer_allocator_handler(env): 173b8021494Sopenharmony_ci directives = util.GetCompilerDirectives(env) 174b8021494Sopenharmony_ci if '__linux__' in directives: 175b8021494Sopenharmony_ci env['code_buffer_allocator'] = 'mmap' 176b8021494Sopenharmony_ci else: 177b8021494Sopenharmony_ci env['code_buffer_allocator'] = 'malloc' 178b8021494Sopenharmony_ci 179b8021494Sopenharmony_ci# A validator checks the consistency of provided options against the environment. 180b8021494Sopenharmony_cidef default_validator(env): 181b8021494Sopenharmony_ci pass 182b8021494Sopenharmony_ci 183b8021494Sopenharmony_ci 184b8021494Sopenharmony_cidef simulator_validator(env): 185b8021494Sopenharmony_ci if env['simulator'] == 'aarch64' and not CanTargetAArch64(env): 186b8021494Sopenharmony_ci raise UserError('Building an AArch64 simulator implies that VIXL targets ' 187b8021494Sopenharmony_ci 'AArch64. Set `target` to include `aarch64` or `a64`.') 188b8021494Sopenharmony_ci 189b8021494Sopenharmony_ci 190b8021494Sopenharmony_ci# Default variables may depend on each other, therefore we need this dictionary 191b8021494Sopenharmony_ci# to be ordered. 192b8021494Sopenharmony_civars_default_handlers = OrderedDict({ 193b8021494Sopenharmony_ci # variable_name : [ 'default val', 'handler', 'validator'] 194b8021494Sopenharmony_ci 'symbols' : [ 'mode==debug', symbols_handler, default_validator ], 195b8021494Sopenharmony_ci 'modifiable_flags' : [ 'mode==debug', modifiable_flags_handler, default_validator], 196b8021494Sopenharmony_ci 'simulator' : [ 'on if the target architectures include AArch64 but ' 197b8021494Sopenharmony_ci 'the host is not AArch64, else off', 198b8021494Sopenharmony_ci simulator_handler, simulator_validator ], 199b8021494Sopenharmony_ci 'code_buffer_allocator' : [ 'mmap with __linux__, malloc otherwise', 200b8021494Sopenharmony_ci code_buffer_allocator_handler, default_validator ] 201b8021494Sopenharmony_ci }) 202b8021494Sopenharmony_ci 203b8021494Sopenharmony_ci 204b8021494Sopenharmony_cidef DefaultVariable(name, help, allowed_values): 205b8021494Sopenharmony_ci help = '%s (%s)' % (help, '|'.join(allowed_values)) 206b8021494Sopenharmony_ci default_value = vars_default_handlers[name][0] 207b8021494Sopenharmony_ci def validator(name, value, env): 208b8021494Sopenharmony_ci if value != default_value and value not in allowed_values: 209b8021494Sopenharmony_ci raise UserError('Invalid value for option {name}: {value}. ' 210b8021494Sopenharmony_ci 'Valid values are: {allowed_values}'.format( 211b8021494Sopenharmony_ci name, value, allowed_values)) 212b8021494Sopenharmony_ci return (name, help, default_value, validator) 213b8021494Sopenharmony_ci 214b8021494Sopenharmony_ci 215b8021494Sopenharmony_cidef SortListVariable(iterator): 216b8021494Sopenharmony_ci # Previously this code relied on the order of items in a list 217b8021494Sopenharmony_ci # converted from a set. However in Python 3 the order changes each run. 218b8021494Sopenharmony_ci # Here we do a custom partial sort to ensure that the build directory 219b8021494Sopenharmony_ci # name is stable, the same across Python 2 and 3, and the same as the 220b8021494Sopenharmony_ci # old code. 221b8021494Sopenharmony_ci result = list(sorted(iterator)) 222b8021494Sopenharmony_ci result = sorted(result, key=lambda x: x == 't32', reverse=True) 223b8021494Sopenharmony_ci result = sorted(result, key=lambda x: x == 'a32', reverse=True) 224b8021494Sopenharmony_ci result = sorted(result, key=lambda x: x == 'a64', reverse=True) 225b8021494Sopenharmony_ci return result 226b8021494Sopenharmony_ci 227b8021494Sopenharmony_ci 228b8021494Sopenharmony_cidef AliasedListVariable(name, help, default_value, allowed_values, aliasing): 229b8021494Sopenharmony_ci help = '%s (all|auto|comma-separated list) (any combination from [%s])' % \ 230b8021494Sopenharmony_ci (help, ', '.join(allowed_values)) 231b8021494Sopenharmony_ci 232b8021494Sopenharmony_ci def validator(name, value, env): 233b8021494Sopenharmony_ci # Here list has been converted to space separated strings. 234b8021494Sopenharmony_ci if value == '': return # auto 235b8021494Sopenharmony_ci for v in value.split(): 236b8021494Sopenharmony_ci if v not in allowed_values: 237b8021494Sopenharmony_ci raise UserError('Invalid value for %s: %s' % (name, value)) 238b8021494Sopenharmony_ci 239b8021494Sopenharmony_ci def converter(value): 240b8021494Sopenharmony_ci if value == 'auto': return [] 241b8021494Sopenharmony_ci if value == 'all': 242b8021494Sopenharmony_ci translated = [aliasing[v] for v in allowed_values] 243b8021494Sopenharmony_ci return SortListVariable(itertools.chain.from_iterable(translated)) 244b8021494Sopenharmony_ci # The validator is run later hence the get. 245b8021494Sopenharmony_ci translated = [aliasing.get(v, v) for v in value.split(',')] 246b8021494Sopenharmony_ci return SortListVariable(itertools.chain.from_iterable(translated)) 247b8021494Sopenharmony_ci 248b8021494Sopenharmony_ci return (name, help, default_value, validator, converter) 249b8021494Sopenharmony_ci 250b8021494Sopenharmony_ci 251b8021494Sopenharmony_civars = Variables() 252b8021494Sopenharmony_ci# Define command line build options. 253b8021494Sopenharmony_civars.AddVariables( 254b8021494Sopenharmony_ci AliasedListVariable('target', 'Target ISA/Architecture', 'auto', 255b8021494Sopenharmony_ci ['aarch32', 'a32', 't32', 'aarch64', 'a64'], 256b8021494Sopenharmony_ci {'aarch32' : ['a32', 't32'], 257b8021494Sopenharmony_ci 'a32' : ['a32'], 't32' : ['t32'], 258b8021494Sopenharmony_ci 'aarch64' : ['a64'], 'a64' : ['a64']}), 259b8021494Sopenharmony_ci EnumVariable('mode', 'Build mode', 260b8021494Sopenharmony_ci 'release', allowed_values=config.build_options_modes), 261b8021494Sopenharmony_ci EnumVariable('ubsan', 'Enable undefined behavior checks', 262b8021494Sopenharmony_ci 'off', allowed_values=['on', 'off']), 263b8021494Sopenharmony_ci EnumVariable('coverage', 'Enable code coverage measurement', 264b8021494Sopenharmony_ci 'off', allowed_values=['on', 'off']), 265b8021494Sopenharmony_ci EnumVariable('negative_testing', 266b8021494Sopenharmony_ci 'Enable negative testing (needs exceptions)', 267b8021494Sopenharmony_ci 'off', allowed_values=['on', 'off']), 268b8021494Sopenharmony_ci DefaultVariable('symbols', 'Include debugging symbols in the binaries', 269b8021494Sopenharmony_ci ['on', 'off']), 270b8021494Sopenharmony_ci DefaultVariable('simulator', 'Simulators to include', ['aarch64', 'none']), 271b8021494Sopenharmony_ci DefaultVariable('code_buffer_allocator', 272b8021494Sopenharmony_ci 'Configure the allocation mechanism in the CodeBuffer', 273b8021494Sopenharmony_ci ['malloc', 'mmap']), 274b8021494Sopenharmony_ci ('std', 275b8021494Sopenharmony_ci 'C++ standard. The standards tested are: %s.' % \ 276b8021494Sopenharmony_ci ', '.join(config.tested_cpp_standards), 277b8021494Sopenharmony_ci config.tested_cpp_standards[0]), 278b8021494Sopenharmony_ci ('compiler_wrapper', 'Command to prefix to the C and C++ compiler (e.g ccache)', '') 279b8021494Sopenharmony_ci ) 280b8021494Sopenharmony_ci 281b8021494Sopenharmony_ci# We use 'variant directories' to avoid recompiling multiple times when build 282b8021494Sopenharmony_ci# options are changed, different build paths are used depending on the options 283b8021494Sopenharmony_ci# set. These are the options that should be reflected in the build directory 284b8021494Sopenharmony_ci# path. 285b8021494Sopenharmony_cioptions_influencing_build_path = [ 286b8021494Sopenharmony_ci 'target', 'mode', 'symbols', 'compiler', 'std', 'simulator', 'negative_testing', 287b8021494Sopenharmony_ci 'code_buffer_allocator' 288b8021494Sopenharmony_ci] 289b8021494Sopenharmony_ci 290b8021494Sopenharmony_ci 291b8021494Sopenharmony_ci 292b8021494Sopenharmony_ci# Build helpers ---------------------------------------------------------------- 293b8021494Sopenharmony_ci 294b8021494Sopenharmony_cidef RetrieveEnvironmentVariables(env): 295b8021494Sopenharmony_ci for key in ['CC', 'CXX', 'AR', 'RANLIB', 'LD']: 296b8021494Sopenharmony_ci if os.getenv(key): env[key] = os.getenv(key) 297b8021494Sopenharmony_ci if os.getenv('LD_LIBRARY_PATH'): env['LIBPATH'] = os.getenv('LD_LIBRARY_PATH') 298b8021494Sopenharmony_ci if os.getenv('CCFLAGS'): 299b8021494Sopenharmony_ci env.Append(CCFLAGS = os.getenv('CCFLAGS').split()) 300b8021494Sopenharmony_ci if os.getenv('CXXFLAGS'): 301b8021494Sopenharmony_ci env.Append(CXXFLAGS = os.getenv('CXXFLAGS').split()) 302b8021494Sopenharmony_ci if os.getenv('LINKFLAGS'): 303b8021494Sopenharmony_ci env.Append(LINKFLAGS = os.getenv('LINKFLAGS').split()) 304b8021494Sopenharmony_ci 305b8021494Sopenharmony_ci# The architecture targeted by default will depend on the compiler being 306b8021494Sopenharmony_ci# used. 'host_arch' is extracted from the compiler while 'target' can be 307b8021494Sopenharmony_ci# set by the user. 308b8021494Sopenharmony_ci# By default, we target both AArch32 and AArch64 unless the compiler targets a 309b8021494Sopenharmony_ci# 32-bit architecture. At the moment, we cannot build VIXL's AArch64 support on 310b8021494Sopenharmony_ci# a 32-bit platform. 311b8021494Sopenharmony_ci# TODO: Port VIXL to build on a 32-bit platform. 312b8021494Sopenharmony_cidef target_handler(env): 313b8021494Sopenharmony_ci # Auto detect 314b8021494Sopenharmony_ci if Is32BitHost(env): 315b8021494Sopenharmony_ci # We use list(set(...)) to keep the same order as if it was specify as 316b8021494Sopenharmony_ci # an option. 317b8021494Sopenharmony_ci env['target'] = SortListVariable(['a32', 't32']) 318b8021494Sopenharmony_ci else: 319b8021494Sopenharmony_ci env['target'] = SortListVariable(['a64', 'a32', 't32']) 320b8021494Sopenharmony_ci 321b8021494Sopenharmony_ci 322b8021494Sopenharmony_cidef target_validator(env): 323b8021494Sopenharmony_ci # TODO: Port VIXL64 to work on a 32-bit platform. 324b8021494Sopenharmony_ci if Is32BitHost(env) and CanTargetAArch64(env): 325b8021494Sopenharmony_ci raise UserError('Building VIXL for AArch64 in 32-bit is not supported. Set ' 326b8021494Sopenharmony_ci '`target` to `aarch32`') 327b8021494Sopenharmony_ci 328b8021494Sopenharmony_ci 329b8021494Sopenharmony_ci# The target option is handled differently from the rest. 330b8021494Sopenharmony_cidef ProcessTargetOption(env): 331b8021494Sopenharmony_ci if env['target'] == []: target_handler(env) 332b8021494Sopenharmony_ci 333b8021494Sopenharmony_ci if 'a32' in env['target']: env['CCFLAGS'] += ['-DVIXL_INCLUDE_TARGET_A32'] 334b8021494Sopenharmony_ci if 't32' in env['target']: env['CCFLAGS'] += ['-DVIXL_INCLUDE_TARGET_T32'] 335b8021494Sopenharmony_ci if 'a64' in env['target']: env['CCFLAGS'] += ['-DVIXL_INCLUDE_TARGET_A64'] 336b8021494Sopenharmony_ci 337b8021494Sopenharmony_ci target_validator(env) 338b8021494Sopenharmony_ci 339b8021494Sopenharmony_ci 340b8021494Sopenharmony_cidef ProcessBuildOptions(env): 341b8021494Sopenharmony_ci # 'all' is unconditionally processed. 342b8021494Sopenharmony_ci if 'all' in options: 343b8021494Sopenharmony_ci for var in options['all']: 344b8021494Sopenharmony_ci if var in env and env[var]: 345b8021494Sopenharmony_ci env[var] += options['all'][var] 346b8021494Sopenharmony_ci else: 347b8021494Sopenharmony_ci env[var] = options['all'][var] 348b8021494Sopenharmony_ci 349b8021494Sopenharmony_ci # The target option *must* be processed before the options defined in 350b8021494Sopenharmony_ci # vars_default_handlers. 351b8021494Sopenharmony_ci ProcessTargetOption(env) 352b8021494Sopenharmony_ci 353b8021494Sopenharmony_ci # Other build options must match 'option:value' 354b8021494Sopenharmony_ci env_dict = env.Dictionary() 355b8021494Sopenharmony_ci 356b8021494Sopenharmony_ci # First apply the default variables handlers in order. 357b8021494Sopenharmony_ci for key, value in vars_default_handlers.items(): 358b8021494Sopenharmony_ci default = value[0] 359b8021494Sopenharmony_ci handler = value[1] 360b8021494Sopenharmony_ci if env_dict.get(key) == default: 361b8021494Sopenharmony_ci handler(env_dict) 362b8021494Sopenharmony_ci 363b8021494Sopenharmony_ci # Second, run the series of validators, to check for errors. 364b8021494Sopenharmony_ci for _, value in vars_default_handlers.items(): 365b8021494Sopenharmony_ci validator = value[2] 366b8021494Sopenharmony_ci validator(env) 367b8021494Sopenharmony_ci 368b8021494Sopenharmony_ci for key in env_dict.keys(): 369b8021494Sopenharmony_ci # Then update the environment according to the value of the variable. 370b8021494Sopenharmony_ci key_val_couple = key + ':%s' % env_dict[key] 371b8021494Sopenharmony_ci if key_val_couple in options: 372b8021494Sopenharmony_ci for var in options[key_val_couple]: 373b8021494Sopenharmony_ci env[var] += options[key_val_couple][var] 374b8021494Sopenharmony_ci 375b8021494Sopenharmony_ci 376b8021494Sopenharmony_cidef ConfigureEnvironmentForCompiler(env): 377b8021494Sopenharmony_ci compiler = util.CompilerInformation(env) 378b8021494Sopenharmony_ci if compiler == 'clang': 379b8021494Sopenharmony_ci # These warnings only work for Clang. 380b8021494Sopenharmony_ci # -Wimplicit-fallthrough only works when compiling the code base as C++11 or 381b8021494Sopenharmony_ci # newer. The compiler does not complain if the option is passed when 382b8021494Sopenharmony_ci # compiling earlier C++ standards. 383b8021494Sopenharmony_ci env.Append(CPPFLAGS = ['-Wimplicit-fallthrough', '-Wshorten-64-to-32']) 384b8021494Sopenharmony_ci 385b8021494Sopenharmony_ci # The '-Wunreachable-code' flag breaks builds for clang 3.4. 386b8021494Sopenharmony_ci if compiler != 'clang-3.4': 387b8021494Sopenharmony_ci env.Append(CPPFLAGS = ['-Wunreachable-code']) 388b8021494Sopenharmony_ci 389b8021494Sopenharmony_ci if env['ubsan'] == 'on': 390b8021494Sopenharmony_ci env.Append(LINKFLAGS = ['-fuse-ld=lld']) 391b8021494Sopenharmony_ci 392b8021494Sopenharmony_ci # GCC 4.8 has a bug which produces a warning saying that an anonymous Operand 393b8021494Sopenharmony_ci # object might be used uninitialized: 394b8021494Sopenharmony_ci # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57045 395b8021494Sopenharmony_ci # The bug does not seem to appear in GCC 4.7, or in debug builds with GCC 4.8. 396b8021494Sopenharmony_ci if env['mode'] == 'release': 397b8021494Sopenharmony_ci if compiler == 'gcc-4.8': 398b8021494Sopenharmony_ci env.Append(CPPFLAGS = ['-Wno-maybe-uninitialized']) 399b8021494Sopenharmony_ci 400b8021494Sopenharmony_ci # GCC 6 and higher is able to detect throwing from inside a destructor and 401b8021494Sopenharmony_ci # reports a warning. However, if negative testing is enabled then assertions 402b8021494Sopenharmony_ci # will throw exceptions. 403b8021494Sopenharmony_ci if env['negative_testing'] == 'on' and env['mode'] == 'debug' \ 404b8021494Sopenharmony_ci and compiler >= 'gcc-6': 405b8021494Sopenharmony_ci env.Append(CPPFLAGS = ['-Wno-terminate']) 406b8021494Sopenharmony_ci 407b8021494Sopenharmony_ci # Suggest missing override keywords on methods. 408b8021494Sopenharmony_ci if compiler >= 'gcc-5': 409b8021494Sopenharmony_ci env.Append(CPPFLAGS = ['-Wsuggest-override']) 410b8021494Sopenharmony_ci elif compiler >= 'clang-3.6': 411b8021494Sopenharmony_ci env.Append(CPPFLAGS = ['-Winconsistent-missing-override']) 412b8021494Sopenharmony_ci 413b8021494Sopenharmony_ci 414b8021494Sopenharmony_cidef ConfigureEnvironment(env): 415b8021494Sopenharmony_ci RetrieveEnvironmentVariables(env) 416b8021494Sopenharmony_ci env['compiler'] = env['CXX'] 417b8021494Sopenharmony_ci if env['compiler_wrapper'] != '': 418b8021494Sopenharmony_ci env['CXX'] = env['compiler_wrapper'] + ' ' + env['CXX'] 419b8021494Sopenharmony_ci env['CC'] = env['compiler_wrapper'] + ' ' + env['CC'] 420b8021494Sopenharmony_ci env['host_arch'] = util.GetHostArch(env) 421b8021494Sopenharmony_ci ProcessBuildOptions(env) 422b8021494Sopenharmony_ci if 'std' in env: 423b8021494Sopenharmony_ci env.Append(CPPFLAGS = ['-std=' + env['std']]) 424b8021494Sopenharmony_ci std_path = env['std'] 425b8021494Sopenharmony_ci ConfigureEnvironmentForCompiler(env) 426b8021494Sopenharmony_ci 427b8021494Sopenharmony_ci 428b8021494Sopenharmony_cidef TargetBuildDir(env): 429b8021494Sopenharmony_ci # Build-time option values are embedded in the build path to avoid requiring a 430b8021494Sopenharmony_ci # full build when an option changes. 431b8021494Sopenharmony_ci build_dir = config.dir_build 432b8021494Sopenharmony_ci for option in options_influencing_build_path: 433b8021494Sopenharmony_ci option_value = ''.join(env[option]) if option in env else '' 434b8021494Sopenharmony_ci build_dir = join(build_dir, option + '_'+ option_value) 435b8021494Sopenharmony_ci return build_dir 436b8021494Sopenharmony_ci 437b8021494Sopenharmony_ci 438b8021494Sopenharmony_cidef PrepareVariantDir(location, build_dir): 439b8021494Sopenharmony_ci location_build_dir = join(build_dir, location) 440b8021494Sopenharmony_ci VariantDir(location_build_dir, location) 441b8021494Sopenharmony_ci return location_build_dir 442b8021494Sopenharmony_ci 443b8021494Sopenharmony_ci 444b8021494Sopenharmony_cidef VIXLLibraryTarget(env): 445b8021494Sopenharmony_ci build_dir = TargetBuildDir(env) 446b8021494Sopenharmony_ci # Create a link to the latest build directory. 447b8021494Sopenharmony_ci # Use `-r` to avoid failure when `latest` exists and is a directory. 448b8021494Sopenharmony_ci subprocess.check_call(["rm", "-rf", config.dir_build_latest]) 449b8021494Sopenharmony_ci util.ensure_dir(build_dir) 450b8021494Sopenharmony_ci subprocess.check_call(["ln", "-s", build_dir, config.dir_build_latest]) 451b8021494Sopenharmony_ci # Source files are in `src` and in `src/aarch64/`. 452b8021494Sopenharmony_ci variant_dir_vixl = PrepareVariantDir(join('src'), build_dir) 453b8021494Sopenharmony_ci sources = [Glob(join(variant_dir_vixl, '*.cc'))] 454b8021494Sopenharmony_ci if CanTargetAArch32(env): 455b8021494Sopenharmony_ci variant_dir_aarch32 = PrepareVariantDir(join('src', 'aarch32'), build_dir) 456b8021494Sopenharmony_ci sources.append(Glob(join(variant_dir_aarch32, '*.cc'))) 457b8021494Sopenharmony_ci if CanTargetAArch64(env): 458b8021494Sopenharmony_ci variant_dir_aarch64 = PrepareVariantDir(join('src', 'aarch64'), build_dir) 459b8021494Sopenharmony_ci sources.append(Glob(join(variant_dir_aarch64, '*.cc'))) 460b8021494Sopenharmony_ci return env.Library(join(build_dir, 'vixl'), sources) 461b8021494Sopenharmony_ci 462b8021494Sopenharmony_ci 463b8021494Sopenharmony_ci 464b8021494Sopenharmony_ci# Build ------------------------------------------------------------------------ 465b8021494Sopenharmony_ci 466b8021494Sopenharmony_ci# The VIXL library, built by default. 467b8021494Sopenharmony_cienv = Environment(variables = vars, 468b8021494Sopenharmony_ci BUILDERS = { 469b8021494Sopenharmony_ci 'Markdown': Builder(action = 'markdown $SOURCE > $TARGET', 470b8021494Sopenharmony_ci suffix = '.html') 471b8021494Sopenharmony_ci }, ENV = os.environ) 472b8021494Sopenharmony_ci# Abort the build if any command line option is unknown or invalid. 473b8021494Sopenharmony_ciunknown_build_options = vars.UnknownVariables() 474b8021494Sopenharmony_ciif unknown_build_options: 475b8021494Sopenharmony_ci print('Unknown build options: ' + str(unknown_build_options.keys())) 476b8021494Sopenharmony_ci Exit(1) 477b8021494Sopenharmony_ci 478b8021494Sopenharmony_ciif env['negative_testing'] == 'on' and env['mode'] != 'debug': 479b8021494Sopenharmony_ci print('negative_testing only works in debug mode') 480b8021494Sopenharmony_ci Exit(1) 481b8021494Sopenharmony_ci 482b8021494Sopenharmony_ciConfigureEnvironment(env) 483b8021494Sopenharmony_ciHelp(vars.GenerateHelpText(env)) 484b8021494Sopenharmony_cilibvixl = VIXLLibraryTarget(env) 485b8021494Sopenharmony_ciDefault(libvixl) 486b8021494Sopenharmony_cienv.Alias('libvixl', libvixl) 487b8021494Sopenharmony_citop_level_targets.Add('', 'Build the VIXL library.') 488b8021494Sopenharmony_ci 489b8021494Sopenharmony_ci 490b8021494Sopenharmony_ci# Common test code. 491b8021494Sopenharmony_citest_build_dir = PrepareVariantDir('test', TargetBuildDir(env)) 492b8021494Sopenharmony_citest_objects = [env.Object(Glob(join(test_build_dir, '*.cc'), exclude=join(test_build_dir, 'test-donkey.cc')))] 493b8021494Sopenharmony_ci 494b8021494Sopenharmony_ci# AArch32 support 495b8021494Sopenharmony_ciif CanTargetAArch32(env): 496b8021494Sopenharmony_ci # The examples. 497b8021494Sopenharmony_ci aarch32_example_names = util.ListCCFilesWithoutExt(config.dir_aarch32_examples) 498b8021494Sopenharmony_ci aarch32_examples_build_dir = PrepareVariantDir('examples/aarch32', TargetBuildDir(env)) 499b8021494Sopenharmony_ci aarch32_example_targets = [] 500b8021494Sopenharmony_ci for example in aarch32_example_names: 501b8021494Sopenharmony_ci prog = env.Program(join(aarch32_examples_build_dir, example), 502b8021494Sopenharmony_ci join(aarch32_examples_build_dir, example + '.cc'), 503b8021494Sopenharmony_ci LIBS=[libvixl]) 504b8021494Sopenharmony_ci aarch32_example_targets.append(prog) 505b8021494Sopenharmony_ci env.Alias('aarch32_examples', aarch32_example_targets) 506b8021494Sopenharmony_ci top_level_targets.Add('aarch32_examples', 'Build the examples for AArch32.') 507b8021494Sopenharmony_ci 508b8021494Sopenharmony_ci # The benchmarks 509b8021494Sopenharmony_ci aarch32_benchmark_names = util.ListCCFilesWithoutExt(config.dir_aarch32_benchmarks) 510b8021494Sopenharmony_ci aarch32_benchmarks_build_dir = PrepareVariantDir('benchmarks/aarch32', TargetBuildDir(env)) 511b8021494Sopenharmony_ci aarch32_benchmark_targets = [] 512b8021494Sopenharmony_ci for bench in aarch32_benchmark_names: 513b8021494Sopenharmony_ci prog = env.Program(join(aarch32_benchmarks_build_dir, bench), 514b8021494Sopenharmony_ci join(aarch32_benchmarks_build_dir, bench + '.cc'), 515b8021494Sopenharmony_ci LIBS=[libvixl]) 516b8021494Sopenharmony_ci aarch32_benchmark_targets.append(prog) 517b8021494Sopenharmony_ci env.Alias('aarch32_benchmarks', aarch32_benchmark_targets) 518b8021494Sopenharmony_ci top_level_targets.Add('aarch32_benchmarks', 'Build the benchmarks for AArch32.') 519b8021494Sopenharmony_ci 520b8021494Sopenharmony_ci # The tests. 521b8021494Sopenharmony_ci test_aarch32_build_dir = PrepareVariantDir(join('test', 'aarch32'), TargetBuildDir(env)) 522b8021494Sopenharmony_ci test_objects.append(env.Object( 523b8021494Sopenharmony_ci Glob(join(test_aarch32_build_dir, '*.cc')), 524b8021494Sopenharmony_ci CPPPATH = env['CPPPATH'] + [config.dir_tests], 525b8021494Sopenharmony_ci CCFLAGS = [flag for flag in env['CCFLAGS'] if flag != '-O3'])) 526b8021494Sopenharmony_ci 527b8021494Sopenharmony_ci# AArch64 support 528b8021494Sopenharmony_ciif CanTargetAArch64(env): 529b8021494Sopenharmony_ci # The benchmarks. 530b8021494Sopenharmony_ci aarch64_benchmark_names = util.ListCCFilesWithoutExt(config.dir_aarch64_benchmarks) 531b8021494Sopenharmony_ci aarch64_benchmarks_build_dir = PrepareVariantDir('benchmarks/aarch64', TargetBuildDir(env)) 532b8021494Sopenharmony_ci aarch64_benchmark_targets = [] 533b8021494Sopenharmony_ci bench_utils = env.Object(join(aarch64_benchmarks_build_dir, 'bench-utils.o'), 534b8021494Sopenharmony_ci join(aarch64_benchmarks_build_dir, 'bench-utils.cc')) 535b8021494Sopenharmony_ci for bench in aarch64_benchmark_names: 536b8021494Sopenharmony_ci if bench != 'bench-utils': 537b8021494Sopenharmony_ci prog = env.Program(join(aarch64_benchmarks_build_dir, bench), 538b8021494Sopenharmony_ci [join(aarch64_benchmarks_build_dir, bench + '.cc'), bench_utils], 539b8021494Sopenharmony_ci LIBS=[libvixl]) 540b8021494Sopenharmony_ci aarch64_benchmark_targets.append(prog) 541b8021494Sopenharmony_ci env.Alias('aarch64_benchmarks', aarch64_benchmark_targets) 542b8021494Sopenharmony_ci top_level_targets.Add('aarch64_benchmarks', 'Build the benchmarks for AArch64.') 543b8021494Sopenharmony_ci 544b8021494Sopenharmony_ci # The examples. 545b8021494Sopenharmony_ci aarch64_example_names = util.ListCCFilesWithoutExt(config.dir_aarch64_examples) 546b8021494Sopenharmony_ci aarch64_examples_build_dir = PrepareVariantDir('examples/aarch64', TargetBuildDir(env)) 547b8021494Sopenharmony_ci aarch64_example_targets = [] 548b8021494Sopenharmony_ci for example in aarch64_example_names: 549b8021494Sopenharmony_ci prog = env.Program(join(aarch64_examples_build_dir, example), 550b8021494Sopenharmony_ci join(aarch64_examples_build_dir, example + '.cc'), 551b8021494Sopenharmony_ci LIBS=[libvixl]) 552b8021494Sopenharmony_ci aarch64_example_targets.append(prog) 553b8021494Sopenharmony_ci env.Alias('aarch64_examples', aarch64_example_targets) 554b8021494Sopenharmony_ci top_level_targets.Add('aarch64_examples', 'Build the examples for AArch64.') 555b8021494Sopenharmony_ci 556b8021494Sopenharmony_ci # The tests. 557b8021494Sopenharmony_ci test_aarch64_build_dir = PrepareVariantDir(join('test', 'aarch64'), TargetBuildDir(env)) 558b8021494Sopenharmony_ci test_objects.append(env.Object( 559b8021494Sopenharmony_ci Glob(join(test_aarch64_build_dir, '*.cc')), 560b8021494Sopenharmony_ci CPPPATH = env['CPPPATH'] + [config.dir_tests], 561b8021494Sopenharmony_ci CCFLAGS = [flag for flag in env['CCFLAGS'] if flag != '-O3'])) 562b8021494Sopenharmony_ci 563b8021494Sopenharmony_ci # The test requires building the example files with specific options, so we 564b8021494Sopenharmony_ci # create a separate variant dir for the example objects built this way. 565b8021494Sopenharmony_ci test_aarch64_examples_vdir = join(TargetBuildDir(env), 'test', 'aarch64', 'test_examples') 566b8021494Sopenharmony_ci VariantDir(test_aarch64_examples_vdir, '.') 567b8021494Sopenharmony_ci test_aarch64_examples_obj = env.Object( 568b8021494Sopenharmony_ci [Glob(join(test_aarch64_examples_vdir, join('test', 'aarch64', 'examples', '*.cc'))), 569b8021494Sopenharmony_ci Glob(join(test_aarch64_examples_vdir, join('examples/aarch64', '*.cc')))], 570b8021494Sopenharmony_ci CCFLAGS = env['CCFLAGS'] + ['-DTEST_EXAMPLES'], 571b8021494Sopenharmony_ci CPPPATH = env['CPPPATH'] + [config.dir_aarch64_examples] + [config.dir_tests]) 572b8021494Sopenharmony_ci test_objects.append(test_aarch64_examples_obj) 573b8021494Sopenharmony_ci 574b8021494Sopenharmony_ci # The simulator test generator. 575b8021494Sopenharmony_ci donkey_objects = [] 576b8021494Sopenharmony_ci donkey_objects.append(env.Object( 577b8021494Sopenharmony_ci [join(test_build_dir, 'test-donkey.cc'), join(test_aarch64_build_dir, 'test-utils-aarch64.cc')], 578b8021494Sopenharmony_ci CPPPATH = env['CPPPATH'] + [config.dir_tests], 579b8021494Sopenharmony_ci CCFLAGS = [flag for flag in env['CCFLAGS'] if flag != '-O3'])) 580b8021494Sopenharmony_ci donkey = env.Program(join(test_build_dir, 'test-donkey'), donkey_objects, LIBS=[libvixl]) 581b8021494Sopenharmony_ci env.Alias('tests', donkey) 582b8021494Sopenharmony_ci 583b8021494Sopenharmony_citest = env.Program(join(test_build_dir, 'test-runner'), test_objects, 584b8021494Sopenharmony_ci LIBS=[libvixl]) 585b8021494Sopenharmony_cienv.Alias('tests', test) 586b8021494Sopenharmony_citop_level_targets.Add('tests', 'Build the tests.') 587b8021494Sopenharmony_ci 588b8021494Sopenharmony_ci 589b8021494Sopenharmony_cienv.Alias('all', top_level_targets.targets) 590b8021494Sopenharmony_citop_level_targets.Add('all', 'Build all the targets above.') 591b8021494Sopenharmony_ci 592b8021494Sopenharmony_ciHelp('\n\nAvailable top level targets:\n' + top_level_targets.Help()) 593b8021494Sopenharmony_ci 594b8021494Sopenharmony_ciextra_targets = VIXLTargets() 595b8021494Sopenharmony_ci 596b8021494Sopenharmony_ci# Build documentation 597b8021494Sopenharmony_cidoc = [ 598b8021494Sopenharmony_ci env.Markdown('README.md'), 599b8021494Sopenharmony_ci env.Markdown('doc/changelog.md'), 600b8021494Sopenharmony_ci env.Markdown('doc/aarch32/getting-started-aarch32.md'), 601b8021494Sopenharmony_ci env.Markdown('doc/aarch32/design/code-generation-aarch32.md'), 602b8021494Sopenharmony_ci env.Markdown('doc/aarch32/design/literal-pool-aarch32.md'), 603b8021494Sopenharmony_ci env.Markdown('doc/aarch64/supported-instructions-aarch64.md'), 604b8021494Sopenharmony_ci env.Markdown('doc/aarch64/getting-started-aarch64.md'), 605b8021494Sopenharmony_ci env.Markdown('doc/aarch64/topics/ycm.md'), 606b8021494Sopenharmony_ci env.Markdown('doc/aarch64/topics/extending-the-disassembler.md'), 607b8021494Sopenharmony_ci env.Markdown('doc/aarch64/topics/index.md'), 608b8021494Sopenharmony_ci] 609b8021494Sopenharmony_cienv.Alias('doc', doc) 610b8021494Sopenharmony_ciextra_targets.Add('doc', 'Convert documentation to HTML (requires the ' 611b8021494Sopenharmony_ci '`markdown` program).') 612b8021494Sopenharmony_ci 613b8021494Sopenharmony_ciHelp('\nAvailable extra targets:\n' + extra_targets.Help()) 614