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 }, 103 'symbols:on' : { 104 'CCFLAGS' : ['-g'], 105 'LINKFLAGS' : ['-g'] 106 }, 107 'negative_testing:on' : { 108 'CCFLAGS' : ['-DVIXL_NEGATIVE_TESTING'] 109 }, 110 'code_buffer_allocator:mmap' : { 111 'CCFLAGS' : ['-DVIXL_CODE_BUFFER_MMAP'] 112 }, 113 'code_buffer_allocator:malloc' : { 114 'CCFLAGS' : ['-DVIXL_CODE_BUFFER_MALLOC'] 115 }, 116 'ubsan:on' : { 117 'CCFLAGS': ['-fsanitize=undefined'], 118 'LINKFLAGS': ['-fsanitize=undefined'] 119 }, 120 'coverage:on' : { 121 'CCFLAGS': ['-fprofile-instr-generate', '-fcoverage-mapping'], 122 'LINKFLAGS': ['-fprofile-instr-generate', '-fcoverage-mapping'] 123 } 124 } 125 126 127# A `DefaultVariable` has a default value that depends on elements not known 128# when variables are first evaluated. 129# Each `DefaultVariable` has a handler that will compute the default value for 130# the given environment. 131def modifiable_flags_handler(env): 132 env['modifiable_flags'] = \ 133 'on' if 'mode' in env and env['mode'] == 'debug' else 'off' 134 135 136def symbols_handler(env): 137 env['symbols'] = 'on' if 'mode' in env and env['mode'] == 'debug' else 'off' 138 139def Is32BitHost(env): 140 return env['host_arch'] in ['aarch32', 'i386'] 141 142def IsAArch64Host(env): 143 return env['host_arch'] == 'aarch64' 144 145def CanTargetA32(env): 146 return 'a32' in env['target'] 147 148def CanTargetT32(env): 149 return 't32' in env['target'] 150 151def CanTargetAArch32(env): 152 return CanTargetA32(env) or CanTargetT32(env) 153 154def CanTargetA64(env): 155 return 'a64' in env['target'] 156 157def CanTargetAArch64(env): 158 return CanTargetA64(env) 159 160 161# By default, include the simulator only if AArch64 is targeted and we are not 162# building VIXL natively for AArch64. 163def simulator_handler(env): 164 if not IsAArch64Host(env) and CanTargetAArch64(env): 165 env['simulator'] = 'aarch64' 166 else: 167 env['simulator'] = 'none' 168 169 170# 'mmap' is required for use with 'mprotect', which is needed for the tests 171# (when running natively), so we use it by default where we can. 172def code_buffer_allocator_handler(env): 173 directives = util.GetCompilerDirectives(env) 174 if '__linux__' in directives: 175 env['code_buffer_allocator'] = 'mmap' 176 else: 177 env['code_buffer_allocator'] = 'malloc' 178 179# A validator checks the consistency of provided options against the environment. 180def default_validator(env): 181 pass 182 183 184def simulator_validator(env): 185 if env['simulator'] == 'aarch64' and not CanTargetAArch64(env): 186 raise UserError('Building an AArch64 simulator implies that VIXL targets ' 187 'AArch64. Set `target` to include `aarch64` or `a64`.') 188 189 190# Default variables may depend on each other, therefore we need this dictionnary 191# to be ordered. 192vars_default_handlers = OrderedDict({ 193 # variable_name : [ 'default val', 'handler', 'validator'] 194 'symbols' : [ 'mode==debug', symbols_handler, default_validator ], 195 'modifiable_flags' : [ 'mode==debug', modifiable_flags_handler, default_validator], 196 'simulator' : [ 'on if the target architectures include AArch64 but ' 197 'the host is not AArch64, else off', 198 simulator_handler, simulator_validator ], 199 'code_buffer_allocator' : [ 'mmap with __linux__, malloc otherwise', 200 code_buffer_allocator_handler, default_validator ] 201 }) 202 203 204def DefaultVariable(name, help, allowed_values): 205 help = '%s (%s)' % (help, '|'.join(allowed_values)) 206 default_value = vars_default_handlers[name][0] 207 def validator(name, value, env): 208 if value != default_value and value not in allowed_values: 209 raise UserError('Invalid value for option {name}: {value}. ' 210 'Valid values are: {allowed_values}'.format( 211 name, value, allowed_values)) 212 return (name, help, default_value, validator) 213 214 215def SortListVariable(iterator): 216 # Previously this code relied on the order of items in a list 217 # converted from a set. However in Python 3 the order changes each run. 218 # Here we do a custom partial sort to ensure that the build directory 219 # name is stable, the same across Python 2 and 3, and the same as the 220 # old code. 221 result = list(sorted(iterator)) 222 result = sorted(result, key=lambda x: x == 't32', reverse=True) 223 result = sorted(result, key=lambda x: x == 'a32', reverse=True) 224 result = sorted(result, key=lambda x: x == 'a64', reverse=True) 225 return result 226 227 228def AliasedListVariable(name, help, default_value, allowed_values, aliasing): 229 help = '%s (all|auto|comma-separated list) (any combination from [%s])' % \ 230 (help, ', '.join(allowed_values)) 231 232 def validator(name, value, env): 233 # Here list has been converted to space separated strings. 234 if value == '': return # auto 235 for v in value.split(): 236 if v not in allowed_values: 237 raise UserError('Invalid value for %s: %s' % (name, value)) 238 239 def converter(value): 240 if value == 'auto': return [] 241 if value == 'all': 242 translated = [aliasing[v] for v in allowed_values] 243 return SortListVariable(itertools.chain.from_iterable(translated)) 244 # The validator is run later hence the get. 245 translated = [aliasing.get(v, v) for v in value.split(',')] 246 return SortListVariable(itertools.chain.from_iterable(translated)) 247 248 return (name, help, default_value, validator, converter) 249 250 251vars = Variables() 252# Define command line build options. 253vars.AddVariables( 254 AliasedListVariable('target', 'Target ISA/Architecture', 'auto', 255 ['aarch32', 'a32', 't32', 'aarch64', 'a64'], 256 {'aarch32' : ['a32', 't32'], 257 'a32' : ['a32'], 't32' : ['t32'], 258 'aarch64' : ['a64'], 'a64' : ['a64']}), 259 EnumVariable('mode', 'Build mode', 260 'release', allowed_values=config.build_options_modes), 261 EnumVariable('ubsan', 'Enable undefined behavior checks', 262 'off', allowed_values=['on', 'off']), 263 EnumVariable('coverage', 'Enable code coverage measurement', 264 'off', allowed_values=['on', 'off']), 265 EnumVariable('negative_testing', 266 'Enable negative testing (needs exceptions)', 267 'off', allowed_values=['on', 'off']), 268 DefaultVariable('symbols', 'Include debugging symbols in the binaries', 269 ['on', 'off']), 270 DefaultVariable('simulator', 'Simulators to include', ['aarch64', 'none']), 271 DefaultVariable('code_buffer_allocator', 272 'Configure the allocation mechanism in the CodeBuffer', 273 ['malloc', 'mmap']), 274 ('std', 275 'C++ standard. The standards tested are: %s.' % \ 276 ', '.join(config.tested_cpp_standards), 277 config.tested_cpp_standards[0]), 278 ('compiler_wrapper', 'Command to prefix to the C and C++ compiler (e.g ccache)', '') 279 ) 280 281# We use 'variant directories' to avoid recompiling multiple times when build 282# options are changed, different build paths are used depending on the options 283# set. These are the options that should be reflected in the build directory 284# path. 285options_influencing_build_path = [ 286 'target', 'mode', 'symbols', 'compiler', 'std', 'simulator', 'negative_testing', 287 'code_buffer_allocator' 288] 289 290 291 292# Build helpers ---------------------------------------------------------------- 293 294def RetrieveEnvironmentVariables(env): 295 for key in ['CC', 'CXX', 'AR', 'RANLIB', 'LD']: 296 if os.getenv(key): env[key] = os.getenv(key) 297 if os.getenv('LD_LIBRARY_PATH'): env['LIBPATH'] = os.getenv('LD_LIBRARY_PATH') 298 if os.getenv('CCFLAGS'): 299 env.Append(CCFLAGS = os.getenv('CCFLAGS').split()) 300 if os.getenv('CXXFLAGS'): 301 env.Append(CXXFLAGS = os.getenv('CXXFLAGS').split()) 302 if os.getenv('LINKFLAGS'): 303 env.Append(LINKFLAGS = os.getenv('LINKFLAGS').split()) 304 305# The architecture targeted by default will depend on the compiler being 306# used. 'host_arch' is extracted from the compiler while 'target' can be 307# set by the user. 308# By default, we target both AArch32 and AArch64 unless the compiler targets a 309# 32-bit architecture. At the moment, we cannot build VIXL's AArch64 support on 310# a 32-bit platform. 311# TODO: Port VIXL to build on a 32-bit platform. 312def target_handler(env): 313 # Auto detect 314 if Is32BitHost(env): 315 # We use list(set(...)) to keep the same order as if it was specify as 316 # an option. 317 env['target'] = SortListVariable(['a32', 't32']) 318 else: 319 env['target'] = SortListVariable(['a64', 'a32', 't32']) 320 321 322def target_validator(env): 323 # TODO: Port VIXL64 to work on a 32-bit platform. 324 if Is32BitHost(env) and CanTargetAArch64(env): 325 raise UserError('Building VIXL for AArch64 in 32-bit is not supported. Set ' 326 '`target` to `aarch32`') 327 328 329# The target option is handled differently from the rest. 330def ProcessTargetOption(env): 331 if env['target'] == []: target_handler(env) 332 333 if 'a32' in env['target']: env['CCFLAGS'] += ['-DVIXL_INCLUDE_TARGET_A32'] 334 if 't32' in env['target']: env['CCFLAGS'] += ['-DVIXL_INCLUDE_TARGET_T32'] 335 if 'a64' in env['target']: env['CCFLAGS'] += ['-DVIXL_INCLUDE_TARGET_A64'] 336 337 target_validator(env) 338 339 340def ProcessBuildOptions(env): 341 # 'all' is unconditionally processed. 342 if 'all' in options: 343 for var in options['all']: 344 if var in env and env[var]: 345 env[var] += options['all'][var] 346 else: 347 env[var] = options['all'][var] 348 349 # The target option *must* be processed before the options defined in 350 # vars_default_handlers. 351 ProcessTargetOption(env) 352 353 # Other build options must match 'option:value' 354 env_dict = env.Dictionary() 355 356 # First apply the default variables handlers in order. 357 for key, value in vars_default_handlers.items(): 358 default = value[0] 359 handler = value[1] 360 if env_dict.get(key) == default: 361 handler(env_dict) 362 363 # Second, run the series of validators, to check for errors. 364 for _, value in vars_default_handlers.items(): 365 validator = value[2] 366 validator(env) 367 368 for key in env_dict.keys(): 369 # Then update the environment according to the value of the variable. 370 key_val_couple = key + ':%s' % env_dict[key] 371 if key_val_couple in options: 372 for var in options[key_val_couple]: 373 env[var] += options[key_val_couple][var] 374 375 376def ConfigureEnvironmentForCompiler(env): 377 compiler = util.CompilerInformation(env) 378 if compiler == 'clang': 379 # These warnings only work for Clang. 380 # -Wimplicit-fallthrough only works when compiling the code base as C++11 or 381 # newer. The compiler does not complain if the option is passed when 382 # compiling earlier C++ standards. 383 env.Append(CPPFLAGS = ['-Wimplicit-fallthrough', '-Wshorten-64-to-32']) 384 385 # The '-Wunreachable-code' flag breaks builds for clang 3.4. 386 if compiler != 'clang-3.4': 387 env.Append(CPPFLAGS = ['-Wunreachable-code']) 388 389 if env['ubsan'] == 'on': 390 env.Append(LINKFLAGS = ['-fuse-ld=lld']) 391 392 # GCC 4.8 has a bug which produces a warning saying that an anonymous Operand 393 # object might be used uninitialized: 394 # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57045 395 # The bug does not seem to appear in GCC 4.7, or in debug builds with GCC 4.8. 396 if env['mode'] == 'release': 397 if compiler == 'gcc-4.8': 398 env.Append(CPPFLAGS = ['-Wno-maybe-uninitialized']) 399 400 # GCC 6 and higher is able to detect throwing from inside a destructor and 401 # reports a warning. However, if negative testing is enabled then assertions 402 # will throw exceptions. 403 if env['negative_testing'] == 'on' and env['mode'] == 'debug' \ 404 and compiler >= 'gcc-6': 405 env.Append(CPPFLAGS = ['-Wno-terminate']) 406 407 # Suggest missing override keywords on methods. 408 if compiler >= 'gcc-5': 409 env.Append(CPPFLAGS = ['-Wsuggest-override']) 410 elif compiler >= 'clang-3.6': 411 env.Append(CPPFLAGS = ['-Winconsistent-missing-override']) 412 413 414def ConfigureEnvironment(env): 415 RetrieveEnvironmentVariables(env) 416 env['compiler'] = env['CXX'] 417 if env['compiler_wrapper'] != '': 418 env['CXX'] = env['compiler_wrapper'] + ' ' + env['CXX'] 419 env['CC'] = env['compiler_wrapper'] + ' ' + env['CC'] 420 env['host_arch'] = util.GetHostArch(env) 421 ProcessBuildOptions(env) 422 if 'std' in env: 423 env.Append(CPPFLAGS = ['-std=' + env['std']]) 424 std_path = env['std'] 425 ConfigureEnvironmentForCompiler(env) 426 427 428def TargetBuildDir(env): 429 # Build-time option values are embedded in the build path to avoid requiring a 430 # full build when an option changes. 431 build_dir = config.dir_build 432 for option in options_influencing_build_path: 433 option_value = ''.join(env[option]) if option in env else '' 434 build_dir = join(build_dir, option + '_'+ option_value) 435 return build_dir 436 437 438def PrepareVariantDir(location, build_dir): 439 location_build_dir = join(build_dir, location) 440 VariantDir(location_build_dir, location) 441 return location_build_dir 442 443 444def VIXLLibraryTarget(env): 445 build_dir = TargetBuildDir(env) 446 # Create a link to the latest build directory. 447 # Use `-r` to avoid failure when `latest` exists and is a directory. 448 subprocess.check_call(["rm", "-rf", config.dir_build_latest]) 449 util.ensure_dir(build_dir) 450 subprocess.check_call(["ln", "-s", build_dir, config.dir_build_latest]) 451 # Source files are in `src` and in `src/aarch64/`. 452 variant_dir_vixl = PrepareVariantDir(join('src'), build_dir) 453 sources = [Glob(join(variant_dir_vixl, '*.cc'))] 454 if CanTargetAArch32(env): 455 variant_dir_aarch32 = PrepareVariantDir(join('src', 'aarch32'), build_dir) 456 sources.append(Glob(join(variant_dir_aarch32, '*.cc'))) 457 if CanTargetAArch64(env): 458 variant_dir_aarch64 = PrepareVariantDir(join('src', 'aarch64'), build_dir) 459 sources.append(Glob(join(variant_dir_aarch64, '*.cc'))) 460 return env.Library(join(build_dir, 'vixl'), sources) 461 462 463 464# Build ------------------------------------------------------------------------ 465 466# The VIXL library, built by default. 467env = Environment(variables = vars, 468 BUILDERS = { 469 'Markdown': Builder(action = 'markdown $SOURCE > $TARGET', 470 suffix = '.html') 471 }, ENV = os.environ) 472# Abort the build if any command line option is unknown or invalid. 473unknown_build_options = vars.UnknownVariables() 474if unknown_build_options: 475 print('Unknown build options: ' + str(unknown_build_options.keys())) 476 Exit(1) 477 478if env['negative_testing'] == 'on' and env['mode'] != 'debug': 479 print('negative_testing only works in debug mode') 480 Exit(1) 481 482ConfigureEnvironment(env) 483Help(vars.GenerateHelpText(env)) 484libvixl = VIXLLibraryTarget(env) 485Default(libvixl) 486env.Alias('libvixl', libvixl) 487top_level_targets.Add('', 'Build the VIXL library.') 488 489 490# Common test code. 491test_build_dir = PrepareVariantDir('test', TargetBuildDir(env)) 492test_objects = [env.Object(Glob(join(test_build_dir, '*.cc'), exclude=join(test_build_dir, 'test-donkey.cc')))] 493 494# AArch32 support 495if CanTargetAArch32(env): 496 # The examples. 497 aarch32_example_names = util.ListCCFilesWithoutExt(config.dir_aarch32_examples) 498 aarch32_examples_build_dir = PrepareVariantDir('examples/aarch32', TargetBuildDir(env)) 499 aarch32_example_targets = [] 500 for example in aarch32_example_names: 501 prog = env.Program(join(aarch32_examples_build_dir, example), 502 join(aarch32_examples_build_dir, example + '.cc'), 503 LIBS=[libvixl]) 504 aarch32_example_targets.append(prog) 505 env.Alias('aarch32_examples', aarch32_example_targets) 506 top_level_targets.Add('aarch32_examples', 'Build the examples for AArch32.') 507 508 # The benchmarks 509 aarch32_benchmark_names = util.ListCCFilesWithoutExt(config.dir_aarch32_benchmarks) 510 aarch32_benchmarks_build_dir = PrepareVariantDir('benchmarks/aarch32', TargetBuildDir(env)) 511 aarch32_benchmark_targets = [] 512 for bench in aarch32_benchmark_names: 513 prog = env.Program(join(aarch32_benchmarks_build_dir, bench), 514 join(aarch32_benchmarks_build_dir, bench + '.cc'), 515 LIBS=[libvixl]) 516 aarch32_benchmark_targets.append(prog) 517 env.Alias('aarch32_benchmarks', aarch32_benchmark_targets) 518 top_level_targets.Add('aarch32_benchmarks', 'Build the benchmarks for AArch32.') 519 520 # The tests. 521 test_aarch32_build_dir = PrepareVariantDir(join('test', 'aarch32'), TargetBuildDir(env)) 522 test_objects.append(env.Object( 523 Glob(join(test_aarch32_build_dir, '*.cc')), 524 CPPPATH = env['CPPPATH'] + [config.dir_tests], 525 CCFLAGS = [flag for flag in env['CCFLAGS'] if flag != '-O3'])) 526 527# AArch64 support 528if CanTargetAArch64(env): 529 # The benchmarks. 530 aarch64_benchmark_names = util.ListCCFilesWithoutExt(config.dir_aarch64_benchmarks) 531 aarch64_benchmarks_build_dir = PrepareVariantDir('benchmarks/aarch64', TargetBuildDir(env)) 532 aarch64_benchmark_targets = [] 533 bench_utils = env.Object(join(aarch64_benchmarks_build_dir, 'bench-utils.o'), 534 join(aarch64_benchmarks_build_dir, 'bench-utils.cc')) 535 for bench in aarch64_benchmark_names: 536 if bench != 'bench-utils': 537 prog = env.Program(join(aarch64_benchmarks_build_dir, bench), 538 [join(aarch64_benchmarks_build_dir, bench + '.cc'), bench_utils], 539 LIBS=[libvixl]) 540 aarch64_benchmark_targets.append(prog) 541 env.Alias('aarch64_benchmarks', aarch64_benchmark_targets) 542 top_level_targets.Add('aarch64_benchmarks', 'Build the benchmarks for AArch64.') 543 544 # The examples. 545 aarch64_example_names = util.ListCCFilesWithoutExt(config.dir_aarch64_examples) 546 aarch64_examples_build_dir = PrepareVariantDir('examples/aarch64', TargetBuildDir(env)) 547 aarch64_example_targets = [] 548 for example in aarch64_example_names: 549 prog = env.Program(join(aarch64_examples_build_dir, example), 550 join(aarch64_examples_build_dir, example + '.cc'), 551 LIBS=[libvixl]) 552 aarch64_example_targets.append(prog) 553 env.Alias('aarch64_examples', aarch64_example_targets) 554 top_level_targets.Add('aarch64_examples', 'Build the examples for AArch64.') 555 556 # The tests. 557 test_aarch64_build_dir = PrepareVariantDir(join('test', 'aarch64'), TargetBuildDir(env)) 558 test_objects.append(env.Object( 559 Glob(join(test_aarch64_build_dir, '*.cc')), 560 CPPPATH = env['CPPPATH'] + [config.dir_tests], 561 CCFLAGS = [flag for flag in env['CCFLAGS'] if flag != '-O3'])) 562 563 # The test requires building the example files with specific options, so we 564 # create a separate variant dir for the example objects built this way. 565 test_aarch64_examples_vdir = join(TargetBuildDir(env), 'test', 'aarch64', 'test_examples') 566 VariantDir(test_aarch64_examples_vdir, '.') 567 test_aarch64_examples_obj = env.Object( 568 [Glob(join(test_aarch64_examples_vdir, join('test', 'aarch64', 'examples', '*.cc'))), 569 Glob(join(test_aarch64_examples_vdir, join('examples/aarch64', '*.cc')))], 570 CCFLAGS = env['CCFLAGS'] + ['-DTEST_EXAMPLES'], 571 CPPPATH = env['CPPPATH'] + [config.dir_aarch64_examples] + [config.dir_tests]) 572 test_objects.append(test_aarch64_examples_obj) 573 574 # The simulator test generator. 575 donkey_objects = [] 576 donkey_objects.append(env.Object( 577 [join(test_build_dir, 'test-donkey.cc'), join(test_aarch64_build_dir, 'test-utils-aarch64.cc')], 578 CPPPATH = env['CPPPATH'] + [config.dir_tests], 579 CCFLAGS = [flag for flag in env['CCFLAGS'] if flag != '-O3'])) 580 donkey = env.Program(join(test_build_dir, 'test-donkey'), donkey_objects, LIBS=[libvixl]) 581 env.Alias('tests', donkey) 582 583test = env.Program(join(test_build_dir, 'test-runner'), test_objects, 584 LIBS=[libvixl]) 585env.Alias('tests', test) 586top_level_targets.Add('tests', 'Build the tests.') 587 588 589env.Alias('all', top_level_targets.targets) 590top_level_targets.Add('all', 'Build all the targets above.') 591 592Help('\n\nAvailable top level targets:\n' + top_level_targets.Help()) 593 594extra_targets = VIXLTargets() 595 596# Build documentation 597doc = [ 598 env.Markdown('README.md'), 599 env.Markdown('doc/changelog.md'), 600 env.Markdown('doc/aarch32/getting-started-aarch32.md'), 601 env.Markdown('doc/aarch32/design/code-generation-aarch32.md'), 602 env.Markdown('doc/aarch32/design/literal-pool-aarch32.md'), 603 env.Markdown('doc/aarch64/supported-instructions-aarch64.md'), 604 env.Markdown('doc/aarch64/getting-started-aarch64.md'), 605 env.Markdown('doc/aarch64/topics/ycm.md'), 606 env.Markdown('doc/aarch64/topics/extending-the-disassembler.md'), 607 env.Markdown('doc/aarch64/topics/index.md'), 608] 609env.Alias('doc', doc) 610extra_targets.Add('doc', 'Convert documentation to HTML (requires the ' 611 '`markdown` program).') 612 613Help('\nAvailable extra targets:\n' + extra_targets.Help()) 614