blob: 17669472f3a6701fdc52c6e33d82c826667f2057 [file] [log] [blame]
Alexandre Ramesb78f1392016-07-01 14:22:22 +01001# Copyright 2015, VIXL authors
armvixlad96eda2013-06-14 11:42:37 +01002# 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
armvixldb644342015-07-21 11:37:10 +010027import glob
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +000028import itertools
armvixlad96eda2013-06-14 11:42:37 +010029import os
armvixldb644342015-07-21 11:37:10 +010030from os.path import join
armvixlc68cb642014-09-25 18:49:30 +010031import platform
armvixl4a102ba2014-07-14 09:02:40 +010032import subprocess
armvixlad96eda2013-06-14 11:42:37 +010033import sys
Pierre Langloisa3b21462016-08-04 16:01:51 +010034from collections import OrderedDict
armvixlad96eda2013-06-14 11:42:37 +010035
armvixl4a102ba2014-07-14 09:02:40 +010036root_dir = os.path.dirname(File('SConstruct').rfile().abspath)
armvixldb644342015-07-21 11:37:10 +010037sys.path.insert(0, join(root_dir, 'tools'))
38import config
armvixl4a102ba2014-07-14 09:02:40 +010039import util
40
Pierre Langlois8253a3c2016-12-14 18:54:22 +000041from SCons.Errors import UserError
42
armvixlc68cb642014-09-25 18:49:30 +010043
44Help('''
45Build system for the VIXL project.
46See README.md for documentation and details about the build system.
armvixlc68cb642014-09-25 18:49:30 +010047''')
48
49
armvixldb644342015-07-21 11:37:10 +010050# We track top-level targets to automatically generate help and alias them.
Pierre Langlois287e6d12016-11-21 14:56:01 +000051class VIXLTargets:
armvixldb644342015-07-21 11:37:10 +010052 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):
armvixl684cd2a2015-10-23 13:38:33 +010059 res = ""
armvixldb644342015-07-21 11:37:10 +010060 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
armvixlad96eda2013-06-14 11:42:37 +010067
Pierre Langlois287e6d12016-11-21 14:56:01 +000068top_level_targets = VIXLTargets()
armvixlad96eda2013-06-14 11:42:37 +010069
70
armvixldb644342015-07-21 11:37:10 +010071
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',
Alexandre Ramesfd098172016-08-09 10:29:53 +010085 '-Wwrite-strings',
Jacob Bramleycff5a2e2019-03-15 09:34:56 +000086 '-Wunused',
Martyn Capewell6e8db232022-01-07 16:38:14 +000087 '-Wshadow',
Jacob Bramleycff5a2e2019-03-15 09:34:56 +000088 '-Wno-missing-noreturn'],
armvixldb644342015-07-21 11:37:10 +010089 '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' : {
Alexandre Ramesfa4a4bd2016-07-25 14:14:22 +010098 'CCFLAGS' : ['-O3'],
armvixldb644342015-07-21 11:37:10 +010099 },
Pierre Langloisa3b21462016-08-04 16:01:51 +0100100 'simulator:aarch64' : {
mmc28a3c407232024-06-19 15:03:55 +0100101 'CCFLAGS' : ['-DVIXL_INCLUDE_SIMULATOR_AARCH64',
102 '-pthread'],
103 'LINKFLAGS' : ['-pthread']
armvixldb644342015-07-21 11:37:10 +0100104 },
105 'symbols:on' : {
106 'CCFLAGS' : ['-g'],
107 'LINKFLAGS' : ['-g']
108 },
Georgia Kouveli38d5d1b2016-11-16 11:58:41 +0000109 'negative_testing:on' : {
110 'CCFLAGS' : ['-DVIXL_NEGATIVE_TESTING']
Jacob Bramley1fa6f062016-12-19 11:40:08 +0000111 },
112 'code_buffer_allocator:mmap' : {
113 'CCFLAGS' : ['-DVIXL_CODE_BUFFER_MMAP']
114 },
115 'code_buffer_allocator:malloc' : {
116 'CCFLAGS' : ['-DVIXL_CODE_BUFFER_MALLOC']
Vincent Belliard4e52d4d2018-04-03 13:34:44 -0700117 },
118 'ubsan:on' : {
119 'CCFLAGS': ['-fsanitize=undefined'],
120 'LINKFLAGS': ['-fsanitize=undefined']
Martyn Capewellae5957c2021-03-31 11:44:16 +0100121 },
122 'coverage:on' : {
123 'CCFLAGS': ['-fprofile-instr-generate', '-fcoverage-mapping'],
124 'LINKFLAGS': ['-fprofile-instr-generate', '-fcoverage-mapping']
Chris Jones30e7bbd2024-02-15 15:05:25 +0000125 },
126 'implicit_checks:on' : {
127 'CCFLAGS' : ['-DVIXL_ENABLE_IMPLICIT_CHECKS'],
Georgia Kouveli38d5d1b2016-11-16 11:58:41 +0000128 }
armvixldb644342015-07-21 11:37:10 +0100129 }
armvixlad96eda2013-06-14 11:42:37 +0100130
131
armvixldb644342015-07-21 11:37:10 +0100132# 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'
armvixl6e2c8272015-03-31 11:04:14 +0100139
140
armvixldb644342015-07-21 11:37:10 +0100141def symbols_handler(env):
142 env['symbols'] = 'on' if 'mode' in env and env['mode'] == 'debug' else 'off'
armvixlad96eda2013-06-14 11:42:37 +0100143
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000144def Is32BitHost(env):
145 return env['host_arch'] in ['aarch32', 'i386']
146
147def IsAArch64Host(env):
148 return env['host_arch'] == 'aarch64'
149
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000150def CanTargetA32(env):
151 return 'a32' in env['target']
152
153def CanTargetT32(env):
154 return 't32' in env['target']
155
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000156def CanTargetAArch32(env):
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000157 return CanTargetA32(env) or CanTargetT32(env)
158
159def CanTargetA64(env):
160 return 'a64' in env['target']
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000161
162def CanTargetAArch64(env):
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000163 return CanTargetA64(env)
Pierre Langloisa3b21462016-08-04 16:01:51 +0100164
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):
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000169 if not IsAArch64Host(env) and CanTargetAArch64(env):
Pierre Langloisa3b21462016-08-04 16:01:51 +0100170 env['simulator'] = 'aarch64'
171 else:
172 env['simulator'] = 'none'
173
174
Jacob Bramley1fa6f062016-12-19 11:40:08 +0000175# '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
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000184# A validator checks the consistency of provided options against the environment.
185def default_validator(env):
186 pass
187
188
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000189def simulator_validator(env):
190 if env['simulator'] == 'aarch64' and not CanTargetAArch64(env):
191 raise UserError('Building an AArch64 simulator implies that VIXL targets '
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000192 'AArch64. Set `target` to include `aarch64` or `a64`.')
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000193
194
Josh Sorefb43d6ef2022-08-03 12:47:14 -0400195# Default variables may depend on each other, therefore we need this dictionary
Pierre Langloisa3b21462016-08-04 16:01:51 +0100196# to be ordered.
197vars_default_handlers = OrderedDict({
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000198 # variable_name : [ 'default val', 'handler', 'validator']
199 'symbols' : [ 'mode==debug', symbols_handler, default_validator ],
200 'modifiable_flags' : [ 'mode==debug', modifiable_flags_handler, default_validator],
Jacob Bramley1fa6f062016-12-19 11:40:08 +0000201 'simulator' : [ 'on if the target architectures include AArch64 but '
Pierre Langloisa3b21462016-08-04 16:01:51 +0100202 'the host is not AArch64, else off',
Jacob Bramley1fa6f062016-12-19 11:40:08 +0000203 simulator_handler, simulator_validator ],
204 'code_buffer_allocator' : [ 'mmap with __linux__, malloc otherwise',
205 code_buffer_allocator_handler, default_validator ]
Pierre Langloisa3b21462016-08-04 16:01:51 +0100206 })
armvixldb644342015-07-21 11:37:10 +0100207
208
Pierre Langloisa3b21462016-08-04 16:01:51 +0100209def DefaultVariable(name, help, allowed_values):
210 help = '%s (%s)' % (help, '|'.join(allowed_values))
armvixldb644342015-07-21 11:37:10 +0100211 default_value = vars_default_handlers[name][0]
Pierre Langloisa3b21462016-08-04 16:01:51 +0100212 def validator(name, value, env):
213 if value != default_value and value not in allowed_values:
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000214 raise UserError('Invalid value for option {name}: {value}. '
215 'Valid values are: {allowed_values}'.format(
216 name, value, allowed_values))
Pierre Langloisa3b21462016-08-04 16:01:51 +0100217 return (name, help, default_value, validator)
armvixldb644342015-07-21 11:37:10 +0100218
219
Matthew Bentham6ebcc8a2020-06-04 12:02:38 +0100220def 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
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000233def 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]
Matthew Bentham6ebcc8a2020-06-04 12:02:38 +0100248 return SortListVariable(itertools.chain.from_iterable(translated))
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000249 # The validator is run later hence the get.
250 translated = [aliasing.get(v, v) for v in value.split(',')]
Matthew Bentham6ebcc8a2020-06-04 12:02:38 +0100251 return SortListVariable(itertools.chain.from_iterable(translated))
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000252
253 return (name, help, default_value, validator, converter)
254
255
armvixldb644342015-07-21 11:37:10 +0100256vars = Variables()
257# Define command line build options.
armvixldb644342015-07-21 11:37:10 +0100258vars.AddVariables(
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000259 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']}),
armvixldb644342015-07-21 11:37:10 +0100264 EnumVariable('mode', 'Build mode',
265 'release', allowed_values=config.build_options_modes),
Vincent Belliard4e52d4d2018-04-03 13:34:44 -0700266 EnumVariable('ubsan', 'Enable undefined behavior checks',
267 'off', allowed_values=['on', 'off']),
Martyn Capewellae5957c2021-03-31 11:44:16 +0100268 EnumVariable('coverage', 'Enable code coverage measurement',
269 'off', allowed_values=['on', 'off']),
Jacob Bramley1fa6f062016-12-19 11:40:08 +0000270 EnumVariable('negative_testing',
271 'Enable negative testing (needs exceptions)',
Georgia Kouveli38d5d1b2016-11-16 11:58:41 +0000272 'off', allowed_values=['on', 'off']),
Chris Jones30e7bbd2024-02-15 15:05:25 +0000273 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']),
armvixldb644342015-07-21 11:37:10 +0100277 DefaultVariable('symbols', 'Include debugging symbols in the binaries',
278 ['on', 'off']),
Pierre Langloisa3b21462016-08-04 16:01:51 +0100279 DefaultVariable('simulator', 'Simulators to include', ['aarch64', 'none']),
Jacob Bramley1fa6f062016-12-19 11:40:08 +0000280 DefaultVariable('code_buffer_allocator',
281 'Configure the allocation mechanism in the CodeBuffer',
282 ['malloc', 'mmap']),
Jacob Bramley191e7572020-01-31 14:19:57 +0000283 ('std',
284 'C++ standard. The standards tested are: %s.' % \
285 ', '.join(config.tested_cpp_standards),
286 config.tested_cpp_standards[0]),
Anthony Barbier9c4ba7a2019-02-15 15:20:25 +0000287 ('compiler_wrapper', 'Command to prefix to the C and C++ compiler (e.g ccache)', '')
armvixldb644342015-07-21 11:37:10 +0100288 )
armvixlad96eda2013-06-14 11:42:37 +0100289
armvixldb644342015-07-21 11:37:10 +0100290# 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.
Pierre Langloisa3b21462016-08-04 16:01:51 +0100294options_influencing_build_path = [
Anthony Barbier9c4ba7a2019-02-15 15:20:25 +0000295 'target', 'mode', 'symbols', 'compiler', 'std', 'simulator', 'negative_testing',
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000296 'code_buffer_allocator'
Pierre Langloisa3b21462016-08-04 16:01:51 +0100297]
armvixlad96eda2013-06-14 11:42:37 +0100298
armvixlad96eda2013-06-14 11:42:37 +0100299
armvixldb644342015-07-21 11:37:10 +0100300
301# Build helpers ----------------------------------------------------------------
302
303def RetrieveEnvironmentVariables(env):
Pierre Langlois88c46b82016-06-02 18:15:32 +0100304 for key in ['CC', 'CXX', 'AR', 'RANLIB', 'LD']:
armvixldb644342015-07-21 11:37:10 +0100305 if os.getenv(key): env[key] = os.getenv(key)
306 if os.getenv('LD_LIBRARY_PATH'): env['LIBPATH'] = os.getenv('LD_LIBRARY_PATH')
Pierre Langlois88c46b82016-06-02 18:15:32 +0100307 if os.getenv('CCFLAGS'):
308 env.Append(CCFLAGS = os.getenv('CCFLAGS').split())
armvixldb644342015-07-21 11:37:10 +0100309 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())
armvixl4a102ba2014-07-14 09:02:40 +0100313
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000314# 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.
Matthew Bentham6ebcc8a2020-06-04 12:02:38 +0100326 env['target'] = SortListVariable(['a32', 't32'])
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000327 else:
Matthew Bentham6ebcc8a2020-06-04 12:02:38 +0100328 env['target'] = SortListVariable(['a64', 'a32', 't32'])
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000329
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
armvixldb644342015-07-21 11:37:10 +0100349def 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]
Pierre Langloisa3b21462016-08-04 16:01:51 +0100357
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000358 # The target option *must* be processed before the options defined in
359 # vars_default_handlers.
360 ProcessTargetOption(env)
361
armvixldb644342015-07-21 11:37:10 +0100362 # Other build options must match 'option:value'
363 env_dict = env.Dictionary()
Pierre Langloisa3b21462016-08-04 16:01:51 +0100364
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
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000372 # 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
armvixldb644342015-07-21 11:37:10 +0100377 for key in env_dict.keys():
armvixldb644342015-07-21 11:37:10 +0100378 # 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):
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000386 compiler = util.CompilerInformation(env)
Pierre Langloisf737e0a2016-11-02 13:08:11 +0000387 if compiler == 'clang':
armvixldb644342015-07-21 11:37:10 +0100388 # 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.
Jacob Bramley176a3792016-11-09 14:44:39 +0000395 if compiler != 'clang-3.4':
armvixldb644342015-07-21 11:37:10 +0100396 env.Append(CPPFLAGS = ['-Wunreachable-code'])
397
Vincent Belliard4e52d4d2018-04-03 13:34:44 -0700398 if env['ubsan'] == 'on':
399 env.Append(LINKFLAGS = ['-fuse-ld=lld'])
400
armvixldb644342015-07-21 11:37:10 +0100401 # 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':
Pierre Langloisf737e0a2016-11-02 13:08:11 +0000406 if compiler == 'gcc-4.8':
armvixldb644342015-07-21 11:37:10 +0100407 env.Append(CPPFLAGS = ['-Wno-maybe-uninitialized'])
Pierre Langloisf737e0a2016-11-02 13:08:11 +0000408
Pierre Langloisf7bf6552017-05-05 13:14:35 +0100409 # 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'])
Pierre Langloisf7bf6552017-05-05 13:14:35 +0100415
Jacob Bramley191e7572020-01-31 14:19:57 +0000416 # 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'])
armvixldb644342015-07-21 11:37:10 +0100421
422
423def ConfigureEnvironment(env):
424 RetrieveEnvironmentVariables(env)
Anthony Barbier9c4ba7a2019-02-15 15:20:25 +0000425 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']
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000429 env['host_arch'] = util.GetHostArch(env)
armvixldb644342015-07-21 11:37:10 +0100430 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:
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000442 option_value = ''.join(env[option]) if option in env else ''
armvixldb644342015-07-21 11:37:10 +0100443 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.
Alexandre Rames4e241932016-06-08 21:32:03 +0100456 # Use `-r` to avoid failure when `latest` exists and is a directory.
457 subprocess.check_call(["rm", "-rf", config.dir_build_latest])
armvixldb644342015-07-21 11:37:10 +0100458 util.ensure_dir(build_dir)
Jacob Bramley45e39202025-01-07 12:30:34 +0000459 subprocess.check_call(["ln", "-r", "-s", build_dir, config.dir_build_latest])
Alexandre Ramesd3832962016-07-04 15:03:43 +0100460 # Source files are in `src` and in `src/aarch64/`.
Alexandre Rames39c32a62016-05-23 15:47:22 +0100461 variant_dir_vixl = PrepareVariantDir(join('src'), build_dir)
Pierre Langloisa3b21462016-08-04 16:01:51 +0100462 sources = [Glob(join(variant_dir_vixl, '*.cc'))]
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000463 if CanTargetAArch32(env):
Pierre Langloisa3b21462016-08-04 16:01:51 +0100464 variant_dir_aarch32 = PrepareVariantDir(join('src', 'aarch32'), build_dir)
465 sources.append(Glob(join(variant_dir_aarch32, '*.cc')))
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000466 if CanTargetAArch64(env):
Pierre Langloisa3b21462016-08-04 16:01:51 +0100467 variant_dir_aarch64 = PrepareVariantDir(join('src', 'aarch64'), build_dir)
468 sources.append(Glob(join(variant_dir_aarch64, '*.cc')))
armvixldb644342015-07-21 11:37:10 +0100469 return env.Library(join(build_dir, 'vixl'), sources)
470
471
472
473# Build ------------------------------------------------------------------------
474
475# The VIXL library, built by default.
Pierre Langlois287e6d12016-11-21 14:56:01 +0000476env = Environment(variables = vars,
477 BUILDERS = {
478 'Markdown': Builder(action = 'markdown $SOURCE > $TARGET',
479 suffix = '.html')
Anthony Barbierf2986e12019-02-28 16:49:23 +0000480 }, ENV = os.environ)
Alexandre Ramesf5de33d2016-10-25 09:51:11 +0100481# Abort the build if any command line option is unknown or invalid.
482unknown_build_options = vars.UnknownVariables()
483if unknown_build_options:
Matthew Benthamfe7cb102020-05-30 13:28:36 +0100484 print('Unknown build options: ' + str(unknown_build_options.keys()))
Alexandre Ramesf5de33d2016-10-25 09:51:11 +0100485 Exit(1)
486
Anthony Barbierf2986e12019-02-28 16:49:23 +0000487if env['negative_testing'] == 'on' and env['mode'] != 'debug':
Matthew Benthamfe7cb102020-05-30 13:28:36 +0100488 print('negative_testing only works in debug mode')
Anthony Barbierf2986e12019-02-28 16:49:23 +0000489 Exit(1)
490
armvixldb644342015-07-21 11:37:10 +0100491ConfigureEnvironment(env)
armvixldb644342015-07-21 11:37:10 +0100492Help(vars.GenerateHelpText(env))
493libvixl = VIXLLibraryTarget(env)
494Default(libvixl)
495env.Alias('libvixl', libvixl)
496top_level_targets.Add('', 'Build the VIXL library.')
497
armvixl4a102ba2014-07-14 09:02:40 +0100498
Pierre Langloisa3b21462016-08-04 16:01:51 +0100499# Common test code.
armvixldb644342015-07-21 11:37:10 +0100500test_build_dir = PrepareVariantDir('test', TargetBuildDir(env))
Martyn Capewelldba51cc2020-08-27 13:48:26 +0100501test_objects = [env.Object(Glob(join(test_build_dir, '*.cc'), exclude=join(test_build_dir, 'test-donkey.cc')))]
Pierre Langlois88c46b82016-06-02 18:15:32 +0100502
Pierre Langloisa3b21462016-08-04 16:01:51 +0100503# AArch32 support
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000504if CanTargetAArch32(env):
Pierre Langloisa3b21462016-08-04 16:01:51 +0100505 # 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.')
Pierre Langlois88c46b82016-06-02 18:15:32 +0100516
Vincent Belliard32cf2542016-07-14 10:04:09 -0700517 # 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
Pierre Langloisa3b21462016-08-04 16:01:51 +0100529 # 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')),
Anthony Barbier7b4df2b2019-03-12 17:36:15 +0000533 CPPPATH = env['CPPPATH'] + [config.dir_tests],
534 CCFLAGS = [flag for flag in env['CCFLAGS'] if flag != '-O3']))
Pierre Langlois88c46b82016-06-02 18:15:32 +0100535
Pierre Langloisa3b21462016-08-04 16:01:51 +0100536# AArch64 support
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000537if CanTargetAArch64(env):
Pierre Langloisa3b21462016-08-04 16:01:51 +0100538 # 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 = []
Jacob Bramley1d925c02019-06-17 16:51:23 +0100542 bench_utils = env.Object(join(aarch64_benchmarks_build_dir, 'bench-utils.o'),
543 join(aarch64_benchmarks_build_dir, 'bench-utils.cc'))
Pierre Langloisa3b21462016-08-04 16:01:51 +0100544 for bench in aarch64_benchmark_names:
Jacob Bramley1d925c02019-06-17 16:51:23 +0100545 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)
Pierre Langloisa3b21462016-08-04 16:01:51 +0100550 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')),
Anthony Barbier7b4df2b2019-03-12 17:36:15 +0000569 CPPPATH = env['CPPPATH'] + [config.dir_tests],
570 CCFLAGS = [flag for flag in env['CCFLAGS'] if flag != '-O3']))
Pierre Langloisa3b21462016-08-04 16:01:51 +0100571
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(
Jacob Bramley0f71a762018-08-30 12:09:34 +0100577 [Glob(join(test_aarch64_examples_vdir, join('test', 'aarch64', 'examples', '*.cc'))),
Pierre Langloisa3b21462016-08-04 16:01:51 +0100578 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)
Pierre Langlois88c46b82016-06-02 18:15:32 +0100582
Martyn Capewelldba51cc2020-08-27 13:48:26 +0100583 # 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
Pierre Langlois88c46b82016-06-02 18:15:32 +0100592test = env.Program(join(test_build_dir, 'test-runner'), test_objects,
armvixldb644342015-07-21 11:37:10 +0100593 LIBS=[libvixl])
594env.Alias('tests', test)
595top_level_targets.Add('tests', 'Build the tests.')
armvixl4a102ba2014-07-14 09:02:40 +0100596
armvixl4a102ba2014-07-14 09:02:40 +0100597
armvixldb644342015-07-21 11:37:10 +0100598env.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())
Pierre Langlois287e6d12016-11-21 14:56:01 +0000602
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())