| #!/usr/bin/env python2 |
| # |
| # Copyright 2017 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| # |
| # pylint: disable=cros-logging-import |
| |
| """Script to build the benchmark locally with toolchain settings.""" |
| from __future__ import print_function |
| |
| import argparse |
| import config |
| import logging |
| import os |
| import subprocess |
| import sys |
| |
| # Turn the logging level to INFO before importing other code, to avoid having |
| # failed import logging messages confuse the user. |
| logging.basicConfig(level=logging.INFO) |
| |
| |
| def _parse_arguments_internal(argv): |
| parser = argparse.ArgumentParser(description='Build benchmarks with ' |
| 'specified toolchain settings') |
| |
| parser.add_argument( |
| '-b', |
| '--bench', |
| required=True, |
| help='Select the benchmark to be built.') |
| |
| parser.add_argument( |
| '-c', |
| '--compiler_dir', |
| metavar='DIR', |
| help='Specify the path to the compiler bin ' |
| 'directory.') |
| |
| parser.add_argument( |
| '-o', |
| '--build_os', |
| help='Specify the host OS to build benchmark.') |
| |
| parser.add_argument( |
| '-l', |
| '--llvm_prebuilts_version', |
| help='Specify the version of prebuilt LLVM.') |
| |
| parser.add_argument( |
| '-f', |
| '--cflags', |
| help='Specify the optimization cflags for the toolchain.') |
| |
| parser.add_argument( |
| '--ldflags', |
| help='Specify linker flags for the toolchain.') |
| |
| return parser.parse_args(argv) |
| |
| |
| # Set flags for compiling benchmarks, by changing the local |
| # CFLAGS/LDFLAGS in the android makefile of each benchmark |
| def set_flags(bench, cflags, ldflags): |
| if not cflags: |
| logging.info('No CFLAGS specified, using default settings.') |
| cflags = '' |
| else: |
| logging.info('Cflags setting to "%s"...', cflags) |
| |
| if not ldflags: |
| logging.info('No LDFLAGS specifed, using default settings.') |
| ldflags = '' |
| else: |
| logging.info('Ldflags setting to "%s"...', ldflags) |
| |
| add_flags = config.bench_flags_dict[bench] |
| add_flags(cflags, ldflags) |
| logging.info('Flags set successfully!') |
| |
| |
| def set_build_os(build_os): |
| # Set $BUILD_OS variable for android makefile |
| if build_os: |
| os.environ['BUILD_OS'] = build_os |
| logging.info('BUILD_OS set to "%s"...', build_os) |
| else: |
| logging.info('No BUILD_OS specified, using linux as default...') |
| |
| |
| def set_llvm_prebuilts_version(llvm_prebuilts_version): |
| # Set $LLVM_PREBUILTS_VERSION for android makefile |
| if llvm_prebuilts_version: |
| os.environ['LLVM_PREBUILTS_VERSION'] = llvm_prebuilts_version |
| logging.info('LLVM_PREBUILTS_VERSION set to "%s"...', |
| llvm_prebuilts_version) |
| else: |
| logging.info('No LLVM_PREBUILTS_VERSION specified, ' |
| 'using default one...') |
| |
| |
| def set_compiler(compiler): |
| # If compiler_dir has been specified, copy the binaries to |
| # a temporary location, set BUILD_OS and LLVM_PREBUILTS_VERSION |
| # variables to the location |
| if compiler: |
| # Report error if path not exits |
| if not os.path.isdir(compiler): |
| logging.error('Error while setting compiler: ' |
| 'Directory %s does not exist!', compiler) |
| raise OSError('Directory %s not exist.' % compiler) |
| |
| # Specify temporary directory for compiler |
| tmp_dir = os.path.join(config.android_home, |
| 'prebuilts/clang/host/linux-x86', 'clang-tmp') |
| |
| compiler_content = os.path.join(compiler, '.') |
| |
| # Copy compiler to new directory |
| try: |
| subprocess.check_call(['cp', '-rf', compiler_content, tmp_dir]) |
| except subprocess.CalledProcessError: |
| logging.error('Error while copying the compiler to ' |
| 'temporary directory %s!', tmp_dir) |
| raise |
| |
| # Set environment variable |
| os.environ['LLVM_PREBUILTS_VERSION'] = 'clang-tmp' |
| |
| logging.info('Prebuilt Compiler set as %s.', os.path.abspath(compiler)) |
| |
| |
| def set_compiler_env(bench, compiler, build_os, llvm_prebuilts_version, cflags, |
| ldflags): |
| logging.info('Setting compiler options for benchmark...') |
| |
| # If no specific prebuilt compiler directory, use BUILD_OS and |
| # LLVM_PREBUILTS_VERSION to set the compiler version. |
| # Otherwise, use the new prebuilt compiler. |
| if not compiler: |
| set_build_os(build_os) |
| set_llvm_prebuilts_version(llvm_prebuilts_version) |
| else: |
| set_compiler(compiler) |
| |
| set_flags(bench, cflags, ldflags) |
| |
| return 0 |
| |
| |
| def remove_tmp_dir(): |
| tmp_dir = os.path.join(config.android_home, |
| 'prebuilts/clang/host/linux-x86', |
| 'clang-tmp') |
| |
| try: |
| subprocess.check_call(['rm', '-r', tmp_dir]) |
| except subprocess.CalledProcessError: |
| logging.error('Error while removing the temporary ' |
| 'compiler directory %s!', tmp_dir) |
| raise |
| |
| |
| # Recover the makefile/blueprint from our patch after building |
| def restore_makefile(bench): |
| pwd = os.path.join(config.android_home, config.bench_dict[bench]) |
| mk_file = os.path.join(pwd, 'Android.mk') |
| if not os.path.exists(mk_file): |
| mk_file = os.path.join(pwd, 'Android.bp') |
| subprocess.check_call(['mv', os.path.join(pwd, 'tmp_makefile'), mk_file]) |
| |
| |
| # Run script to build benchmark |
| def build_bench(bench, source_dir): |
| logging.info('Start building benchmark...') |
| |
| raw_cmd = ('cd {android_home} ' |
| '&& source build/envsetup.sh ' |
| '&& lunch {product_combo} ' |
| '&& mmma {source_dir} -j48'.format( |
| android_home=config.android_home, |
| product_combo=config.product_combo, |
| source_dir=source_dir)) |
| |
| log_file = os.path.join(config.bench_suite_dir, 'build_log') |
| with open(log_file, 'a') as logfile: |
| log_head = 'Log for building benchmark: %s\n' % (bench) |
| logfile.write(log_head) |
| try: |
| subprocess.check_call( |
| ['bash', '-c', raw_cmd], stdout=logfile, stderr=logfile) |
| except subprocess.CalledProcessError: |
| logging.error('Error while running %s, please check ' |
| '%s for more info.', raw_cmd, log_file) |
| restore_makefile(bench) |
| raise |
| |
| logging.info('Logs for building benchmark %s are written to %s.', |
| bench, log_file) |
| logging.info('Benchmark built successfully!') |
| |
| |
| def main(argv): |
| arguments = _parse_arguments_internal(argv) |
| |
| bench = arguments.bench |
| compiler = arguments.compiler_dir |
| build_os = arguments.build_os |
| llvm_version = arguments.llvm_prebuilts_version |
| cflags = arguments.cflags |
| ldflags = arguments.ldflags |
| |
| try: |
| source_dir = config.bench_dict[bench] |
| except KeyError: |
| logging.error('Please select one benchmark from the list below:\n\t' + |
| '\n\t'.join(config.bench_list)) |
| raise |
| |
| set_compiler_env(bench, compiler, build_os, llvm_version, cflags, ldflags) |
| |
| build_bench(bench, source_dir) |
| |
| # If flags has been set, remember to restore the makefile/blueprint to |
| # original ones. |
| restore_makefile(bench) |
| |
| # If a tmp directory is used for compiler path, remove it after building. |
| if compiler: |
| remove_tmp_dir() |
| |
| |
| if __name__ == '__main__': |
| main(sys.argv[1:]) |