blob: e23272f4f087ef7126b98fc84aa8e1070b942385 [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
Mateusz Kalinowskicc24b302020-10-02 10:09:53 +010032import re
armvixl4a102ba2014-07-14 09:02:40 +010033import subprocess
armvixlad96eda2013-06-14 11:42:37 +010034import sys
Mateusz Kalinowskicc24b302020-10-02 10:09:53 +010035import warnings
Pierre Langloisa3b21462016-08-04 16:01:51 +010036from collections import OrderedDict
armvixlad96eda2013-06-14 11:42:37 +010037
armvixl4a102ba2014-07-14 09:02:40 +010038root_dir = os.path.dirname(File('SConstruct').rfile().abspath)
armvixldb644342015-07-21 11:37:10 +010039sys.path.insert(0, join(root_dir, 'tools'))
40import config
armvixl4a102ba2014-07-14 09:02:40 +010041import util
42
Pierre Langlois8253a3c2016-12-14 18:54:22 +000043from SCons.Errors import UserError
44
armvixlc68cb642014-09-25 18:49:30 +010045
46Help('''
47Build system for the VIXL project.
48See README.md for documentation and details about the build system.
armvixlc68cb642014-09-25 18:49:30 +010049''')
50
51
armvixldb644342015-07-21 11:37:10 +010052# We track top-level targets to automatically generate help and alias them.
Pierre Langlois287e6d12016-11-21 14:56:01 +000053class VIXLTargets:
armvixldb644342015-07-21 11:37:10 +010054 def __init__(self):
55 self.targets = []
56 self.help_messages = []
Mateusz Kalinowskicc24b302020-10-02 10:09:53 +010057 def Add(self, target, help_message, cpp_version=14):
58 self.targets.append((target, cpp_version))
armvixldb644342015-07-21 11:37:10 +010059 self.help_messages.append(help_message)
60 def Help(self):
armvixl684cd2a2015-10-23 13:38:33 +010061 res = ""
armvixldb644342015-07-21 11:37:10 +010062 for i in range(len(self.targets)):
63 res += '\t{0:<{1}}{2:<{3}}\n'.format(
Mateusz Kalinowskicc24b302020-10-02 10:09:53 +010064 'scons ' + self.targets[i][0],
65 len('scons ') + max({len(t[0]) for t in self.targets}),
armvixldb644342015-07-21 11:37:10 +010066 ' : ' + self.help_messages[i],
67 len(' : ') + max(map(len, self.help_messages)))
68 return res
armvixlad96eda2013-06-14 11:42:37 +010069
Pierre Langlois287e6d12016-11-21 14:56:01 +000070top_level_targets = VIXLTargets()
armvixlad96eda2013-06-14 11:42:37 +010071
72
armvixldb644342015-07-21 11:37:10 +010073
74# Build options ----------------------------------------------------------------
75
76# Store all the options in a dictionary.
77# The SConstruct will check the build variables and construct the build
78# environment as appropriate.
79options = {
80 'all' : { # Unconditionally processed.
81 'CCFLAGS' : ['-Wall',
82 '-Werror',
83 '-fdiagnostics-show-option',
84 '-Wextra',
85 '-Wredundant-decls',
86 '-pedantic',
Alexandre Ramesfd098172016-08-09 10:29:53 +010087 '-Wwrite-strings',
Jacob Bramleycff5a2e2019-03-15 09:34:56 +000088 '-Wunused',
89 '-Wno-missing-noreturn'],
armvixldb644342015-07-21 11:37:10 +010090 'CPPPATH' : [config.dir_src_vixl]
91 },
92# 'build_option:value' : {
93# 'environment_key' : 'values to append'
94# },
95 'mode:debug' : {
96 'CCFLAGS' : ['-DVIXL_DEBUG', '-O0']
97 },
98 'mode:release' : {
Alexandre Ramesfa4a4bd2016-07-25 14:14:22 +010099 'CCFLAGS' : ['-O3'],
armvixldb644342015-07-21 11:37:10 +0100100 },
Pierre Langloisa3b21462016-08-04 16:01:51 +0100101 'simulator:aarch64' : {
Pierre Langlois1e85b7f2016-08-05 14:20:36 +0100102 'CCFLAGS' : ['-DVIXL_INCLUDE_SIMULATOR_AARCH64'],
armvixldb644342015-07-21 11:37:10 +0100103 },
104 'symbols:on' : {
105 'CCFLAGS' : ['-g'],
106 'LINKFLAGS' : ['-g']
107 },
Georgia Kouveli38d5d1b2016-11-16 11:58:41 +0000108 'negative_testing:on' : {
109 'CCFLAGS' : ['-DVIXL_NEGATIVE_TESTING']
Jacob Bramley1fa6f062016-12-19 11:40:08 +0000110 },
111 'code_buffer_allocator:mmap' : {
112 'CCFLAGS' : ['-DVIXL_CODE_BUFFER_MMAP']
113 },
114 'code_buffer_allocator:malloc' : {
115 'CCFLAGS' : ['-DVIXL_CODE_BUFFER_MALLOC']
Vincent Belliard4e52d4d2018-04-03 13:34:44 -0700116 },
117 'ubsan:on' : {
118 'CCFLAGS': ['-fsanitize=undefined'],
119 'LINKFLAGS': ['-fsanitize=undefined']
Georgia Kouveli38d5d1b2016-11-16 11:58:41 +0000120 }
armvixldb644342015-07-21 11:37:10 +0100121 }
armvixlad96eda2013-06-14 11:42:37 +0100122
123
armvixldb644342015-07-21 11:37:10 +0100124# A `DefaultVariable` has a default value that depends on elements not known
125# when variables are first evaluated.
126# Each `DefaultVariable` has a handler that will compute the default value for
127# the given environment.
128def modifiable_flags_handler(env):
129 env['modifiable_flags'] = \
130 'on' if 'mode' in env and env['mode'] == 'debug' else 'off'
armvixl6e2c8272015-03-31 11:04:14 +0100131
132
armvixldb644342015-07-21 11:37:10 +0100133def symbols_handler(env):
134 env['symbols'] = 'on' if 'mode' in env and env['mode'] == 'debug' else 'off'
armvixlad96eda2013-06-14 11:42:37 +0100135
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000136def Is32BitHost(env):
137 return env['host_arch'] in ['aarch32', 'i386']
138
139def IsAArch64Host(env):
140 return env['host_arch'] == 'aarch64'
141
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000142def CanTargetA32(env):
143 return 'a32' in env['target']
144
145def CanTargetT32(env):
146 return 't32' in env['target']
147
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000148def CanTargetAArch32(env):
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000149 return CanTargetA32(env) or CanTargetT32(env)
150
151def CanTargetA64(env):
152 return 'a64' in env['target']
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000153
154def CanTargetAArch64(env):
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000155 return CanTargetA64(env)
Pierre Langloisa3b21462016-08-04 16:01:51 +0100156
157
158# By default, include the simulator only if AArch64 is targeted and we are not
159# building VIXL natively for AArch64.
160def simulator_handler(env):
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000161 if not IsAArch64Host(env) and CanTargetAArch64(env):
Pierre Langloisa3b21462016-08-04 16:01:51 +0100162 env['simulator'] = 'aarch64'
163 else:
164 env['simulator'] = 'none'
165
166
Jacob Bramley1fa6f062016-12-19 11:40:08 +0000167# 'mmap' is required for use with 'mprotect', which is needed for the tests
168# (when running natively), so we use it by default where we can.
169def code_buffer_allocator_handler(env):
170 directives = util.GetCompilerDirectives(env)
171 if '__linux__' in directives:
172 env['code_buffer_allocator'] = 'mmap'
173 else:
174 env['code_buffer_allocator'] = 'malloc'
175
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000176# A validator checks the consistency of provided options against the environment.
177def default_validator(env):
178 pass
179
180
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000181def simulator_validator(env):
182 if env['simulator'] == 'aarch64' and not CanTargetAArch64(env):
183 raise UserError('Building an AArch64 simulator implies that VIXL targets '
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000184 'AArch64. Set `target` to include `aarch64` or `a64`.')
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000185
186
Pierre Langloisa3b21462016-08-04 16:01:51 +0100187# Default variables may depend on each other, therefore we need this dictionnary
188# to be ordered.
189vars_default_handlers = OrderedDict({
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000190 # variable_name : [ 'default val', 'handler', 'validator']
191 'symbols' : [ 'mode==debug', symbols_handler, default_validator ],
192 'modifiable_flags' : [ 'mode==debug', modifiable_flags_handler, default_validator],
Jacob Bramley1fa6f062016-12-19 11:40:08 +0000193 'simulator' : [ 'on if the target architectures include AArch64 but '
Pierre Langloisa3b21462016-08-04 16:01:51 +0100194 'the host is not AArch64, else off',
Jacob Bramley1fa6f062016-12-19 11:40:08 +0000195 simulator_handler, simulator_validator ],
196 'code_buffer_allocator' : [ 'mmap with __linux__, malloc otherwise',
197 code_buffer_allocator_handler, default_validator ]
Pierre Langloisa3b21462016-08-04 16:01:51 +0100198 })
armvixldb644342015-07-21 11:37:10 +0100199
200
Pierre Langloisa3b21462016-08-04 16:01:51 +0100201def DefaultVariable(name, help, allowed_values):
202 help = '%s (%s)' % (help, '|'.join(allowed_values))
armvixldb644342015-07-21 11:37:10 +0100203 default_value = vars_default_handlers[name][0]
Pierre Langloisa3b21462016-08-04 16:01:51 +0100204 def validator(name, value, env):
205 if value != default_value and value not in allowed_values:
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000206 raise UserError('Invalid value for option {name}: {value}. '
207 'Valid values are: {allowed_values}'.format(
208 name, value, allowed_values))
Pierre Langloisa3b21462016-08-04 16:01:51 +0100209 return (name, help, default_value, validator)
armvixldb644342015-07-21 11:37:10 +0100210
211
Matthew Bentham6ebcc8a2020-06-04 12:02:38 +0100212def SortListVariable(iterator):
213 # Previously this code relied on the order of items in a list
214 # converted from a set. However in Python 3 the order changes each run.
215 # Here we do a custom partial sort to ensure that the build directory
216 # name is stable, the same across Python 2 and 3, and the same as the
217 # old code.
218 result = list(sorted(iterator))
219 result = sorted(result, key=lambda x: x == 't32', reverse=True)
220 result = sorted(result, key=lambda x: x == 'a32', reverse=True)
221 result = sorted(result, key=lambda x: x == 'a64', reverse=True)
222 return result
223
224
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000225def AliasedListVariable(name, help, default_value, allowed_values, aliasing):
226 help = '%s (all|auto|comma-separated list) (any combination from [%s])' % \
227 (help, ', '.join(allowed_values))
228
229 def validator(name, value, env):
230 # Here list has been converted to space separated strings.
231 if value == '': return # auto
232 for v in value.split():
233 if v not in allowed_values:
234 raise UserError('Invalid value for %s: %s' % (name, value))
235
236 def converter(value):
237 if value == 'auto': return []
238 if value == 'all':
239 translated = [aliasing[v] for v in allowed_values]
Matthew Bentham6ebcc8a2020-06-04 12:02:38 +0100240 return SortListVariable(itertools.chain.from_iterable(translated))
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000241 # The validator is run later hence the get.
242 translated = [aliasing.get(v, v) for v in value.split(',')]
Matthew Bentham6ebcc8a2020-06-04 12:02:38 +0100243 return SortListVariable(itertools.chain.from_iterable(translated))
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000244
245 return (name, help, default_value, validator, converter)
246
247
armvixldb644342015-07-21 11:37:10 +0100248vars = Variables()
249# Define command line build options.
armvixldb644342015-07-21 11:37:10 +0100250vars.AddVariables(
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000251 AliasedListVariable('target', 'Target ISA/Architecture', 'auto',
252 ['aarch32', 'a32', 't32', 'aarch64', 'a64'],
253 {'aarch32' : ['a32', 't32'],
254 'a32' : ['a32'], 't32' : ['t32'],
255 'aarch64' : ['a64'], 'a64' : ['a64']}),
armvixldb644342015-07-21 11:37:10 +0100256 EnumVariable('mode', 'Build mode',
257 'release', allowed_values=config.build_options_modes),
Vincent Belliard4e52d4d2018-04-03 13:34:44 -0700258 EnumVariable('ubsan', 'Enable undefined behavior checks',
259 'off', allowed_values=['on', 'off']),
Jacob Bramley1fa6f062016-12-19 11:40:08 +0000260 EnumVariable('negative_testing',
261 'Enable negative testing (needs exceptions)',
Georgia Kouveli38d5d1b2016-11-16 11:58:41 +0000262 'off', allowed_values=['on', 'off']),
armvixldb644342015-07-21 11:37:10 +0100263 DefaultVariable('symbols', 'Include debugging symbols in the binaries',
264 ['on', 'off']),
Pierre Langloisa3b21462016-08-04 16:01:51 +0100265 DefaultVariable('simulator', 'Simulators to include', ['aarch64', 'none']),
Jacob Bramley1fa6f062016-12-19 11:40:08 +0000266 DefaultVariable('code_buffer_allocator',
267 'Configure the allocation mechanism in the CodeBuffer',
268 ['malloc', 'mmap']),
Jacob Bramley191e7572020-01-31 14:19:57 +0000269 ('std',
270 'C++ standard. The standards tested are: %s.' % \
271 ', '.join(config.tested_cpp_standards),
272 config.tested_cpp_standards[0]),
Anthony Barbier9c4ba7a2019-02-15 15:20:25 +0000273 ('compiler_wrapper', 'Command to prefix to the C and C++ compiler (e.g ccache)', '')
armvixldb644342015-07-21 11:37:10 +0100274 )
armvixlad96eda2013-06-14 11:42:37 +0100275
armvixldb644342015-07-21 11:37:10 +0100276# We use 'variant directories' to avoid recompiling multiple times when build
277# options are changed, different build paths are used depending on the options
278# set. These are the options that should be reflected in the build directory
279# path.
Pierre Langloisa3b21462016-08-04 16:01:51 +0100280options_influencing_build_path = [
Anthony Barbier9c4ba7a2019-02-15 15:20:25 +0000281 'target', 'mode', 'symbols', 'compiler', 'std', 'simulator', 'negative_testing',
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000282 'code_buffer_allocator'
Pierre Langloisa3b21462016-08-04 16:01:51 +0100283]
armvixlad96eda2013-06-14 11:42:37 +0100284
armvixlad96eda2013-06-14 11:42:37 +0100285
armvixldb644342015-07-21 11:37:10 +0100286
287# Build helpers ----------------------------------------------------------------
288
289def RetrieveEnvironmentVariables(env):
Pierre Langlois88c46b82016-06-02 18:15:32 +0100290 for key in ['CC', 'CXX', 'AR', 'RANLIB', 'LD']:
armvixldb644342015-07-21 11:37:10 +0100291 if os.getenv(key): env[key] = os.getenv(key)
292 if os.getenv('LD_LIBRARY_PATH'): env['LIBPATH'] = os.getenv('LD_LIBRARY_PATH')
Pierre Langlois88c46b82016-06-02 18:15:32 +0100293 if os.getenv('CCFLAGS'):
294 env.Append(CCFLAGS = os.getenv('CCFLAGS').split())
armvixldb644342015-07-21 11:37:10 +0100295 if os.getenv('CXXFLAGS'):
296 env.Append(CXXFLAGS = os.getenv('CXXFLAGS').split())
297 if os.getenv('LINKFLAGS'):
298 env.Append(LINKFLAGS = os.getenv('LINKFLAGS').split())
armvixl4a102ba2014-07-14 09:02:40 +0100299
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000300# The architecture targeted by default will depend on the compiler being
301# used. 'host_arch' is extracted from the compiler while 'target' can be
302# set by the user.
303# By default, we target both AArch32 and AArch64 unless the compiler targets a
304# 32-bit architecture. At the moment, we cannot build VIXL's AArch64 support on
305# a 32-bit platform.
306# TODO: Port VIXL to build on a 32-bit platform.
307def target_handler(env):
308 # Auto detect
309 if Is32BitHost(env):
310 # We use list(set(...)) to keep the same order as if it was specify as
311 # an option.
Matthew Bentham6ebcc8a2020-06-04 12:02:38 +0100312 env['target'] = SortListVariable(['a32', 't32'])
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000313 else:
Matthew Bentham6ebcc8a2020-06-04 12:02:38 +0100314 env['target'] = SortListVariable(['a64', 'a32', 't32'])
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000315
316
317def target_validator(env):
318 # TODO: Port VIXL64 to work on a 32-bit platform.
319 if Is32BitHost(env) and CanTargetAArch64(env):
320 raise UserError('Building VIXL for AArch64 in 32-bit is not supported. Set '
321 '`target` to `aarch32`')
322
323
324# The target option is handled differently from the rest.
325def ProcessTargetOption(env):
326 if env['target'] == []: target_handler(env)
327
328 if 'a32' in env['target']: env['CCFLAGS'] += ['-DVIXL_INCLUDE_TARGET_A32']
329 if 't32' in env['target']: env['CCFLAGS'] += ['-DVIXL_INCLUDE_TARGET_T32']
330 if 'a64' in env['target']: env['CCFLAGS'] += ['-DVIXL_INCLUDE_TARGET_A64']
331
332 target_validator(env)
333
334
armvixldb644342015-07-21 11:37:10 +0100335def ProcessBuildOptions(env):
336 # 'all' is unconditionally processed.
337 if 'all' in options:
338 for var in options['all']:
339 if var in env and env[var]:
340 env[var] += options['all'][var]
341 else:
342 env[var] = options['all'][var]
Pierre Langloisa3b21462016-08-04 16:01:51 +0100343
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000344 # The target option *must* be processed before the options defined in
345 # vars_default_handlers.
346 ProcessTargetOption(env)
347
armvixldb644342015-07-21 11:37:10 +0100348 # Other build options must match 'option:value'
349 env_dict = env.Dictionary()
Pierre Langloisa3b21462016-08-04 16:01:51 +0100350
351 # First apply the default variables handlers in order.
352 for key, value in vars_default_handlers.items():
353 default = value[0]
354 handler = value[1]
355 if env_dict.get(key) == default:
356 handler(env_dict)
357
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000358 # Second, run the series of validators, to check for errors.
359 for _, value in vars_default_handlers.items():
360 validator = value[2]
361 validator(env)
362
armvixldb644342015-07-21 11:37:10 +0100363 for key in env_dict.keys():
armvixldb644342015-07-21 11:37:10 +0100364 # Then update the environment according to the value of the variable.
365 key_val_couple = key + ':%s' % env_dict[key]
366 if key_val_couple in options:
367 for var in options[key_val_couple]:
368 env[var] += options[key_val_couple][var]
369
370
371def ConfigureEnvironmentForCompiler(env):
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000372 compiler = util.CompilerInformation(env)
Pierre Langloisf737e0a2016-11-02 13:08:11 +0000373 if compiler == 'clang':
armvixldb644342015-07-21 11:37:10 +0100374 # These warnings only work for Clang.
375 # -Wimplicit-fallthrough only works when compiling the code base as C++11 or
376 # newer. The compiler does not complain if the option is passed when
377 # compiling earlier C++ standards.
378 env.Append(CPPFLAGS = ['-Wimplicit-fallthrough', '-Wshorten-64-to-32'])
379
380 # The '-Wunreachable-code' flag breaks builds for clang 3.4.
Jacob Bramley176a3792016-11-09 14:44:39 +0000381 if compiler != 'clang-3.4':
armvixldb644342015-07-21 11:37:10 +0100382 env.Append(CPPFLAGS = ['-Wunreachable-code'])
383
Vincent Belliard4e52d4d2018-04-03 13:34:44 -0700384 if env['ubsan'] == 'on':
385 env.Append(LINKFLAGS = ['-fuse-ld=lld'])
386
armvixldb644342015-07-21 11:37:10 +0100387 # GCC 4.8 has a bug which produces a warning saying that an anonymous Operand
388 # object might be used uninitialized:
389 # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57045
390 # The bug does not seem to appear in GCC 4.7, or in debug builds with GCC 4.8.
391 if env['mode'] == 'release':
Pierre Langloisf737e0a2016-11-02 13:08:11 +0000392 if compiler == 'gcc-4.8':
armvixldb644342015-07-21 11:37:10 +0100393 env.Append(CPPFLAGS = ['-Wno-maybe-uninitialized'])
Pierre Langloisf737e0a2016-11-02 13:08:11 +0000394
Pierre Langloisf7bf6552017-05-05 13:14:35 +0100395 # GCC 6 and higher is able to detect throwing from inside a destructor and
396 # reports a warning. However, if negative testing is enabled then assertions
397 # will throw exceptions.
398 if env['negative_testing'] == 'on' and env['mode'] == 'debug' \
399 and compiler >= 'gcc-6':
400 env.Append(CPPFLAGS = ['-Wno-terminate'])
Pierre Langloisf7bf6552017-05-05 13:14:35 +0100401
Jacob Bramley191e7572020-01-31 14:19:57 +0000402 # Suggest missing override keywords on methods.
403 if compiler >= 'gcc-5':
404 env.Append(CPPFLAGS = ['-Wsuggest-override'])
405 elif compiler >= 'clang-3.6':
406 env.Append(CPPFLAGS = ['-Winconsistent-missing-override'])
armvixldb644342015-07-21 11:37:10 +0100407
408
409def ConfigureEnvironment(env):
410 RetrieveEnvironmentVariables(env)
Anthony Barbier9c4ba7a2019-02-15 15:20:25 +0000411 env['compiler'] = env['CXX']
412 if env['compiler_wrapper'] != '':
413 env['CXX'] = env['compiler_wrapper'] + ' ' + env['CXX']
414 env['CC'] = env['compiler_wrapper'] + ' ' + env['CC']
Pierre Langlois8253a3c2016-12-14 18:54:22 +0000415 env['host_arch'] = util.GetHostArch(env)
armvixldb644342015-07-21 11:37:10 +0100416 ProcessBuildOptions(env)
417 if 'std' in env:
418 env.Append(CPPFLAGS = ['-std=' + env['std']])
419 std_path = env['std']
420 ConfigureEnvironmentForCompiler(env)
421
422
423def TargetBuildDir(env):
424 # Build-time option values are embedded in the build path to avoid requiring a
425 # full build when an option changes.
426 build_dir = config.dir_build
427 for option in options_influencing_build_path:
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000428 option_value = ''.join(env[option]) if option in env else ''
armvixldb644342015-07-21 11:37:10 +0100429 build_dir = join(build_dir, option + '_'+ option_value)
430 return build_dir
431
432
433def PrepareVariantDir(location, build_dir):
434 location_build_dir = join(build_dir, location)
435 VariantDir(location_build_dir, location)
436 return location_build_dir
437
438
439def VIXLLibraryTarget(env):
440 build_dir = TargetBuildDir(env)
441 # Create a link to the latest build directory.
Alexandre Rames4e241932016-06-08 21:32:03 +0100442 # Use `-r` to avoid failure when `latest` exists and is a directory.
443 subprocess.check_call(["rm", "-rf", config.dir_build_latest])
armvixldb644342015-07-21 11:37:10 +0100444 util.ensure_dir(build_dir)
445 subprocess.check_call(["ln", "-s", build_dir, config.dir_build_latest])
Alexandre Ramesd3832962016-07-04 15:03:43 +0100446 # Source files are in `src` and in `src/aarch64/`.
Alexandre Rames39c32a62016-05-23 15:47:22 +0100447 variant_dir_vixl = PrepareVariantDir(join('src'), build_dir)
Pierre Langloisa3b21462016-08-04 16:01:51 +0100448 sources = [Glob(join(variant_dir_vixl, '*.cc'))]
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000449 if CanTargetAArch32(env):
Pierre Langloisa3b21462016-08-04 16:01:51 +0100450 variant_dir_aarch32 = PrepareVariantDir(join('src', 'aarch32'), build_dir)
451 sources.append(Glob(join(variant_dir_aarch32, '*.cc')))
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000452 if CanTargetAArch64(env):
Pierre Langloisa3b21462016-08-04 16:01:51 +0100453 variant_dir_aarch64 = PrepareVariantDir(join('src', 'aarch64'), build_dir)
454 sources.append(Glob(join(variant_dir_aarch64, '*.cc')))
armvixldb644342015-07-21 11:37:10 +0100455 return env.Library(join(build_dir, 'vixl'), sources)
456
457
458
459# Build ------------------------------------------------------------------------
460
461# The VIXL library, built by default.
Pierre Langlois287e6d12016-11-21 14:56:01 +0000462env = Environment(variables = vars,
463 BUILDERS = {
464 'Markdown': Builder(action = 'markdown $SOURCE > $TARGET',
465 suffix = '.html')
Anthony Barbierf2986e12019-02-28 16:49:23 +0000466 }, ENV = os.environ)
Alexandre Ramesf5de33d2016-10-25 09:51:11 +0100467# Abort the build if any command line option is unknown or invalid.
468unknown_build_options = vars.UnknownVariables()
469if unknown_build_options:
Matthew Benthamfe7cb102020-05-30 13:28:36 +0100470 print('Unknown build options: ' + str(unknown_build_options.keys()))
Alexandre Ramesf5de33d2016-10-25 09:51:11 +0100471 Exit(1)
472
Anthony Barbierf2986e12019-02-28 16:49:23 +0000473if env['negative_testing'] == 'on' and env['mode'] != 'debug':
Matthew Benthamfe7cb102020-05-30 13:28:36 +0100474 print('negative_testing only works in debug mode')
Anthony Barbierf2986e12019-02-28 16:49:23 +0000475 Exit(1)
476
armvixldb644342015-07-21 11:37:10 +0100477ConfigureEnvironment(env)
armvixldb644342015-07-21 11:37:10 +0100478Help(vars.GenerateHelpText(env))
479libvixl = VIXLLibraryTarget(env)
480Default(libvixl)
481env.Alias('libvixl', libvixl)
482top_level_targets.Add('', 'Build the VIXL library.')
483
armvixl4a102ba2014-07-14 09:02:40 +0100484
Pierre Langloisa3b21462016-08-04 16:01:51 +0100485# Common test code.
armvixldb644342015-07-21 11:37:10 +0100486test_build_dir = PrepareVariantDir('test', TargetBuildDir(env))
Pierre Langlois88c46b82016-06-02 18:15:32 +0100487test_objects = [env.Object(Glob(join(test_build_dir, '*.cc')))]
Mateusz Kalinowskicc24b302020-10-02 10:09:53 +0100488# Global variable holding cpp version as an integer.
489# Useful in optional linking with text assembler library.
490m = re.match('c\+\+(\d{2})', env['std'])
491cpp_version = 14 if m is None else int(m.group(1))
Pierre Langlois88c46b82016-06-02 18:15:32 +0100492
Pierre Langloisa3b21462016-08-04 16:01:51 +0100493# AArch32 support
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000494if CanTargetAArch32(env):
Pierre Langloisa3b21462016-08-04 16:01:51 +0100495 # The examples.
496 aarch32_example_names = util.ListCCFilesWithoutExt(config.dir_aarch32_examples)
497 aarch32_examples_build_dir = PrepareVariantDir('examples/aarch32', TargetBuildDir(env))
498 aarch32_example_targets = []
499 for example in aarch32_example_names:
500 prog = env.Program(join(aarch32_examples_build_dir, example),
501 join(aarch32_examples_build_dir, example + '.cc'),
502 LIBS=[libvixl])
503 aarch32_example_targets.append(prog)
504 env.Alias('aarch32_examples', aarch32_example_targets)
505 top_level_targets.Add('aarch32_examples', 'Build the examples for AArch32.')
Pierre Langlois88c46b82016-06-02 18:15:32 +0100506
Vincent Belliard32cf2542016-07-14 10:04:09 -0700507 # The benchmarks
508 aarch32_benchmark_names = util.ListCCFilesWithoutExt(config.dir_aarch32_benchmarks)
509 aarch32_benchmarks_build_dir = PrepareVariantDir('benchmarks/aarch32', TargetBuildDir(env))
510 aarch32_benchmark_targets = []
511 for bench in aarch32_benchmark_names:
512 prog = env.Program(join(aarch32_benchmarks_build_dir, bench),
513 join(aarch32_benchmarks_build_dir, bench + '.cc'),
514 LIBS=[libvixl])
515 aarch32_benchmark_targets.append(prog)
516 env.Alias('aarch32_benchmarks', aarch32_benchmark_targets)
517 top_level_targets.Add('aarch32_benchmarks', 'Build the benchmarks for AArch32.')
518
Pierre Langloisa3b21462016-08-04 16:01:51 +0100519 # The tests.
520 test_aarch32_build_dir = PrepareVariantDir(join('test', 'aarch32'), TargetBuildDir(env))
521 test_objects.append(env.Object(
522 Glob(join(test_aarch32_build_dir, '*.cc')),
Anthony Barbier7b4df2b2019-03-12 17:36:15 +0000523 CPPPATH = env['CPPPATH'] + [config.dir_tests],
524 CCFLAGS = [flag for flag in env['CCFLAGS'] if flag != '-O3']))
Pierre Langlois88c46b82016-06-02 18:15:32 +0100525
Pierre Langloisa3b21462016-08-04 16:01:51 +0100526# AArch64 support
Rodolph Perfetta9a9331f2016-12-09 22:05:48 +0000527if CanTargetAArch64(env):
Pierre Langloisa3b21462016-08-04 16:01:51 +0100528 # The benchmarks.
529 aarch64_benchmark_names = util.ListCCFilesWithoutExt(config.dir_aarch64_benchmarks)
530 aarch64_benchmarks_build_dir = PrepareVariantDir('benchmarks/aarch64', TargetBuildDir(env))
531 aarch64_benchmark_targets = []
Jacob Bramley1d925c02019-06-17 16:51:23 +0100532 bench_utils = env.Object(join(aarch64_benchmarks_build_dir, 'bench-utils.o'),
533 join(aarch64_benchmarks_build_dir, 'bench-utils.cc'))
Pierre Langloisa3b21462016-08-04 16:01:51 +0100534 for bench in aarch64_benchmark_names:
Jacob Bramley1d925c02019-06-17 16:51:23 +0100535 if bench != 'bench-utils':
536 prog = env.Program(join(aarch64_benchmarks_build_dir, bench),
537 [join(aarch64_benchmarks_build_dir, bench + '.cc'), bench_utils],
538 LIBS=[libvixl])
539 aarch64_benchmark_targets.append(prog)
Pierre Langloisa3b21462016-08-04 16:01:51 +0100540 env.Alias('aarch64_benchmarks', aarch64_benchmark_targets)
541 top_level_targets.Add('aarch64_benchmarks', 'Build the benchmarks for AArch64.')
542
543 # The examples.
544 aarch64_example_names = util.ListCCFilesWithoutExt(config.dir_aarch64_examples)
545 aarch64_examples_build_dir = PrepareVariantDir('examples/aarch64', TargetBuildDir(env))
546 aarch64_example_targets = []
547 for example in aarch64_example_names:
548 prog = env.Program(join(aarch64_examples_build_dir, example),
549 join(aarch64_examples_build_dir, example + '.cc'),
550 LIBS=[libvixl])
551 aarch64_example_targets.append(prog)
552 env.Alias('aarch64_examples', aarch64_example_targets)
553 top_level_targets.Add('aarch64_examples', 'Build the examples for AArch64.')
554
Mateusz Kalinowskicc24b302020-10-02 10:09:53 +0100555 # The text assembler.
556 text_assembler_build_dir = PrepareVariantDir('src/tasm', TargetBuildDir(env))
557 tasm_obj = env.Object(
558 Glob(join(text_assembler_build_dir, '*.cc')),
559 CPPPATH = env['CPPPATH'] + [config.dir_src_tasm])
560
561 libtasm = env.Library(text_assembler_build_dir, tasm_obj, LIBS=[libvixl])
562 env.Alias('text_assembler', libtasm)
563
564 top_level_targets.Add('text_assembler', 'Build text assembler. Requires C++17.', 17)
565 if ('text_assembler' in COMMAND_LINE_TARGETS) and (cpp_version < 17):
566 warnings.warn('The text assembler requires C++17 or above.')
567
568 # The text assembler examples.
569 tasm_examples_names = util.ListCCFilesWithoutExt(config.dir_tasm_examples)
570 tasm_examples_build_dir = PrepareVariantDir('examples/aarch64/tasm', TargetBuildDir(env))
571 tasm_examples_targets = []
572 for example in tasm_examples_names:
573 example_obj = env.Object(
574 Glob(join(tasm_examples_build_dir, example + '.cc')),
575 CPPPATH = env['CPPPATH'] + [config.dir_src_tasm] + [config.dir_tasm_examples])
576 prog = env.Program(join(tasm_examples_build_dir, example), example_obj,
577 LIBS=[libtasm, libvixl])
578 tasm_examples_targets.append(prog)
579
580 # Copy files with examples in assembly language to build output directory.
581 asm_src_dir = Glob(join(config.dir_tasm_examples, 'asm-src/*'))
582 copy_cmd = env.Install(join(tasm_examples_build_dir, 'asm-src'), asm_src_dir)
583 env.Alias('tasm_examples', tasm_examples_targets)
584 env.Depends('tasm_examples', copy_cmd)
585
586 top_level_targets.Add('tasm_examples',
587 'Build the examples for text assembler. Requires C++17.', 17)
588 if ('tasm_examples' in COMMAND_LINE_TARGETS) and (cpp_version < 17):
589 warnings.warn('The text assembler requires C++17 or above.')
590
Pierre Langloisa3b21462016-08-04 16:01:51 +0100591 # The tests.
592 test_aarch64_build_dir = PrepareVariantDir(join('test', 'aarch64'), TargetBuildDir(env))
593 test_objects.append(env.Object(
594 Glob(join(test_aarch64_build_dir, '*.cc')),
Anthony Barbier7b4df2b2019-03-12 17:36:15 +0000595 CPPPATH = env['CPPPATH'] + [config.dir_tests],
596 CCFLAGS = [flag for flag in env['CCFLAGS'] if flag != '-O3']))
Pierre Langloisa3b21462016-08-04 16:01:51 +0100597
598 # The test requires building the example files with specific options, so we
599 # create a separate variant dir for the example objects built this way.
600 test_aarch64_examples_vdir = join(TargetBuildDir(env), 'test', 'aarch64', 'test_examples')
601 VariantDir(test_aarch64_examples_vdir, '.')
602 test_aarch64_examples_obj = env.Object(
Jacob Bramley0f71a762018-08-30 12:09:34 +0100603 [Glob(join(test_aarch64_examples_vdir, join('test', 'aarch64', 'examples', '*.cc'))),
Pierre Langloisa3b21462016-08-04 16:01:51 +0100604 Glob(join(test_aarch64_examples_vdir, join('examples/aarch64', '*.cc')))],
605 CCFLAGS = env['CCFLAGS'] + ['-DTEST_EXAMPLES'],
606 CPPPATH = env['CPPPATH'] + [config.dir_aarch64_examples] + [config.dir_tests])
607 test_objects.append(test_aarch64_examples_obj)
Pierre Langlois88c46b82016-06-02 18:15:32 +0100608
Mateusz Kalinowskicc24b302020-10-02 10:09:53 +0100609libtasm_dep = [libtasm] if ((cpp_version >= 17) and ('a64' in env['target'])) else []
Pierre Langlois88c46b82016-06-02 18:15:32 +0100610test = env.Program(join(test_build_dir, 'test-runner'), test_objects,
Mateusz Kalinowskicc24b302020-10-02 10:09:53 +0100611 LIBS=[libvixl] + libtasm_dep)
armvixldb644342015-07-21 11:37:10 +0100612env.Alias('tests', test)
613top_level_targets.Add('tests', 'Build the tests.')
armvixl4a102ba2014-07-14 09:02:40 +0100614
Mateusz Kalinowskicc24b302020-10-02 10:09:53 +0100615all_targets = [t[0] for t in top_level_targets.targets if cpp_version >= t[1]]
616env.Alias('all', all_targets)
617top_level_targets.Add('all', 'Build all targets possible for the specified "std".')
armvixldb644342015-07-21 11:37:10 +0100618
619Help('\n\nAvailable top level targets:\n' + top_level_targets.Help())
Pierre Langlois287e6d12016-11-21 14:56:01 +0000620
621extra_targets = VIXLTargets()
622
623# Build documentation
624doc = [
625 env.Markdown('README.md'),
626 env.Markdown('doc/changelog.md'),
627 env.Markdown('doc/aarch32/getting-started-aarch32.md'),
628 env.Markdown('doc/aarch32/design/code-generation-aarch32.md'),
629 env.Markdown('doc/aarch32/design/literal-pool-aarch32.md'),
630 env.Markdown('doc/aarch64/supported-instructions-aarch64.md'),
631 env.Markdown('doc/aarch64/getting-started-aarch64.md'),
632 env.Markdown('doc/aarch64/topics/ycm.md'),
633 env.Markdown('doc/aarch64/topics/extending-the-disassembler.md'),
634 env.Markdown('doc/aarch64/topics/index.md'),
635]
636env.Alias('doc', doc)
637extra_targets.Add('doc', 'Convert documentation to HTML (requires the '
638 '`markdown` program).')
639
640Help('\nAvailable extra targets:\n' + extra_targets.Help())