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