blob: e29e9a782bf847dfc2bbe317430846b5c1cb4930 [file] [log] [blame]
# Copyright 2015, ARM Limited
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of ARM Limited nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
import os.path
import platform
import subprocess
import sys
root_dir = os.path.dirname(File('SConstruct').rfile().abspath)
sys.path.insert(0, os.path.join(root_dir, 'tools'))
import util
Help('''
Build system for the VIXL project.
See README.md for documentation and details about the build system.
Some common build targets are:
scons # Build the VIXL library and test utility.
scons examples # Build all the examples.
scons all # Build everything.
''')
# Global configuration.
PROJ_SRC_DIR = 'src'
PROJ_SRC_FILES = '''
src/vixl/a64/assembler-a64.cc
src/vixl/a64/cpu-a64.cc
src/vixl/a64/debugger-a64.cc
src/vixl/a64/decoder-a64.cc
src/vixl/a64/disasm-a64.cc
src/vixl/a64/instructions-a64.cc
src/vixl/a64/instrument-a64.cc
src/vixl/a64/logic-a64.cc
src/vixl/a64/macro-assembler-a64.cc
src/vixl/a64/simulator-a64.cc
src/vixl/code-buffer.cc
src/vixl/compiler-intrinsics.cc
src/vixl/utils.cc
'''.split()
PROJ_EXAMPLES_DIR = 'examples'
PROJ_EXAMPLES_SRC_FILES = '''
examples/abs.cc
examples/add2-vectors.cc
examples/add3-double.cc
examples/add4-double.cc
examples/check-bounds.cc
examples/crc-checksums.cc
examples/custom-disassembler.cc
examples/debugger.cc
examples/factorial-rec.cc
examples/factorial.cc
examples/neon-matrix-multiply.cc
examples/getting-started.cc
examples/non-const-visitor.cc
examples/sum-array.cc
examples/swap-int32.cc
examples/swap4.cc
'''.split()
# List target specific files.
# Target names are used as dictionary entries.
TARGET_SRC_DIR = {
'test': 'test',
'bench-dataop': 'benchmarks',
'bench-branch': 'benchmarks',
'bench-branch-link': 'benchmarks',
'bench-branch-masm': 'benchmarks',
'bench-branch-link-masm': 'benchmarks',
'examples': 'examples'
}
TARGET_SRC_FILES = {
'test': '''
test/test-runner.cc
test/examples/test-examples.cc
test/test-assembler-a64.cc
test/test-disasm-a64.cc
test/test-fuzz-a64.cc
test/test-invalset.cc
test/test-simulator-a64.cc
test/test-utils-a64.cc
'''.split(),
'bench-dataop': '''
benchmarks/bench-dataop.cc
'''.split(),
'bench-branch': '''
benchmarks/bench-branch.cc
'''.split(),
'bench-branch-link': '''
benchmarks/bench-branch-link.cc
'''.split(),
'bench-branch-masm': '''
benchmarks/bench-branch-masm.cc
'''.split(),
'bench-branch-link-masm': '''
benchmarks/bench-branch-link-masm.cc
'''.split()
}
OBJ_DIR = 'obj'
# Helper functions.
def abort(message):
print('ABORTING: ' + message)
sys.exit(1)
def list_target(obj_dir, src_files):
return map(lambda x: os.path.join(obj_dir, x), src_files)
def is_compiler(compiler):
return env['CXX'].find(compiler) == 0
def create_variant(obj_dir, targets_dir):
VariantDir(os.path.join(obj_dir, PROJ_SRC_DIR), PROJ_SRC_DIR)
for directory in targets_dir.itervalues():
VariantDir(os.path.join(obj_dir, directory), directory)
# Build arguments.
args = Variables()
args.Add(EnumVariable('mode', 'Build mode', 'release',
allowed_values = ['release', 'debug']))
sim_default = 'off' if platform.machine() == 'aarch64' else 'on'
args.Add(EnumVariable('simulator', 'build for the simulator', sim_default,
allowed_values = ['on', 'off']))
args.Add('std', 'c++ standard')
# Configure the environment.
env = Environment(variables=args)
# Commandline help.
Help(args.GenerateHelpText(env) + '\n')
# Abort if any invalid argument was passed.
# This check must happened after an environment is created.
unknown_arg = args.UnknownVariables()
if unknown_arg:
abort('Unknown variable(s): ' + str(unknown_arg.keys()))
# Setup tools.
# This is necessary for cross-compilation.
env['CXX'] = os.environ.get('CXX', env.get('CXX'))
env['AR'] = os.environ.get('AR', env.get('AR'))
env['RANLIB'] = os.environ.get('RANLIB', env.get('RANLIB'))
env['CC'] = os.environ.get('CC', env.get('CC'))
env['LD'] = os.environ.get('LD', env.get('LD'))
if os.environ.get('CPPFLAGS'):
env.Append(CPPFLAGS = os.environ.get('CPPFLAGS').split())
if os.environ.get('LINKFLAGS'):
env.Append(LINKFLAGS = os.environ.get('LINKFLAGS').split())
# Always look in 'src' for include files.
# TODO: Restore the '-Wunreachable-code' flag. This flag breaks builds for clang
# 3.4 with std=c++98. So we need to re-enable this conditionally when clang is at
# version 3.5 or later.
env.Append(CPPPATH = [PROJ_SRC_DIR])
env.Append(CPPFLAGS = ['-Wall',
'-Werror',
'-fdiagnostics-show-option',
'-Wextra',
'-Wredundant-decls',
'-pedantic',
# Explicitly enable the write-strings warning. VIXL uses
# const correctly when handling string constants.
'-Wwrite-strings'])
build_suffix = ''
std_path = 'default-std'
if 'std' in env:
env.Append(CPPFLAGS = ['-std=' + env['std']])
std_path = env['std']
if is_compiler('clang++'):
# This warning only works for Clang, when compiling the code base as C++11
# or newer. The compiler does not complain if the option is passed when
# compiling earlier C++ standards.
env.Append(CPPFLAGS = ['-Wimplicit-fallthrough'])
if env['simulator'] == 'on':
env.Append(CPPFLAGS = ['-DUSE_SIMULATOR'])
build_suffix += '_sim'
if env['mode'] == 'debug':
env.Append(CPPFLAGS = ['-g', '-DVIXL_DEBUG'])
# Append the debug mode suffix to the executable name.
build_suffix += '_g'
else:
# Release mode.
env.Append(CPPFLAGS = ['-O3'])
process = subprocess.Popen(env['CXX'] + ' --version | grep "gnu.*4\.8"',
shell = True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout, stderr = process.communicate()
using_gcc48 = stdout != ''
if using_gcc48:
# GCC 4.8 has a bug which produces a warning saying that an anonymous
# Operand object might be used uninitialized:
# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57045
# The bug does not seem to appear in GCC 4.7, or in debug builds with
# GCC 4.8.
env.Append(CPPFLAGS = ['-Wno-maybe-uninitialized'])
# Configure build directory
build_dir = os.path.join(OBJ_DIR, env['mode'], env['CXX'], std_path, '')
create_variant(build_dir, TARGET_SRC_DIR)
# The lists of available targets and target names.
targets = []
target_alias_names = []
# Helper to create aliases.
def create_alias(name, target):
env.Alias(name, target)
targets.append(target)
target_alias_names.append(name)
# The vixl library.
libvixl = env.Library(build_dir + 'vixl' + build_suffix,
list_target(build_dir, PROJ_SRC_FILES))
create_alias('libvixl', libvixl)
# The test executable.
# The test requires building the example files with specific options, so we
# create a separate variant dir for the example objects built this way.
test_ex_vdir = os.path.join(build_dir, 'test_examples')
VariantDir(test_ex_vdir, '.')
test_ex_obj = env.Object(list_target(test_ex_vdir, PROJ_EXAMPLES_SRC_FILES),
CPPFLAGS = env['CPPFLAGS'] + ['-DTEST_EXAMPLES'])
test = env.Program(build_dir + 'test-runner' + build_suffix,
list_target(build_dir, TARGET_SRC_FILES['test']) +
test_ex_obj + libvixl,
CPPPATH = env['CPPPATH'] + [PROJ_EXAMPLES_DIR])
create_alias('test', test)
# The benchmarks.
benchmarks = ['bench-dataop', 'bench-branch', 'bench-branch-link',
'bench-branch-masm', 'bench-branch-link-masm']
for bench in benchmarks:
prog = env.Program(build_dir + bench + build_suffix,
list_target(build_dir, TARGET_SRC_FILES[bench]) + libvixl)
create_alias(bench, prog)
# Alias to build all benchmarks.
create_alias('benchmarks', benchmarks)
# The examples.
examples = []
for example in PROJ_EXAMPLES_SRC_FILES:
example_name = "example-" + os.path.splitext(os.path.basename(example))[0]
prog = env.Program(build_dir + example_name,
[os.path.join(build_dir, example)] + libvixl,
CPPPATH = env['CPPPATH'] + [PROJ_EXAMPLES_DIR])
create_alias(example_name, prog)
examples.append(prog)
# Alias to build all examples.
create_alias('examples', examples)
# Create a simple alias to build everything with the current options.
create_alias('all', targets)
Help('Available top level targets:\n' + '\t' + '\n\t'.join(target_alias_names) + '\n')
# By default, only build the tests.
Default(libvixl, test)