| # 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) |