1#!/usr/bin/env vpython3 2 3# Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 4# 5# Use of this source code is governed by a BSD-style license 6# that can be found in the LICENSE file in the root of the source 7# tree. An additional intellectual property rights grant can be found 8# in the file PATENTS. All contributing project authors may 9# be found in the AUTHORS file in the root of the source tree. 10 11"""MB - the Meta-Build wrapper around GN. 12 13MB is a wrapper script for GN that can be used to generate build files 14for sets of canned configurations and analyze them. 15""" 16 17import os 18import sys 19 20_SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) 21_SRC_DIR = os.path.dirname(os.path.dirname(_SCRIPT_DIR)) 22sys.path.insert(0, _SRC_DIR) 23 24from tools.mb import mb 25 26 27def _GetExecutable(target, platform): 28 executable_prefix = '.\\' if platform == 'win32' else './' 29 executable_suffix = '.exe' if platform == 'win32' else '' 30 return executable_prefix + target + executable_suffix 31 32 33def main(args): 34 mbw = WebRTCMetaBuildWrapper() 35 return mbw.Main(args) 36 37 38class WebRTCMetaBuildWrapper(mb.MetaBuildWrapper): 39 def __init__(self): 40 super().__init__() 41 # Make sure default_config and default_isolate_map are attributes of the 42 # parent class before changing their values. 43 # pylint: disable=access-member-before-definition 44 assert self.default_config 45 assert self.default_isolate_map 46 self.default_config = os.path.join(_SCRIPT_DIR, 'mb_config.pyl') 47 self.default_isolate_map = os.path.join(_SRC_DIR, 'infra', 'specs', 48 'gn_isolate_map.pyl') 49 50 def GetSwarmingCommand(self, target, vals): 51 isolate_map = self.ReadIsolateMap() 52 test_type = isolate_map[target]['type'] 53 54 is_android = 'target_os="android"' in vals['gn_args'] 55 is_fuchsia = 'target_os="fuchsia"' in vals['gn_args'] 56 is_ios = 'target_os="ios"' in vals['gn_args'] 57 is_linux = self.platform.startswith('linux') and not is_android 58 is_win = self.platform.startswith('win') 59 60 if test_type == 'nontest': 61 self.WriteFailureAndRaise('We should not be isolating %s.' % target, 62 output_path=None) 63 if test_type not in ('console_test_launcher', 'windowed_test_launcher', 64 'non_parallel_console_test_launcher', 'raw', 65 'additional_compile_target', 'junit_test', 'script'): 66 self.WriteFailureAndRaise('No command line for ' 67 '%s found (test type %s).' % 68 (target, test_type), 69 output_path=None) 70 71 cmdline = [] 72 extra_files = [ 73 '../../.vpython3', 74 '../../testing/test_env.py', 75 ] 76 vpython_exe = 'vpython3' 77 78 if isolate_map[target].get('script'): 79 cmdline += [ 80 vpython_exe, 81 '../../' + self.ToSrcRelPath(isolate_map[target]['script']) 82 ] 83 elif is_android: 84 cmdline += [ 85 'luci-auth', 'context', '--', vpython_exe, 86 '../../build/android/test_wrapper/logdog_wrapper.py', '--target', 87 target, '--logdog-bin-cmd', 88 '../../.task_template_packages/logdog_butler', '--logcat-output-file', 89 '${ISOLATED_OUTDIR}/logcats', '--store-tombstones' 90 ] 91 elif is_ios or is_fuchsia or test_type == 'raw': 92 if is_win: 93 cmdline += ['bin\\run_{}.bat'.format(target)] 94 else: 95 cmdline += ['bin/run_{}'.format(target)] 96 else: 97 if isolate_map[target].get('use_webcam', False): 98 cmdline += [ 99 vpython_exe, '../../tools_webrtc/ensure_webcam_is_running.py' 100 ] 101 extra_files.append('../../tools_webrtc/ensure_webcam_is_running.py') 102 if isolate_map[target].get('use_pipewire', False): 103 cmdline += [vpython_exe, '../../tools_webrtc/configure_pipewire.py'] 104 extra_files.append('../../tools_webrtc/configure_pipewire.py') 105 106 # is_linux uses use_ozone and x11 by default. 107 use_x11 = is_linux 108 109 xvfb = use_x11 and test_type == 'windowed_test_launcher' 110 if xvfb: 111 cmdline += [vpython_exe, '../../testing/xvfb.py'] 112 extra_files.append('../../testing/xvfb.py') 113 else: 114 cmdline += [vpython_exe, '../../testing/test_env.py'] 115 116 extra_files += [ 117 '../../third_party/gtest-parallel/gtest-parallel', 118 '../../third_party/gtest-parallel/gtest_parallel.py', 119 '../../tools_webrtc/gtest-parallel-wrapper.py', 120 ] 121 output_dir = '${ISOLATED_OUTDIR}/test_logs' 122 timeout = isolate_map[target].get('timeout', 900) 123 cmdline += [ 124 '../../tools_webrtc/gtest-parallel-wrapper.py', 125 '--output_dir=%s' % output_dir, 126 '--gtest_color=no', 127 # We tell gtest-parallel to interrupt the test after 900 128 # seconds, so it can exit cleanly and report results, 129 # instead of being interrupted by swarming and not 130 # reporting anything. 131 '--timeout=%s' % timeout, 132 ] 133 if test_type == 'non_parallel_console_test_launcher': 134 # Still use the gtest-parallel-wrapper.py script since we 135 # need it to run tests on swarming, but don't execute tests 136 # in parallel. 137 cmdline.append('--workers=1') 138 139 asan = 'is_asan=true' in vals['gn_args'] 140 lsan = 'is_lsan=true' in vals['gn_args'] 141 msan = 'is_msan=true' in vals['gn_args'] 142 tsan = 'is_tsan=true' in vals['gn_args'] 143 sanitizer = asan or lsan or msan or tsan 144 if not sanitizer: 145 # Retry would hide most sanitizers detections. 146 cmdline.append('--retry_failed=3') 147 148 cmdline.append(_GetExecutable(target, self.platform)) 149 150 cmdline.extend([ 151 '--asan=%d' % asan, 152 '--lsan=%d' % lsan, 153 '--msan=%d' % msan, 154 '--tsan=%d' % tsan, 155 ]) 156 157 cmdline += isolate_map[target].get('args', []) 158 159 return cmdline, extra_files 160 161if __name__ == '__main__': 162 sys.exit(main(sys.argv[1:])) 163