1*58b9f456SAndroid Build Coastguard Worker#!/usr/bin/env python 2*58b9f456SAndroid Build Coastguard Worker# 3*58b9f456SAndroid Build Coastguard Worker# Copyright (C) 2015 The Android Open Source Project 4*58b9f456SAndroid Build Coastguard Worker# 5*58b9f456SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*58b9f456SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*58b9f456SAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*58b9f456SAndroid Build Coastguard Worker# 9*58b9f456SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*58b9f456SAndroid Build Coastguard Worker# 11*58b9f456SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*58b9f456SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*58b9f456SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*58b9f456SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*58b9f456SAndroid Build Coastguard Worker# limitations under the License. 16*58b9f456SAndroid Build Coastguard Worker# 17*58b9f456SAndroid Build Coastguard Worker"""Runs the libc++ tests against the platform libc++.""" 18*58b9f456SAndroid Build Coastguard Workerfrom __future__ import print_function 19*58b9f456SAndroid Build Coastguard Worker 20*58b9f456SAndroid Build Coastguard Workerimport argparse 21*58b9f456SAndroid Build Coastguard Workerimport logging 22*58b9f456SAndroid Build Coastguard Workerimport os 23*58b9f456SAndroid Build Coastguard Workerimport posixpath 24*58b9f456SAndroid Build Coastguard Workerimport sys 25*58b9f456SAndroid Build Coastguard Worker 26*58b9f456SAndroid Build Coastguard WorkerTHIS_DIR = os.path.dirname(os.path.realpath(__file__)) 27*58b9f456SAndroid Build Coastguard WorkerANDROID_DIR = os.path.realpath(os.path.join(THIS_DIR, '../..')) 28*58b9f456SAndroid Build Coastguard Worker 29*58b9f456SAndroid Build Coastguard Worker 30*58b9f456SAndroid Build Coastguard Workerdef logger(): 31*58b9f456SAndroid Build Coastguard Worker """Returns the logger for the module.""" 32*58b9f456SAndroid Build Coastguard Worker return logging.getLogger(__name__) 33*58b9f456SAndroid Build Coastguard Worker 34*58b9f456SAndroid Build Coastguard Worker 35*58b9f456SAndroid Build Coastguard Workerdef call(cmd, *args, **kwargs): 36*58b9f456SAndroid Build Coastguard Worker """subprocess.call with logging.""" 37*58b9f456SAndroid Build Coastguard Worker import subprocess 38*58b9f456SAndroid Build Coastguard Worker logger().info('call %s', ' '.join(cmd)) 39*58b9f456SAndroid Build Coastguard Worker return subprocess.call(cmd, *args, **kwargs) 40*58b9f456SAndroid Build Coastguard Worker 41*58b9f456SAndroid Build Coastguard Worker 42*58b9f456SAndroid Build Coastguard Workerdef check_call(cmd, *args, **kwargs): 43*58b9f456SAndroid Build Coastguard Worker """subprocess.check_call with logging.""" 44*58b9f456SAndroid Build Coastguard Worker import subprocess 45*58b9f456SAndroid Build Coastguard Worker logger().info('check_call %s', ' '.join(cmd)) 46*58b9f456SAndroid Build Coastguard Worker return subprocess.check_call(cmd, *args, **kwargs) 47*58b9f456SAndroid Build Coastguard Worker 48*58b9f456SAndroid Build Coastguard Worker 49*58b9f456SAndroid Build Coastguard Workerdef check_output(cmd, *args, **kwargs): 50*58b9f456SAndroid Build Coastguard Worker """subprocess.check_output with logging.""" 51*58b9f456SAndroid Build Coastguard Worker import subprocess 52*58b9f456SAndroid Build Coastguard Worker logger().info('check_output %s', ' '.join(cmd)) 53*58b9f456SAndroid Build Coastguard Worker return subprocess.check_output(cmd, *args, **kwargs) 54*58b9f456SAndroid Build Coastguard Worker 55*58b9f456SAndroid Build Coastguard Worker 56*58b9f456SAndroid Build Coastguard Workerclass ArgParser(argparse.ArgumentParser): 57*58b9f456SAndroid Build Coastguard Worker """Parses command line arguments.""" 58*58b9f456SAndroid Build Coastguard Worker 59*58b9f456SAndroid Build Coastguard Worker def __init__(self): 60*58b9f456SAndroid Build Coastguard Worker super(ArgParser, self).__init__() 61*58b9f456SAndroid Build Coastguard Worker self.add_argument('--bitness', choices=(32, 64), type=int, default=32) 62*58b9f456SAndroid Build Coastguard Worker self.add_argument('--host', action='store_true') 63*58b9f456SAndroid Build Coastguard Worker 64*58b9f456SAndroid Build Coastguard Worker 65*58b9f456SAndroid Build Coastguard Workerdef extract_build_cmds(commands, exe_name): 66*58b9f456SAndroid Build Coastguard Worker """Extracts build command information from `ninja -t commands` output. 67*58b9f456SAndroid Build Coastguard Worker 68*58b9f456SAndroid Build Coastguard Worker Args: 69*58b9f456SAndroid Build Coastguard Worker commands: String containing the output of `ninja -t commands` for the 70*58b9f456SAndroid Build Coastguard Worker libcxx_test_template. 71*58b9f456SAndroid Build Coastguard Worker exe_name: The basename of the built executable. 72*58b9f456SAndroid Build Coastguard Worker 73*58b9f456SAndroid Build Coastguard Worker Returns: 74*58b9f456SAndroid Build Coastguard Worker Tuple of (compiler, compiler_flags, linker_flags). 75*58b9f456SAndroid Build Coastguard Worker """ 76*58b9f456SAndroid Build Coastguard Worker cc = None 77*58b9f456SAndroid Build Coastguard Worker cflags = None 78*58b9f456SAndroid Build Coastguard Worker ldflags = None 79*58b9f456SAndroid Build Coastguard Worker template_name = 'external/libcxx/libcxx_test_template.cpp' 80*58b9f456SAndroid Build Coastguard Worker 81*58b9f456SAndroid Build Coastguard Worker for cmd in commands.splitlines(): 82*58b9f456SAndroid Build Coastguard Worker cmd_args = cmd.split() 83*58b9f456SAndroid Build Coastguard Worker if cc is None and template_name in cmd_args: 84*58b9f456SAndroid Build Coastguard Worker for i, arg in enumerate(cmd_args): 85*58b9f456SAndroid Build Coastguard Worker if arg == '-o': 86*58b9f456SAndroid Build Coastguard Worker cmd_args[i + 1] = '%OUT%' 87*58b9f456SAndroid Build Coastguard Worker elif arg == template_name: 88*58b9f456SAndroid Build Coastguard Worker cmd_args[i] = '%SOURCE%' 89*58b9f456SAndroid Build Coastguard Worker # Drop dependency tracking args since they can cause file 90*58b9f456SAndroid Build Coastguard Worker # not found errors at test time. 91*58b9f456SAndroid Build Coastguard Worker if arg == '-MD': 92*58b9f456SAndroid Build Coastguard Worker cmd_args[i] = '' 93*58b9f456SAndroid Build Coastguard Worker if arg == '-MF': 94*58b9f456SAndroid Build Coastguard Worker cmd_args[i] = '' 95*58b9f456SAndroid Build Coastguard Worker cmd_args[i + 1] = '' 96*58b9f456SAndroid Build Coastguard Worker if cmd_args[0] == 'PWD=/proc/self/cwd': 97*58b9f456SAndroid Build Coastguard Worker cmd_args = cmd_args[1:] 98*58b9f456SAndroid Build Coastguard Worker if cmd_args[0].endswith('gomacc'): 99*58b9f456SAndroid Build Coastguard Worker cmd_args = cmd_args[1:] 100*58b9f456SAndroid Build Coastguard Worker cc = cmd_args[0] 101*58b9f456SAndroid Build Coastguard Worker cflags = cmd_args[1:] 102*58b9f456SAndroid Build Coastguard Worker if ldflags is None: 103*58b9f456SAndroid Build Coastguard Worker is_ld = False 104*58b9f456SAndroid Build Coastguard Worker for i, arg in enumerate(cmd_args): 105*58b9f456SAndroid Build Coastguard Worker # Here we assume that the rspfile contains the path to the 106*58b9f456SAndroid Build Coastguard Worker # object file and nothing else. 107*58b9f456SAndroid Build Coastguard Worker if arg.startswith('@'): 108*58b9f456SAndroid Build Coastguard Worker cmd_args[i] = '%SOURCE%' 109*58b9f456SAndroid Build Coastguard Worker if arg == '-o' and cmd_args[i + 1].endswith(exe_name): 110*58b9f456SAndroid Build Coastguard Worker cmd_args[i + 1] = '%OUT%' 111*58b9f456SAndroid Build Coastguard Worker is_ld = True 112*58b9f456SAndroid Build Coastguard Worker if is_ld: 113*58b9f456SAndroid Build Coastguard Worker ldflags = cmd_args[1:] 114*58b9f456SAndroid Build Coastguard Worker 115*58b9f456SAndroid Build Coastguard Worker return cc, cflags, ldflags 116*58b9f456SAndroid Build Coastguard Worker 117*58b9f456SAndroid Build Coastguard Worker 118*58b9f456SAndroid Build Coastguard Workerdef get_build_cmds(bitness, host): 119*58b9f456SAndroid Build Coastguard Worker """Use ninja -t commands to find the build commands for an executable.""" 120*58b9f456SAndroid Build Coastguard Worker out_dir = os.getenv('OUT_DIR', os.path.join(ANDROID_DIR, 'out')) 121*58b9f456SAndroid Build Coastguard Worker product_out = os.getenv('ANDROID_PRODUCT_OUT') 122*58b9f456SAndroid Build Coastguard Worker 123*58b9f456SAndroid Build Coastguard Worker if host: 124*58b9f456SAndroid Build Coastguard Worker rel_out_dir = os.path.relpath( 125*58b9f456SAndroid Build Coastguard Worker os.path.join(out_dir, 'soong/host/linux-x86/bin'), ANDROID_DIR) 126*58b9f456SAndroid Build Coastguard Worker target = os.path.join(rel_out_dir, 'libcxx_test_template64') 127*58b9f456SAndroid Build Coastguard Worker else: 128*58b9f456SAndroid Build Coastguard Worker exe_name = 'libcxx_test_template' + str(bitness) 129*58b9f456SAndroid Build Coastguard Worker rel_out_dir = os.path.relpath(product_out, ANDROID_DIR) 130*58b9f456SAndroid Build Coastguard Worker target = os.path.join(rel_out_dir, 'system/bin', exe_name) 131*58b9f456SAndroid Build Coastguard Worker 132*58b9f456SAndroid Build Coastguard Worker # Generate $OUT_DIR/combined-$TARGET_PRODUCT.ninja and build the 133*58b9f456SAndroid Build Coastguard Worker # template target's dependencies. 134*58b9f456SAndroid Build Coastguard Worker check_call([ 135*58b9f456SAndroid Build Coastguard Worker 'bash', 136*58b9f456SAndroid Build Coastguard Worker os.path.join(ANDROID_DIR, 'build/soong/soong_ui.bash'), '--make-mode', 137*58b9f456SAndroid Build Coastguard Worker target 138*58b9f456SAndroid Build Coastguard Worker ]) 139*58b9f456SAndroid Build Coastguard Worker 140*58b9f456SAndroid Build Coastguard Worker ninja_path = os.path.join( 141*58b9f456SAndroid Build Coastguard Worker out_dir, 'combined-' + os.getenv('TARGET_PRODUCT') + '.ninja') 142*58b9f456SAndroid Build Coastguard Worker commands = check_output([ 143*58b9f456SAndroid Build Coastguard Worker os.path.join(ANDROID_DIR, 'prebuilts/build-tools/linux-x86/bin/ninja'), 144*58b9f456SAndroid Build Coastguard Worker '-C', ANDROID_DIR, '-f', ninja_path, '-t', 'commands', target 145*58b9f456SAndroid Build Coastguard Worker ]) 146*58b9f456SAndroid Build Coastguard Worker 147*58b9f456SAndroid Build Coastguard Worker return extract_build_cmds(commands, os.path.basename(target)) 148*58b9f456SAndroid Build Coastguard Worker 149*58b9f456SAndroid Build Coastguard Worker 150*58b9f456SAndroid Build Coastguard Workerdef setup_test_directory(): 151*58b9f456SAndroid Build Coastguard Worker """Prepares a device test directory for use by the shell user.""" 152*58b9f456SAndroid Build Coastguard Worker stdfs_test_data = os.path.join( 153*58b9f456SAndroid Build Coastguard Worker THIS_DIR, 'test/std/input.output/filesystems/Inputs/static_test_env') 154*58b9f456SAndroid Build Coastguard Worker device_dir = '/data/local/tmp/libcxx' 155*58b9f456SAndroid Build Coastguard Worker dynamic_dir = posixpath.join(device_dir, 'dynamic_test_env') 156*58b9f456SAndroid Build Coastguard Worker check_call(['adb', 'shell', 'rm', '-rf', device_dir]) 157*58b9f456SAndroid Build Coastguard Worker check_call(['adb', 'shell', 'mkdir', '-p', device_dir]) 158*58b9f456SAndroid Build Coastguard Worker check_call(['adb', 'shell', 'mkdir', '-p', dynamic_dir]) 159*58b9f456SAndroid Build Coastguard Worker check_call(['adb', 'push', '--sync', stdfs_test_data, device_dir]) 160*58b9f456SAndroid Build Coastguard Worker check_call(['adb', 'shell', 'chown', '-R', 'shell:shell', device_dir]) 161*58b9f456SAndroid Build Coastguard Worker 162*58b9f456SAndroid Build Coastguard Worker 163*58b9f456SAndroid Build Coastguard Workerdef main(): 164*58b9f456SAndroid Build Coastguard Worker """Program entry point.""" 165*58b9f456SAndroid Build Coastguard Worker logging.basicConfig(level=logging.INFO) 166*58b9f456SAndroid Build Coastguard Worker 167*58b9f456SAndroid Build Coastguard Worker args, lit_args = ArgParser().parse_known_args() 168*58b9f456SAndroid Build Coastguard Worker lit_path = os.path.join(ANDROID_DIR, 'external/llvm/utils/lit/lit.py') 169*58b9f456SAndroid Build Coastguard Worker cc, cflags, ldflags = get_build_cmds(args.bitness, args.host) 170*58b9f456SAndroid Build Coastguard Worker 171*58b9f456SAndroid Build Coastguard Worker mode_str = 'host' if args.host else 'device' 172*58b9f456SAndroid Build Coastguard Worker android_mode_arg = '--param=android_mode=' + mode_str 173*58b9f456SAndroid Build Coastguard Worker cxx_under_test_arg = '--param=cxx_under_test=' + cc 174*58b9f456SAndroid Build Coastguard Worker cxx_template_arg = '--param=cxx_template=' + ' '.join(cflags) 175*58b9f456SAndroid Build Coastguard Worker link_template_arg = '--param=link_template=' + ' '.join(ldflags) 176*58b9f456SAndroid Build Coastguard Worker site_cfg_path = os.path.join(THIS_DIR, 'test/lit.site.cfg') 177*58b9f456SAndroid Build Coastguard Worker libcxx_site_cfg_arg = '--param=libcxx_site_config=' + site_cfg_path 178*58b9f456SAndroid Build Coastguard Worker libcxxabi_site_cfg_arg = '--param=libcxxabi_site_config=' + site_cfg_path 179*58b9f456SAndroid Build Coastguard Worker default_test_paths = [ 180*58b9f456SAndroid Build Coastguard Worker os.path.join(THIS_DIR, 'test'), 181*58b9f456SAndroid Build Coastguard Worker os.path.join(ANDROID_DIR, 'external/libcxxabi/test') 182*58b9f456SAndroid Build Coastguard Worker ] 183*58b9f456SAndroid Build Coastguard Worker 184*58b9f456SAndroid Build Coastguard Worker have_filter_args = False 185*58b9f456SAndroid Build Coastguard Worker for arg in lit_args: 186*58b9f456SAndroid Build Coastguard Worker # If the argument is a valid path with default_test_paths, it is a test 187*58b9f456SAndroid Build Coastguard Worker # filter. 188*58b9f456SAndroid Build Coastguard Worker real_path = os.path.realpath(arg) 189*58b9f456SAndroid Build Coastguard Worker if not any(real_path.startswith(path) for path in default_test_paths): 190*58b9f456SAndroid Build Coastguard Worker continue 191*58b9f456SAndroid Build Coastguard Worker if not os.path.exists(real_path): 192*58b9f456SAndroid Build Coastguard Worker continue 193*58b9f456SAndroid Build Coastguard Worker 194*58b9f456SAndroid Build Coastguard Worker have_filter_args = True 195*58b9f456SAndroid Build Coastguard Worker break # No need to keep scanning. 196*58b9f456SAndroid Build Coastguard Worker 197*58b9f456SAndroid Build Coastguard Worker if not args.host: 198*58b9f456SAndroid Build Coastguard Worker setup_test_directory() 199*58b9f456SAndroid Build Coastguard Worker 200*58b9f456SAndroid Build Coastguard Worker lit_args = [ 201*58b9f456SAndroid Build Coastguard Worker '-sv', android_mode_arg, cxx_under_test_arg, cxx_template_arg, 202*58b9f456SAndroid Build Coastguard Worker link_template_arg, libcxx_site_cfg_arg, libcxxabi_site_cfg_arg 203*58b9f456SAndroid Build Coastguard Worker ] + lit_args 204*58b9f456SAndroid Build Coastguard Worker cmd = ['python', lit_path] + lit_args 205*58b9f456SAndroid Build Coastguard Worker if not have_filter_args: 206*58b9f456SAndroid Build Coastguard Worker cmd += default_test_paths 207*58b9f456SAndroid Build Coastguard Worker sys.exit(call(cmd)) 208*58b9f456SAndroid Build Coastguard Worker 209*58b9f456SAndroid Build Coastguard Worker 210*58b9f456SAndroid Build Coastguard Workerif __name__ == '__main__': 211*58b9f456SAndroid Build Coastguard Worker main() 212