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