1 # Copyright 2015, ARM Limited 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 27 import os 28 import os.path 29 import platform 30 import subprocess 31 import sys 32 33 root_dir = os.path.dirname(File('SConstruct').rfile().abspath) 34 sys.path.insert(0, os.path.join(root_dir, 'tools')) 35 import util 36 37 38 Help(''' 39 Build system for the VIXL project. 40 See README.md for documentation and details about the build system. 41 Some common build targets are: 42 scons # Build the VIXL library and test utility. 43 scons examples # Build all the examples. 44 scons all # Build everything. 45 46 ''') 47 48 49 # Global configuration. 50 PROJ_SRC_DIR = 'src' 51 PROJ_SRC_FILES = ''' 52 src/vixl/a64/assembler-a64.cc 53 src/vixl/a64/cpu-a64.cc 54 src/vixl/a64/debugger-a64.cc 55 src/vixl/a64/decoder-a64.cc 56 src/vixl/a64/disasm-a64.cc 57 src/vixl/a64/instructions-a64.cc 58 src/vixl/a64/instrument-a64.cc 59 src/vixl/a64/logic-a64.cc 60 src/vixl/a64/macro-assembler-a64.cc 61 src/vixl/a64/simulator-a64.cc 62 src/vixl/code-buffer.cc 63 src/vixl/compiler-intrinsics.cc 64 src/vixl/utils.cc 65 '''.split() 66 PROJ_EXAMPLES_DIR = 'examples' 67 PROJ_EXAMPLES_SRC_FILES = ''' 68 examples/abs.cc 69 examples/add2-vectors.cc 70 examples/add3-double.cc 71 examples/add4-double.cc 72 examples/check-bounds.cc 73 examples/crc-checksums.cc 74 examples/custom-disassembler.cc 75 examples/debugger.cc 76 examples/factorial-rec.cc 77 examples/factorial.cc 78 examples/neon-matrix-multiply.cc 79 examples/getting-started.cc 80 examples/non-const-visitor.cc 81 examples/sum-array.cc 82 examples/swap-int32.cc 83 examples/swap4.cc 84 '''.split() 85 # List target specific files. 86 # Target names are used as dictionary entries. 87 TARGET_SRC_DIR = { 88 'test': 'test', 89 'bench-dataop': 'benchmarks', 90 'bench-branch': 'benchmarks', 91 'bench-branch-link': 'benchmarks', 92 'bench-branch-masm': 'benchmarks', 93 'bench-branch-link-masm': 'benchmarks', 94 'examples': 'examples' 95 } 96 TARGET_SRC_FILES = { 97 'test': ''' 98 test/test-runner.cc 99 test/examples/test-examples.cc 100 test/test-assembler-a64.cc 101 test/test-disasm-a64.cc 102 test/test-fuzz-a64.cc 103 test/test-invalset.cc 104 test/test-simulator-a64.cc 105 test/test-utils-a64.cc 106 '''.split(), 107 'bench-dataop': ''' 108 benchmarks/bench-dataop.cc 109 '''.split(), 110 'bench-branch': ''' 111 benchmarks/bench-branch.cc 112 '''.split(), 113 'bench-branch-link': ''' 114 benchmarks/bench-branch-link.cc 115 '''.split(), 116 'bench-branch-masm': ''' 117 benchmarks/bench-branch-masm.cc 118 '''.split(), 119 'bench-branch-link-masm': ''' 120 benchmarks/bench-branch-link-masm.cc 121 '''.split() 122 } 123 OBJ_DIR = 'obj' 124 125 # Helper functions. 126 def abort(message): 127 print('ABORTING: ' + message) 128 sys.exit(1) 129 130 131 def list_target(obj_dir, src_files): 132 return map(lambda x: os.path.join(obj_dir, x), src_files) 133 134 135 def is_compiler(compiler): 136 return env['CXX'].find(compiler) == 0 137 138 139 def create_variant(obj_dir, targets_dir): 140 VariantDir(os.path.join(obj_dir, PROJ_SRC_DIR), PROJ_SRC_DIR) 141 for directory in targets_dir.itervalues(): 142 VariantDir(os.path.join(obj_dir, directory), directory) 143 144 145 # Build arguments. 146 args = Variables() 147 args.Add(EnumVariable('mode', 'Build mode', 'release', 148 allowed_values = ['release', 'debug'])) 149 sim_default = 'off' if platform.machine() == 'aarch64' else 'on' 150 args.Add(EnumVariable('simulator', 'build for the simulator', sim_default, 151 allowed_values = ['on', 'off'])) 152 args.Add('std', 'c++ standard') 153 154 # Configure the environment. 155 env = Environment(variables=args) 156 157 # Commandline help. 158 Help(args.GenerateHelpText(env) + '\n') 159 160 # Abort if any invalid argument was passed. 161 # This check must happened after an environment is created. 162 unknown_arg = args.UnknownVariables() 163 if unknown_arg: 164 abort('Unknown variable(s): ' + str(unknown_arg.keys())) 165 166 # Setup tools. 167 # This is necessary for cross-compilation. 168 env['CXX'] = os.environ.get('CXX', env.get('CXX')) 169 env['AR'] = os.environ.get('AR', env.get('AR')) 170 env['RANLIB'] = os.environ.get('RANLIB', env.get('RANLIB')) 171 env['CC'] = os.environ.get('CC', env.get('CC')) 172 env['LD'] = os.environ.get('LD', env.get('LD')) 173 174 if os.environ.get('CPPFLAGS'): 175 env.Append(CPPFLAGS = os.environ.get('CPPFLAGS').split()) 176 if os.environ.get('LINKFLAGS'): 177 env.Append(LINKFLAGS = os.environ.get('LINKFLAGS').split()) 178 179 # Always look in 'src' for include files. 180 # TODO: Restore the '-Wunreachable-code' flag. This flag breaks builds for clang 181 # 3.4 with std=c++98. So we need to re-enable this conditionally when clang is at 182 # version 3.5 or later. 183 env.Append(CPPPATH = [PROJ_SRC_DIR]) 184 env.Append(CPPFLAGS = ['-Wall', 185 '-Werror', 186 '-fdiagnostics-show-option', 187 '-Wextra', 188 '-Wredundant-decls', 189 '-pedantic', 190 # Explicitly enable the write-strings warning. VIXL uses 191 # const correctly when handling string constants. 192 '-Wwrite-strings']) 193 194 build_suffix = '' 195 std_path = 'default-std' 196 197 if 'std' in env: 198 env.Append(CPPFLAGS = ['-std=' + env['std']]) 199 std_path = env['std'] 200 201 if is_compiler('clang++'): 202 # This warning only works for Clang, when compiling the code base as C++11 203 # or newer. The compiler does not complain if the option is passed when 204 # compiling earlier C++ standards. 205 env.Append(CPPFLAGS = ['-Wimplicit-fallthrough']) 206 207 if env['simulator'] == 'on': 208 env.Append(CPPFLAGS = ['-DUSE_SIMULATOR']) 209 build_suffix += '_sim' 210 211 if env['mode'] == 'debug': 212 env.Append(CPPFLAGS = ['-g', '-DVIXL_DEBUG']) 213 # Append the debug mode suffix to the executable name. 214 build_suffix += '_g' 215 else: 216 # Release mode. 217 env.Append(CPPFLAGS = ['-O3']) 218 process = subprocess.Popen(env['CXX'] + ' --version | grep "gnu.*4\.8"', 219 shell = True, 220 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 221 stdout, stderr = process.communicate() 222 using_gcc48 = stdout != '' 223 if using_gcc48: 224 # GCC 4.8 has a bug which produces a warning saying that an anonymous 225 # Operand object might be used uninitialized: 226 # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57045 227 # The bug does not seem to appear in GCC 4.7, or in debug builds with 228 # GCC 4.8. 229 env.Append(CPPFLAGS = ['-Wno-maybe-uninitialized']) 230 231 # Configure build directory 232 build_dir = os.path.join(OBJ_DIR, env['mode'], env['CXX'], std_path, '') 233 create_variant(build_dir, TARGET_SRC_DIR) 234 235 # The lists of available targets and target names. 236 targets = [] 237 target_alias_names = [] 238 # Helper to create aliases. 239 def create_alias(name, target): 240 env.Alias(name, target) 241 targets.append(target) 242 target_alias_names.append(name) 243 244 245 # The vixl library. 246 libvixl = env.Library(build_dir + 'vixl' + build_suffix, 247 list_target(build_dir, PROJ_SRC_FILES)) 248 create_alias('libvixl', libvixl) 249 250 251 # The test executable. 252 # The test requires building the example files with specific options, so we 253 # create a separate variant dir for the example objects built this way. 254 test_ex_vdir = os.path.join(build_dir, 'test_examples') 255 VariantDir(test_ex_vdir, '.') 256 test_ex_obj = env.Object(list_target(test_ex_vdir, PROJ_EXAMPLES_SRC_FILES), 257 CPPFLAGS = env['CPPFLAGS'] + ['-DTEST_EXAMPLES']) 258 test = env.Program(build_dir + 'test-runner' + build_suffix, 259 list_target(build_dir, TARGET_SRC_FILES['test']) + 260 test_ex_obj + libvixl, 261 CPPPATH = env['CPPPATH'] + [PROJ_EXAMPLES_DIR]) 262 create_alias('test', test) 263 264 # The benchmarks. 265 benchmarks = ['bench-dataop', 'bench-branch', 'bench-branch-link', 266 'bench-branch-masm', 'bench-branch-link-masm'] 267 for bench in benchmarks: 268 prog = env.Program(build_dir + bench + build_suffix, 269 list_target(build_dir, TARGET_SRC_FILES[bench]) + libvixl) 270 create_alias(bench, prog) 271 # Alias to build all benchmarks. 272 create_alias('benchmarks', benchmarks) 273 274 # The examples. 275 examples = [] 276 for example in PROJ_EXAMPLES_SRC_FILES: 277 example_name = "example-" + os.path.splitext(os.path.basename(example))[0] 278 prog = env.Program(build_dir + example_name, 279 [os.path.join(build_dir, example)] + libvixl, 280 CPPPATH = env['CPPPATH'] + [PROJ_EXAMPLES_DIR]) 281 create_alias(example_name, prog) 282 examples.append(prog) 283 # Alias to build all examples. 284 create_alias('examples', examples) 285 286 287 # Create a simple alias to build everything with the current options. 288 create_alias('all', targets) 289 290 Help('Available top level targets:\n' + '\t' + '\n\t'.join(target_alias_names) + '\n') 291 292 # By default, only build the tests. 293 Default(libvixl, test) 294