blob: 5b65cb5bdd6674ceeb433747d01c764f3f0c57fa [file] [log] [blame]
Zhizhou Yange5986902017-08-10 17:37:53 -07001#!/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."""
10from __future__ import print_function
11
12import argparse
13import config
14import logging
15import os
16import subprocess
17import sys
18
19# Turn the logging level to INFO before importing other code, to avoid having
20# failed import logging messages confuse the user.
21logging.basicConfig(level=logging.INFO)
22
23
24def _parse_arguments_internal(argv):
Zhizhou Yang62362922017-08-30 16:04:36 -070025 parser = argparse.ArgumentParser(description='Build benchmarks with '
26 'specified toolchain settings')
Zhizhou Yange5986902017-08-10 17:37:53 -070027
Zhizhou Yang62362922017-08-30 16:04:36 -070028 parser.add_argument(
29 '-b',
30 '--bench',
31 required=True,
32 help='Select the benchmark to be built.')
Zhizhou Yange5986902017-08-10 17:37:53 -070033
Zhizhou Yang62362922017-08-30 16:04:36 -070034 parser.add_argument(
35 '-c',
36 '--compiler_dir',
37 metavar='DIR',
38 help='Specify the path to the compiler bin '
39 'directory.')
Zhizhou Yange5986902017-08-10 17:37:53 -070040
Zhizhou Yang62362922017-08-30 16:04:36 -070041 parser.add_argument(
42 '-o',
43 '--build_os',
44 help='Specify the host OS to build benchmark.')
Zhizhou Yange5986902017-08-10 17:37:53 -070045
Zhizhou Yang62362922017-08-30 16:04:36 -070046 parser.add_argument(
47 '-l',
48 '--llvm_prebuilts_version',
49 help='Specify the version of prebuilt LLVM.')
Zhizhou Yange5986902017-08-10 17:37:53 -070050
Zhizhou Yang62362922017-08-30 16:04:36 -070051 parser.add_argument(
52 '-f',
53 '--cflags',
54 help='Specify the optimization cflags for the toolchain.')
Zhizhou Yange5986902017-08-10 17:37:53 -070055
Zhizhou Yang62362922017-08-30 16:04:36 -070056 parser.add_argument(
57 '--ldflags',
58 help='Specify linker flags for the toolchain.')
Zhizhou Yange5986902017-08-10 17:37:53 -070059
Zhizhou Yang62362922017-08-30 16:04:36 -070060 return parser.parse_args(argv)
Zhizhou Yange5986902017-08-10 17:37:53 -070061
62
63# Set flags for compiling benchmarks, by changing the local
64# CFLAGS/LDFLAGS in the android makefile of each benchmark
65def set_flags(bench, cflags, ldflags):
Zhizhou Yang62362922017-08-30 16:04:36 -070066 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 Yange5986902017-08-10 17:37:53 -070071
Zhizhou Yang62362922017-08-30 16:04:36 -070072 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 Yange5986902017-08-10 17:37:53 -070077
Zhizhou Yang62362922017-08-30 16:04:36 -070078 add_flags = config.bench_flags_dict[bench]
79 add_flags(cflags, ldflags)
80 logging.info('Flags set successfully!')
Zhizhou Yange5986902017-08-10 17:37:53 -070081
82
83def set_build_os(build_os):
Zhizhou Yang62362922017-08-30 16:04:36 -070084 # 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 Yange5986902017-08-10 17:37:53 -070090
91
92def set_llvm_prebuilts_version(llvm_prebuilts_version):
Zhizhou Yang62362922017-08-30 16:04:36 -070093 # 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 Yange5986902017-08-10 17:37:53 -0700101
102
103def set_compiler(compiler):
Zhizhou Yang62362922017-08-30 16:04:36 -0700104 # 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 Yange5986902017-08-10 17:37:53 -0700113
Zhizhou Yang62362922017-08-30 16:04:36 -0700114 # Specify temporary directory for compiler
115 tmp_dir = os.path.join(config.android_home,
116 'prebuilts/clang/host/linux-x86', 'clang-tmp')
Zhizhou Yange5986902017-08-10 17:37:53 -0700117
Zhizhou Yang62362922017-08-30 16:04:36 -0700118 compiler_content = os.path.join(compiler, '.')
Zhizhou Yange5986902017-08-10 17:37:53 -0700119
Zhizhou Yang62362922017-08-30 16:04:36 -0700120 # 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 Yange5986902017-08-10 17:37:53 -0700127
Zhizhou Yang62362922017-08-30 16:04:36 -0700128 # Set environment variable
129 os.environ['LLVM_PREBUILTS_VERSION'] = 'clang-tmp'
Zhizhou Yange5986902017-08-10 17:37:53 -0700130
Zhizhou Yang62362922017-08-30 16:04:36 -0700131 logging.info('Prebuilt Compiler set as %s.', os.path.abspath(compiler))
Zhizhou Yange5986902017-08-10 17:37:53 -0700132
133
134def set_compiler_env(bench, compiler, build_os, llvm_prebuilts_version, cflags,
135 ldflags):
Zhizhou Yang62362922017-08-30 16:04:36 -0700136 logging.info('Setting compiler options for benchmark...')
Zhizhou Yange5986902017-08-10 17:37:53 -0700137
Zhizhou Yang62362922017-08-30 16:04:36 -0700138 # 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 Yange5986902017-08-10 17:37:53 -0700146
Zhizhou Yang62362922017-08-30 16:04:36 -0700147 set_flags(bench, cflags, ldflags)
Zhizhou Yange5986902017-08-10 17:37:53 -0700148
Zhizhou Yang62362922017-08-30 16:04:36 -0700149 return 0
Zhizhou Yange5986902017-08-10 17:37:53 -0700150
151
152def remove_tmp_dir():
Zhizhou Yang62362922017-08-30 16:04:36 -0700153 tmp_dir = os.path.join(config.android_home,
154 'prebuilts/clang/host/linux-x86',
155 'clang-tmp')
Zhizhou Yange5986902017-08-10 17:37:53 -0700156
Zhizhou Yang62362922017-08-30 16:04:36 -0700157 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 Yange5986902017-08-10 17:37:53 -0700163
164
165# Recover the makefile/blueprint from our patch after building
166def restore_makefile(bench):
Zhizhou Yang62362922017-08-30 16:04:36 -0700167 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 Yange5986902017-08-10 17:37:53 -0700172
173
174# Run script to build benchmark
175def build_bench(bench, source_dir):
Zhizhou Yang62362922017-08-30 16:04:36 -0700176 logging.info('Start building benchmark...')
Zhizhou Yange5986902017-08-10 17:37:53 -0700177
Zhizhou Yang62362922017-08-30 16:04:36 -0700178 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 Yange5986902017-08-10 17:37:53 -0700185
Zhizhou Yang62362922017-08-30 16:04:36 -0700186 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 Yange5986902017-08-10 17:37:53 -0700198
Zhizhou Yang62362922017-08-30 16:04:36 -0700199 logging.info('Logs for building benchmark %s are written to %s.',
200 bench, log_file)
201 logging.info('Benchmark built successfully!')
Zhizhou Yange5986902017-08-10 17:37:53 -0700202
203
204def main(argv):
Zhizhou Yang62362922017-08-30 16:04:36 -0700205 arguments = _parse_arguments_internal(argv)
Zhizhou Yange5986902017-08-10 17:37:53 -0700206
Zhizhou Yang62362922017-08-30 16:04:36 -0700207 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 Yange5986902017-08-10 17:37:53 -0700213
Zhizhou Yang62362922017-08-30 16:04:36 -0700214 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 Yange5986902017-08-10 17:37:53 -0700220
Zhizhou Yang62362922017-08-30 16:04:36 -0700221 set_compiler_env(bench, compiler, build_os, llvm_version, cflags, ldflags)
Zhizhou Yange5986902017-08-10 17:37:53 -0700222
Zhizhou Yang62362922017-08-30 16:04:36 -0700223 build_bench(bench, source_dir)
Zhizhou Yange5986902017-08-10 17:37:53 -0700224
Zhizhou Yang62362922017-08-30 16:04:36 -0700225 # If flags has been set, remember to restore the makefile/blueprint to
226 # original ones.
227 restore_makefile(bench)
Zhizhou Yange5986902017-08-10 17:37:53 -0700228
Zhizhou Yang62362922017-08-30 16:04:36 -0700229 # If a tmp directory is used for compiler path, remove it after building.
230 if compiler:
231 remove_tmp_dir()
Zhizhou Yange5986902017-08-10 17:37:53 -0700232
233
234if __name__ == '__main__':
Zhizhou Yang62362922017-08-30 16:04:36 -0700235 main(sys.argv[1:])