Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python2 |
| 2 | # |
| 3 | # Copyright 2017 The Chromium OS Authors. All rights reserved. |
| 4 | # Use of this source code is governed by a BSD-style license that can be |
| 5 | # found in the LICENSE file. |
| 6 | # |
| 7 | # pylint: disable=cros-logging-import |
| 8 | |
| 9 | """Script to build the benchmark locally with toolchain settings.""" |
| 10 | from __future__ import print_function |
| 11 | |
| 12 | import argparse |
| 13 | import config |
| 14 | import logging |
| 15 | import os |
| 16 | import subprocess |
| 17 | import sys |
| 18 | |
| 19 | # Turn the logging level to INFO before importing other code, to avoid having |
| 20 | # failed import logging messages confuse the user. |
| 21 | logging.basicConfig(level=logging.INFO) |
| 22 | |
| 23 | |
| 24 | def _parse_arguments_internal(argv): |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 25 | parser = argparse.ArgumentParser(description='Build benchmarks with ' |
| 26 | 'specified toolchain settings') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 27 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 28 | parser.add_argument( |
| 29 | '-b', |
| 30 | '--bench', |
| 31 | required=True, |
| 32 | help='Select the benchmark to be built.') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 33 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 34 | parser.add_argument( |
| 35 | '-c', |
| 36 | '--compiler_dir', |
| 37 | metavar='DIR', |
| 38 | help='Specify the path to the compiler bin ' |
| 39 | 'directory.') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 40 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 41 | parser.add_argument( |
| 42 | '-o', |
| 43 | '--build_os', |
| 44 | help='Specify the host OS to build benchmark.') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 45 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 46 | parser.add_argument( |
| 47 | '-l', |
| 48 | '--llvm_prebuilts_version', |
| 49 | help='Specify the version of prebuilt LLVM.') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 50 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 51 | parser.add_argument( |
| 52 | '-f', |
| 53 | '--cflags', |
| 54 | help='Specify the optimization cflags for the toolchain.') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 55 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 56 | parser.add_argument( |
| 57 | '--ldflags', |
| 58 | help='Specify linker flags for the toolchain.') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 59 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 60 | return parser.parse_args(argv) |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 61 | |
| 62 | |
| 63 | # Set flags for compiling benchmarks, by changing the local |
| 64 | # CFLAGS/LDFLAGS in the android makefile of each benchmark |
| 65 | def set_flags(bench, cflags, ldflags): |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 66 | if not cflags: |
| 67 | logging.info('No CFLAGS specified, using default settings.') |
| 68 | cflags = '' |
| 69 | else: |
| 70 | logging.info('Cflags setting to "%s"...', cflags) |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 71 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 72 | if not ldflags: |
| 73 | logging.info('No LDFLAGS specifed, using default settings.') |
| 74 | ldflags = '' |
| 75 | else: |
| 76 | logging.info('Ldflags setting to "%s"...', ldflags) |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 77 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 78 | add_flags = config.bench_flags_dict[bench] |
| 79 | add_flags(cflags, ldflags) |
| 80 | logging.info('Flags set successfully!') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 81 | |
| 82 | |
| 83 | def set_build_os(build_os): |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 84 | # Set $BUILD_OS variable for android makefile |
| 85 | if build_os: |
| 86 | os.environ['BUILD_OS'] = build_os |
| 87 | logging.info('BUILD_OS set to "%s"...', build_os) |
| 88 | else: |
| 89 | logging.info('No BUILD_OS specified, using linux as default...') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 90 | |
| 91 | |
| 92 | def set_llvm_prebuilts_version(llvm_prebuilts_version): |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 93 | # Set $LLVM_PREBUILTS_VERSION for android makefile |
| 94 | if llvm_prebuilts_version: |
| 95 | os.environ['LLVM_PREBUILTS_VERSION'] = llvm_prebuilts_version |
| 96 | logging.info('LLVM_PREBUILTS_VERSION set to "%s"...', |
| 97 | llvm_prebuilts_version) |
| 98 | else: |
| 99 | logging.info('No LLVM_PREBUILTS_VERSION specified, ' |
| 100 | 'using default one...') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 101 | |
| 102 | |
| 103 | def set_compiler(compiler): |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 104 | # If compiler_dir has been specified, copy the binaries to |
| 105 | # a temporary location, set BUILD_OS and LLVM_PREBUILTS_VERSION |
| 106 | # variables to the location |
| 107 | if compiler: |
| 108 | # Report error if path not exits |
| 109 | if not os.path.isdir(compiler): |
| 110 | logging.error('Error while setting compiler: ' |
| 111 | 'Directory %s does not exist!', compiler) |
| 112 | raise OSError('Directory %s not exist.' % compiler) |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 113 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 114 | # Specify temporary directory for compiler |
| 115 | tmp_dir = os.path.join(config.android_home, |
| 116 | 'prebuilts/clang/host/linux-x86', 'clang-tmp') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 117 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 118 | compiler_content = os.path.join(compiler, '.') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 119 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 120 | # Copy compiler to new directory |
| 121 | try: |
| 122 | subprocess.check_call(['cp', '-rf', compiler_content, tmp_dir]) |
| 123 | except subprocess.CalledProcessError: |
| 124 | logging.error('Error while copying the compiler to ' |
| 125 | 'temporary directory %s!', tmp_dir) |
| 126 | raise |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 127 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 128 | # Set environment variable |
| 129 | os.environ['LLVM_PREBUILTS_VERSION'] = 'clang-tmp' |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 130 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 131 | logging.info('Prebuilt Compiler set as %s.', os.path.abspath(compiler)) |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 132 | |
| 133 | |
| 134 | def set_compiler_env(bench, compiler, build_os, llvm_prebuilts_version, cflags, |
| 135 | ldflags): |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 136 | logging.info('Setting compiler options for benchmark...') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 137 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 138 | # If no specific prebuilt compiler directory, use BUILD_OS and |
| 139 | # LLVM_PREBUILTS_VERSION to set the compiler version. |
| 140 | # Otherwise, use the new prebuilt compiler. |
| 141 | if not compiler: |
| 142 | set_build_os(build_os) |
| 143 | set_llvm_prebuilts_version(llvm_prebuilts_version) |
| 144 | else: |
| 145 | set_compiler(compiler) |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 146 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 147 | set_flags(bench, cflags, ldflags) |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 148 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 149 | return 0 |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 150 | |
| 151 | |
| 152 | def remove_tmp_dir(): |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 153 | tmp_dir = os.path.join(config.android_home, |
| 154 | 'prebuilts/clang/host/linux-x86', |
| 155 | 'clang-tmp') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 156 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 157 | try: |
| 158 | subprocess.check_call(['rm', '-r', tmp_dir]) |
| 159 | except subprocess.CalledProcessError: |
| 160 | logging.error('Error while removing the temporary ' |
| 161 | 'compiler directory %s!', tmp_dir) |
| 162 | raise |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 163 | |
| 164 | |
| 165 | # Recover the makefile/blueprint from our patch after building |
| 166 | def restore_makefile(bench): |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 167 | pwd = os.path.join(config.android_home, config.bench_dict[bench]) |
| 168 | mk_file = os.path.join(pwd, 'Android.mk') |
| 169 | if not os.path.exists(mk_file): |
| 170 | mk_file = os.path.join(pwd, 'Android.bp') |
| 171 | subprocess.check_call(['mv', os.path.join(pwd, 'tmp_makefile'), mk_file]) |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 172 | |
| 173 | |
| 174 | # Run script to build benchmark |
| 175 | def build_bench(bench, source_dir): |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 176 | logging.info('Start building benchmark...') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 177 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 178 | raw_cmd = ('cd {android_home} ' |
| 179 | '&& source build/envsetup.sh ' |
| 180 | '&& lunch {product_combo} ' |
| 181 | '&& mmma {source_dir} -j48'.format( |
| 182 | android_home=config.android_home, |
| 183 | product_combo=config.product_combo, |
| 184 | source_dir=source_dir)) |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 185 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 186 | log_file = os.path.join(config.bench_suite_dir, 'build_log') |
| 187 | with open(log_file, 'a') as logfile: |
| 188 | log_head = 'Log for building benchmark: %s\n' % (bench) |
| 189 | logfile.write(log_head) |
| 190 | try: |
| 191 | subprocess.check_call( |
| 192 | ['bash', '-c', raw_cmd], stdout=logfile, stderr=logfile) |
| 193 | except subprocess.CalledProcessError: |
| 194 | logging.error('Error while running %s, please check ' |
| 195 | '%s for more info.', raw_cmd, log_file) |
| 196 | restore_makefile(bench) |
| 197 | raise |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 198 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 199 | logging.info('Logs for building benchmark %s are written to %s.', |
| 200 | bench, log_file) |
| 201 | logging.info('Benchmark built successfully!') |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 202 | |
| 203 | |
| 204 | def main(argv): |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 205 | arguments = _parse_arguments_internal(argv) |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 206 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 207 | bench = arguments.bench |
| 208 | compiler = arguments.compiler_dir |
| 209 | build_os = arguments.build_os |
| 210 | llvm_version = arguments.llvm_prebuilts_version |
| 211 | cflags = arguments.cflags |
| 212 | ldflags = arguments.ldflags |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 213 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 214 | try: |
| 215 | source_dir = config.bench_dict[bench] |
| 216 | except KeyError: |
| 217 | logging.error('Please select one benchmark from the list below:\n\t' + |
| 218 | '\n\t'.join(config.bench_list)) |
| 219 | raise |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 220 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 221 | set_compiler_env(bench, compiler, build_os, llvm_version, cflags, ldflags) |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 222 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 223 | build_bench(bench, source_dir) |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 224 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 225 | # If flags has been set, remember to restore the makefile/blueprint to |
| 226 | # original ones. |
| 227 | restore_makefile(bench) |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 228 | |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 229 | # If a tmp directory is used for compiler path, remove it after building. |
| 230 | if compiler: |
| 231 | remove_tmp_dir() |
Zhizhou Yang | e598690 | 2017-08-10 17:37:53 -0700 | [diff] [blame] | 232 | |
| 233 | |
| 234 | if __name__ == '__main__': |
Zhizhou Yang | 6236292 | 2017-08-30 16:04:36 -0700 | [diff] [blame] | 235 | main(sys.argv[1:]) |