blob: 21d87df6060372e03966354ee079a16942caf6d8 [file] [log] [blame]
Zach Reizner451dd3b2017-08-30 17:08:59 -07001#!/usr/bin/env python3
Zach Reizner5e4ab462017-09-22 14:19:15 -07002# Copyright 2017 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
Zach Reizner451dd3b2017-08-30 17:08:59 -07005
6"""Builds crosvm in debug/release mode on all supported target architectures.
7
8A sysroot for each target architectures is required. The defaults are all
Zach Reizner5e4ab462017-09-22 14:19:15 -07009generic boards' sysroots, but they can be changed with the command line
10arguments.
Zach Reizner451dd3b2017-08-30 17:08:59 -070011
Zach Reizner5e4ab462017-09-22 14:19:15 -070012To test changes more quickly, set the --noclean option. This prevents the
13target directories from being removed before building and testing.
Zach Reizner451dd3b2017-08-30 17:08:59 -070014"""
15
16from __future__ import print_function
Zach Reizner5e4ab462017-09-22 14:19:15 -070017import argparse
Zach Reizner451dd3b2017-08-30 17:08:59 -070018import multiprocessing.pool
19import os
20import shutil
21import subprocess
22import sys
23
Yunlian Jiang610fa312018-09-24 15:55:41 -070024ARM_TRIPLE = os.getenv('ARM_TRIPLE', 'armv7a-cros-linux-gnueabihf')
Zach Reizner451dd3b2017-08-30 17:08:59 -070025AARCH64_TRIPLE = os.getenv('AARCH64_TRIPLE', 'aarch64-cros-linux-gnu')
26X86_64_TRIPLE = os.getenv('X86_64_TRIPLE', 'x86_64-cros-linux-gnu')
27
Zach Reizner451dd3b2017-08-30 17:08:59 -070028TEST_MODULES_PARALLEL = [
29 'crosvm',
30 'data_model',
31 'kernel_loader',
32 'kvm',
33 'kvm_sys',
34 'net_sys',
Jason D. Clintond7f03622017-09-04 21:32:36 -060035 'net_util',
Zach Reizner451dd3b2017-08-30 17:08:59 -070036 'syscall_defines',
Jason D. Clinton6f366b52017-09-07 20:51:07 -060037 'vhost',
Zach Reizner451dd3b2017-08-30 17:08:59 -070038 'virtio_sys',
39 'x86_64',
40]
41
Zach Reizner1f77a0d2017-09-04 15:59:08 -070042TEST_MODULES_SERIAL = [
43 'io_jail',
44 'sys_util',
Zach Reizner5e4ab462017-09-22 14:19:15 -070045]
Zach Reizner451dd3b2017-08-30 17:08:59 -070046
Zach Reizner5e4ab462017-09-22 14:19:15 -070047# Bright green.
Zach Reizner451dd3b2017-08-30 17:08:59 -070048PASS_COLOR = '\033[1;32m'
Zach Reizner5e4ab462017-09-22 14:19:15 -070049# Bright red.
Zach Reizner451dd3b2017-08-30 17:08:59 -070050FAIL_COLOR = '\033[1;31m'
Zach Reizner5e4ab462017-09-22 14:19:15 -070051# Default color.
Zach Reizner451dd3b2017-08-30 17:08:59 -070052END_COLOR = '\033[0m'
53
Zach Reizner5e4ab462017-09-22 14:19:15 -070054
Zach Reizner451dd3b2017-08-30 17:08:59 -070055def get_target_path(triple, kind, test_it):
Zach Reizner5e4ab462017-09-22 14:19:15 -070056 """Constructs a target path based on the configuration parameters.
57
58 Args:
59 triple: Target triple. Example: 'x86_64-unknown-linux-gnu'.
60 kind: 'debug' or 'release'.
61 test_it: If this target is tested.
62 """
Zach Reizner451dd3b2017-08-30 17:08:59 -070063 target_path = '/tmp/%s_%s' % (triple, kind)
64 if test_it:
65 target_path += '_test'
66 return target_path
67
68
69def build_target(triple, is_release, env):
Zach Reizner5e4ab462017-09-22 14:19:15 -070070 """Does a cargo build for the triple in release or debug mode.
71
72 Args:
73 triple: Target triple. Example: 'x86_64-unknown-linux-gnu'.
74 is_release: True to build a release version.
75 env: Enviroment variables to run cargo with.
76 """
Zach Reizner451dd3b2017-08-30 17:08:59 -070077 args = ['cargo', 'build', '--target=%s' % triple]
78
79 if is_release:
80 args.append('--release')
81
82 return subprocess.Popen(args, env=env).wait() == 0
83
Zach Reizner5e4ab462017-09-22 14:19:15 -070084
Zach Reizner451dd3b2017-08-30 17:08:59 -070085def test_target_modules(triple, is_release, env, modules, parallel):
Zach Reizner5e4ab462017-09-22 14:19:15 -070086 """Does a cargo test on given modules for the triple and configuration.
87
88 Args:
89 triple: Target triple. Example: 'x86_64-unknown-linux-gnu'.
90 is_release: True to build a release version.
91 env: Enviroment variables to run cargo with.
92 modules: List of module strings to test.
93 parallel: True to run the tests in parallel threads.
94 """
Zach Reizner451dd3b2017-08-30 17:08:59 -070095 args = ['cargo', 'test', '--target=%s' % triple]
96
97 if is_release:
98 args.append('--release')
99
Zach Reizner451dd3b2017-08-30 17:08:59 -0700100 for mod in modules:
101 args.append('-p')
102 args.append(mod)
103
Zach Reiznerad984522017-10-31 21:57:37 -0700104 if not parallel:
105 args.append('--')
106 args.append('--test-threads=1')
107
Zach Reizner451dd3b2017-08-30 17:08:59 -0700108 return subprocess.Popen(args, env=env).wait() == 0
109
110
111def test_target(triple, is_release, env):
Zach Reizner5e4ab462017-09-22 14:19:15 -0700112 """Does a cargo test for the given triple and configuration.
113
114 Args:
115 triple: Target triple. Example: 'x86_64-unknown-linux-gnu'.
116 is_release: True to build a release version.
117 env: Enviroment variables to run cargo with.
118 """
Jianxun Zhang1bc4a062019-02-25 22:12:26 -0800119
120 parallel_result = test_target_modules(
121 triple, is_release, env, TEST_MODULES_PARALLEL, True)
122
123 serial_result = test_target_modules(
124 triple, is_release, env, TEST_MODULES_SERIAL, False)
125
126 return parallel_result and serial_result
Zach Reizner451dd3b2017-08-30 17:08:59 -0700127
128
Zach Reizner5e4ab462017-09-22 14:19:15 -0700129def check_build(sysroot, triple, kind, test_it, clean):
130 """Runs relavent builds/tests for the given triple and configuration
131
132 Args:
133 sysroot: path to the target's sysroot directory.
134 triple: Target triple. Example: 'x86_64-unknown-linux-gnu'.
135 kind: 'debug' or 'release'.
136 test_it: True to test this triple and kind.
137 clean: True to skip cleaning the target path.
138 """
Zach Reizner451dd3b2017-08-30 17:08:59 -0700139 if not os.path.isdir(sysroot):
140 return 'sysroot missing'
141
142 target_path = get_target_path(triple, kind, test_it)
143
Zach Reizner5e4ab462017-09-22 14:19:15 -0700144 if clean:
Zach Reizner451dd3b2017-08-30 17:08:59 -0700145 shutil.rmtree(target_path, True)
146
147 is_release = kind == 'release'
148
149 env = os.environ.copy()
150 env['TARGET_CC'] = '%s-clang'%triple
151 env['SYSROOT'] = sysroot
152 env['CARGO_TARGET_DIR'] = target_path
153
154 if test_it:
155 if not test_target(triple, is_release, env):
156 return 'test error'
157 else:
158 if not build_target(triple, is_release, env):
159 return 'build error'
160
161 return 'pass'
162
163
164def get_stripped_size(triple):
Zach Reizner5e4ab462017-09-22 14:19:15 -0700165 """Returns the formatted size of the given triple's release binary.
166
167 Args:
168 triple: Target triple. Example: 'x86_64-unknown-linux-gnu'.
169 """
Zach Reizner451dd3b2017-08-30 17:08:59 -0700170 target_path = get_target_path(triple, 'release', False)
171 bin_path = os.path.join(target_path, triple, 'release', 'crosvm')
172 proc = subprocess.Popen(['%s-strip' % triple, bin_path])
173
174 if proc.wait() != 0:
175 return 'failed'
176
177 return '%dKiB' % (os.path.getsize(bin_path) / 1024)
178
179
Zach Reizner5e4ab462017-09-22 14:19:15 -0700180def get_parser():
181 """Gets the argument parser"""
182 parser = argparse.ArgumentParser(description=__doc__)
183 parser.add_argument('--arm-sysroot',
184 default='/build/arm-generic',
185 help='ARM sysroot directory (default=%(default)s)')
186 parser.add_argument('--aarch64-sysroot',
187 default='/build/arm64-generic',
188 help='AARCH64 sysroot directory (default=%(default)s)')
189 parser.add_argument('--x86_64-sysroot',
190 default='/build/amd64-generic',
191 help='x86_64 sysroot directory (default=%(default)s)')
192 parser.add_argument('--noclean', dest='clean', default=True,
193 action='store_false',
194 help='Keep the tempororary build directories.')
195 return parser
196
197
198def main(argv):
199 opts = get_parser().parse_args(argv)
200 build_test_cases = (
201 #(sysroot path, target triple, debug/release, should test?)
202 (opts.arm_sysroot, ARM_TRIPLE, "debug", False, opts.clean),
203 (opts.arm_sysroot, ARM_TRIPLE, "release", False, opts.clean),
204 (opts.aarch64_sysroot, AARCH64_TRIPLE, "debug", False, opts.clean),
205 (opts.aarch64_sysroot, AARCH64_TRIPLE, "release", False, opts.clean),
206 (opts.x86_64_sysroot, X86_64_TRIPLE, "debug", False, opts.clean),
207 (opts.x86_64_sysroot, X86_64_TRIPLE, "release", False, opts.clean),
208 (opts.x86_64_sysroot, X86_64_TRIPLE, "debug", True, opts.clean),
209 (opts.x86_64_sysroot, X86_64_TRIPLE, "release", True, opts.clean),
210 )
211
Zach Reizner451dd3b2017-08-30 17:08:59 -0700212 os.chdir(os.path.dirname(sys.argv[0]))
Zach Reizner5e4ab462017-09-22 14:19:15 -0700213 pool = multiprocessing.pool.Pool(len(build_test_cases))
214 results = pool.starmap(check_build, build_test_cases, 1)
Zach Reizner451dd3b2017-08-30 17:08:59 -0700215
216 print('---')
217 print('build test summary:')
Zach Reizner5e4ab462017-09-22 14:19:15 -0700218 for test_case, result in zip(build_test_cases, results):
219 _, triple, kind, test_it, _ = test_case
Zach Reizner451dd3b2017-08-30 17:08:59 -0700220 title = '%s_%s' % (triple.split('-')[0], kind)
221 if test_it:
222 title += "_test"
223
224 result_color = FAIL_COLOR
225 if result == 'pass':
226 result_color = PASS_COLOR
227
228 display_size = ''
229 if result == 'pass' and kind == 'release' and not test_it:
230 display_size = get_stripped_size(triple) + ' stripped binary'
231
232 print('%20s: %s%15s%s %s' %
233 (title, result_color, result, END_COLOR, display_size))
234
235
236if __name__ == '__main__':
Zach Reizner5e4ab462017-09-22 14:19:15 -0700237 sys.exit(main(sys.argv[1:]))