From 451dd3bdabaae658346a6f5fa247f3f69da19322 Mon Sep 17 00:00:00 2001 From: Zach Reizner Date: Wed, 30 Aug 2017 17:08:59 -0700 Subject: [PATCH] add build_test script to automate crosvm test running TEST=./build_test && cros lint build_test.py BUG=None Change-Id: I11de92ab1c854264b762c3bb2e3ebda9d3f4b007 Reviewed-on: https://chromium-review.googlesource.com/644409 Commit-Ready: Zach Reizner Tested-by: Zach Reizner Reviewed-by: Zach Reizner --- build_test | 1 + build_test.py | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 120000 build_test create mode 100755 build_test.py diff --git a/build_test b/build_test new file mode 120000 index 0000000000..a864fcf7a6 --- /dev/null +++ b/build_test @@ -0,0 +1 @@ +build_test.py \ No newline at end of file diff --git a/build_test.py b/build_test.py new file mode 100755 index 0000000000..4064db1496 --- /dev/null +++ b/build_test.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 + +"""Builds crosvm in debug/release mode on all supported target architectures. + +A sysroot for each target architectures is required. The defaults are all +generic boards' sysroots, but they can be changed with the ARM_SYSROOT, +AARCH64_SYSROOT, X86_64_SYSROOT environment variables. + +To test changes more quickly, set the NOCLEAN environment variable. This +prevents the target directories from being removed before building and testing. +""" + +from __future__ import print_function +import multiprocessing.pool +import os +import shutil +import subprocess +import sys + +NOCLEAN = os.getenv('NOCLEAN') is not None + +ARM_TRIPLE = os.getenv('ARM_TRIPLE', 'armv7a-cros-linux-gnueabi') +AARCH64_TRIPLE = os.getenv('AARCH64_TRIPLE', 'aarch64-cros-linux-gnu') +X86_64_TRIPLE = os.getenv('X86_64_TRIPLE', 'x86_64-cros-linux-gnu') + +ARM_SYSROOT = os.getenv('ARM_SYSROOT', '/build/arm-generic') +AARCH64_SYSROOT = os.getenv('AARCH64_SYSROOT', '/build/arm64-generic') +X86_64_SYSROOT = os.getenv('X86_64_SYSROOT', '/build/amd64-generic') + +BUILD_TEST_CASES = [ + #(sysroot path, target triple, debug/release, should test?) + (ARM_SYSROOT, ARM_TRIPLE, "debug", False), + (ARM_SYSROOT, ARM_TRIPLE, "release", False), + (AARCH64_SYSROOT, AARCH64_TRIPLE, "debug", False), + (AARCH64_SYSROOT, AARCH64_TRIPLE, "release", False), + (X86_64_SYSROOT, X86_64_TRIPLE, "debug", False), + (X86_64_SYSROOT, X86_64_TRIPLE, "release", False), + (X86_64_SYSROOT, X86_64_TRIPLE, "debug", True), + (X86_64_SYSROOT, X86_64_TRIPLE, "release", True), +] + +TEST_MODULES_PARALLEL = [ + 'crosvm', + 'data_model', + 'kernel_loader', + 'kvm', + 'kvm_sys', + 'net_sys', + 'sys_util', + 'syscall_defines', + 'virtio_sys', + 'x86_64', +] + +TEST_MODULES_SERIAL = ['io_jail'] + +# Bright green +PASS_COLOR = '\033[1;32m' +# Bright red +FAIL_COLOR = '\033[1;31m' +# Default color +END_COLOR = '\033[0m' + +def get_target_path(triple, kind, test_it): + target_path = '/tmp/%s_%s' % (triple, kind) + if test_it: + target_path += '_test' + return target_path + + +def build_target(triple, is_release, env): + args = ['cargo', 'build', '--target=%s' % triple] + + if is_release: + args.append('--release') + + return subprocess.Popen(args, env=env).wait() == 0 + +def test_target_modules(triple, is_release, env, modules, parallel): + args = ['cargo', 'test', '--target=%s' % triple] + + if is_release: + args.append('--release') + + if not parallel: + env = env.copy() + env['RUST_TEST_THREADS'] = '1' + + for mod in modules: + args.append('-p') + args.append(mod) + + return subprocess.Popen(args, env=env).wait() == 0 + + +def test_target(triple, is_release, env): + return ( + test_target_modules( + triple, is_release, env, TEST_MODULES_PARALLEL, True) and + test_target_modules( + triple, is_release, env, TEST_MODULES_SERIAL, False) + ) + + +def check_build(sysroot, triple, kind, test_it): + if not os.path.isdir(sysroot): + return 'sysroot missing' + + target_path = get_target_path(triple, kind, test_it) + + if not NOCLEAN: + shutil.rmtree(target_path, True) + + is_release = kind == 'release' + + env = os.environ.copy() + env['TARGET_CC'] = '%s-clang'%triple + env['SYSROOT'] = sysroot + env['CARGO_TARGET_DIR'] = target_path + + if test_it: + if not test_target(triple, is_release, env): + return 'test error' + else: + if not build_target(triple, is_release, env): + return 'build error' + + return 'pass' + + +def get_stripped_size(triple): + target_path = get_target_path(triple, 'release', False) + bin_path = os.path.join(target_path, triple, 'release', 'crosvm') + proc = subprocess.Popen(['%s-strip' % triple, bin_path]) + + if proc.wait() != 0: + return 'failed' + + return '%dKiB' % (os.path.getsize(bin_path) / 1024) + + +def main(): + os.chdir(os.path.dirname(sys.argv[0])) + pool = multiprocessing.pool.Pool() + results = pool.starmap(check_build, BUILD_TEST_CASES, 1) + + print('---') + print('build test summary:') + for test_case, result in zip(BUILD_TEST_CASES, results): + _, triple, kind, test_it = test_case + title = '%s_%s' % (triple.split('-')[0], kind) + if test_it: + title += "_test" + + result_color = FAIL_COLOR + if result == 'pass': + result_color = PASS_COLOR + + display_size = '' + if result == 'pass' and kind == 'release' and not test_it: + display_size = get_stripped_size(triple) + ' stripped binary' + + print('%20s: %s%15s%s %s' % + (title, result_color, result, END_COLOR, display_size)) + + +if __name__ == '__main__': + main()