blob: c27a044796ca6dc5a0f502d5c5a57482197cccfa [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 """
Zach Reizner451dd3b2017-08-30 17:08:59 -0700119 return (
120 test_target_modules(
121 triple, is_release, env, TEST_MODULES_PARALLEL, True) and
122 test_target_modules(
123 triple, is_release, env, TEST_MODULES_SERIAL, False)
124 )
125
126
Zach Reizner5e4ab462017-09-22 14:19:15 -0700127def check_build(sysroot, triple, kind, test_it, clean):
128 """Runs relavent builds/tests for the given triple and configuration
129
130 Args:
131 sysroot: path to the target's sysroot directory.
132 triple: Target triple. Example: 'x86_64-unknown-linux-gnu'.
133 kind: 'debug' or 'release'.
134 test_it: True to test this triple and kind.
135 clean: True to skip cleaning the target path.
136 """
Zach Reizner451dd3b2017-08-30 17:08:59 -0700137 if not os.path.isdir(sysroot):
138 return 'sysroot missing'
139
140 target_path = get_target_path(triple, kind, test_it)
141
Zach Reizner5e4ab462017-09-22 14:19:15 -0700142 if clean:
Zach Reizner451dd3b2017-08-30 17:08:59 -0700143 shutil.rmtree(target_path, True)
144
145 is_release = kind == 'release'
146
147 env = os.environ.copy()
148 env['TARGET_CC'] = '%s-clang'%triple
149 env['SYSROOT'] = sysroot
150 env['CARGO_TARGET_DIR'] = target_path
151
152 if test_it:
153 if not test_target(triple, is_release, env):
154 return 'test error'
155 else:
156 if not build_target(triple, is_release, env):
157 return 'build error'
158
159 return 'pass'
160
161
162def get_stripped_size(triple):
Zach Reizner5e4ab462017-09-22 14:19:15 -0700163 """Returns the formatted size of the given triple's release binary.
164
165 Args:
166 triple: Target triple. Example: 'x86_64-unknown-linux-gnu'.
167 """
Zach Reizner451dd3b2017-08-30 17:08:59 -0700168 target_path = get_target_path(triple, 'release', False)
169 bin_path = os.path.join(target_path, triple, 'release', 'crosvm')
170 proc = subprocess.Popen(['%s-strip' % triple, bin_path])
171
172 if proc.wait() != 0:
173 return 'failed'
174
175 return '%dKiB' % (os.path.getsize(bin_path) / 1024)
176
177
Zach Reizner5e4ab462017-09-22 14:19:15 -0700178def get_parser():
179 """Gets the argument parser"""
180 parser = argparse.ArgumentParser(description=__doc__)
181 parser.add_argument('--arm-sysroot',
182 default='/build/arm-generic',
183 help='ARM sysroot directory (default=%(default)s)')
184 parser.add_argument('--aarch64-sysroot',
185 default='/build/arm64-generic',
186 help='AARCH64 sysroot directory (default=%(default)s)')
187 parser.add_argument('--x86_64-sysroot',
188 default='/build/amd64-generic',
189 help='x86_64 sysroot directory (default=%(default)s)')
190 parser.add_argument('--noclean', dest='clean', default=True,
191 action='store_false',
192 help='Keep the tempororary build directories.')
193 return parser
194
195
196def main(argv):
197 opts = get_parser().parse_args(argv)
198 build_test_cases = (
199 #(sysroot path, target triple, debug/release, should test?)
200 (opts.arm_sysroot, ARM_TRIPLE, "debug", False, opts.clean),
201 (opts.arm_sysroot, ARM_TRIPLE, "release", False, opts.clean),
202 (opts.aarch64_sysroot, AARCH64_TRIPLE, "debug", False, opts.clean),
203 (opts.aarch64_sysroot, AARCH64_TRIPLE, "release", False, opts.clean),
204 (opts.x86_64_sysroot, X86_64_TRIPLE, "debug", False, opts.clean),
205 (opts.x86_64_sysroot, X86_64_TRIPLE, "release", False, opts.clean),
206 (opts.x86_64_sysroot, X86_64_TRIPLE, "debug", True, opts.clean),
207 (opts.x86_64_sysroot, X86_64_TRIPLE, "release", True, opts.clean),
208 )
209
Zach Reizner451dd3b2017-08-30 17:08:59 -0700210 os.chdir(os.path.dirname(sys.argv[0]))
Zach Reizner5e4ab462017-09-22 14:19:15 -0700211 pool = multiprocessing.pool.Pool(len(build_test_cases))
212 results = pool.starmap(check_build, build_test_cases, 1)
Zach Reizner451dd3b2017-08-30 17:08:59 -0700213
214 print('---')
215 print('build test summary:')
Zach Reizner5e4ab462017-09-22 14:19:15 -0700216 for test_case, result in zip(build_test_cases, results):
217 _, triple, kind, test_it, _ = test_case
Zach Reizner451dd3b2017-08-30 17:08:59 -0700218 title = '%s_%s' % (triple.split('-')[0], kind)
219 if test_it:
220 title += "_test"
221
222 result_color = FAIL_COLOR
223 if result == 'pass':
224 result_color = PASS_COLOR
225
226 display_size = ''
227 if result == 'pass' and kind == 'release' and not test_it:
228 display_size = get_stripped_size(triple) + ' stripped binary'
229
230 print('%20s: %s%15s%s %s' %
231 (title, result_color, result, END_COLOR, display_size))
232
233
234if __name__ == '__main__':
Zach Reizner5e4ab462017-09-22 14:19:15 -0700235 sys.exit(main(sys.argv[1:]))