Update run_tests.py to use Soong.

am: 26cd9b82f8

Change-Id: I0748261cf691ec81f681e6f95c639bcef6f5e2b9
This commit is contained in:
Peter Collingbourne
2018-12-05 18:20:08 -08:00
committed by android-build-merger
12 changed files with 158 additions and 168 deletions

View File

@@ -128,13 +128,46 @@ cc_library_shared {
},
}
// This target is used to extract the build commands for a test executable.
// See run_tests.py.
cc_binary {
name: "libcxx_test_template",
srcs: [
"libcxx_test_template.cpp",
],
cppflags: [
"-fsized-deallocation",
"-fexceptions",
"-Wno-format-zero-length",
"-Wno-implicit-fallthrough",
"-Wno-non-virtual-dtor",
"-Wno-return-stack-address",
"-Wno-unused-local-typedef",
// ANDROIDMK TRANSLATION ERROR: unsupported conditional
// ifdef LIBCXX_TESTING
// ANDROIDMK TRANSLATION ERROR: unsupported include
// include $(LOCAL_PATH)/buildcmds/Android.mk
// ANDROIDMK TRANSLATION ERROR: endif from unsupported contitional
// endif
// TARGET_BUILD_APPS
"-UNDEBUG",
// Optimization is causing relocation for nothrow new to be thrown away.
// http://llvm.org/bugs/show_bug.cgi?id=21421
"-O0",
],
ldflags: [
// This makes the tests run a little faster.
"-Wl,--strip-all",
],
rtti: true,
local_include_dirs: [
"test/support",
],
multilib: {
lib32: {
suffix: "32",
},
lib64: {
suffix: "64",
},
},
compile_multilib: "both",
host_supported: true,
gnu_extensions: false,
cpp_std: "c++17",
}

View File

@@ -1 +0,0 @@
# This empty Android.mk file is required to shadow buildcmds/Android.mk

View File

@@ -1,4 +0,0 @@
cxx_under_test
cxx.cmds
link.cmds
testconfig.mk

View File

@@ -1,45 +0,0 @@
#
# Copyright (C) 2014 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
# Don't build for unbundled branches
ifeq (,$(TARGET_BUILD_APPS))
include $(CLEAR_VARS)
LOCAL_MODULE := libc++_build_commands_$(ANDROID_DEVICE)
LOCAL_SRC_FILES := dummy.cpp
LOCAL_CXX_STL := libc++
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../test/support
LOCAL_CPPFLAGS := \
-std=c++17 \
-fsized-deallocation \
-fexceptions \
-UNDEBUG \
-Wno-error=non-virtual-dtor \
-Wno-format-zero-length \
-Wno-reserved-user-defined-literal \
-Wno-unused-local-typedef \
-Wno-unused-variable \
# Optimization is causing relocation for nothrow new to be thrown away.
# http://llvm.org/bugs/show_bug.cgi?id=21421
LOCAL_CPPFLAGS += -O0
LOCAL_RTTI_FLAG := -frtti
include $(LOCAL_PATH)/testconfig.mk
endif

View File

@@ -1,16 +0,0 @@
#!/bin/bash
CXX=$1
ARGS=${*:2}
DIR=external/libcxx/buildcmds
echo $ANDROID_BUILD_TOP/$CXX > $DIR/cxx_under_test
echo $ARGS | grep -P '\S+\.cpp\b' > /dev/null
if [ $? -eq 0 ]; then
echo $ARGS | perl -ne 's/\S+\.cpp\b/%SOURCE%/; print' \
| perl -ne 's/\S+\.o\b/%OUT%/; print' > $DIR/cxx.cmds
else
echo $ARGS | perl -ne 's/out\/\S+\/EXECUTABLES\/\S+\.o\b/%SOURCE%/; print' \
| perl -ne 's/-o\s+\S+\b/-o %OUT%/; print' > $DIR/link.cmds
fi
$CXX $ARGS

View File

@@ -1,3 +0,0 @@
int main() {
return 0;
}

1
libcxx_test_template.cpp Normal file
View File

@@ -0,0 +1 @@
int main() {}

11
pylintrc Normal file
View File

@@ -0,0 +1,11 @@
[MESSAGES CONTROL]
disable=design,fixme
[BASIC]
good-names=i,
j,
k,
ex,
Run,
_,
cc

View File

@@ -22,7 +22,6 @@ import logging
import os
import sys
THIS_DIR = os.path.dirname(os.path.realpath(__file__))
ANDROID_DIR = os.path.realpath(os.path.join(THIS_DIR, '../..'))
@@ -46,68 +45,101 @@ def check_call(cmd, *args, **kwargs):
return subprocess.check_call(cmd, *args, **kwargs)
def check_output(cmd, *args, **kwargs):
"""subprocess.check_output with logging."""
import subprocess
logger().info('check_output %s', ' '.join(cmd))
return subprocess.check_output(cmd, *args, **kwargs)
class ArgParser(argparse.ArgumentParser):
"""Parses command line arguments."""
def __init__(self):
super(ArgParser, self).__init__()
self.add_argument(
'--compiler', choices=('clang', 'gcc'), default='clang')
self.add_argument(
'--bitness', choices=(32, 64), type=int, default=32)
self.add_argument('--bitness', choices=(32, 64), type=int, default=32)
self.add_argument('--host', action='store_true')
def gen_test_config(bitness, compiler, host):
"""Generates the test configuration makefile for buildcmds."""
testconfig_mk_path = os.path.join(THIS_DIR, 'buildcmds/testconfig.mk')
with open(testconfig_mk_path, 'w') as test_config:
if compiler == 'clang':
print('LOCAL_CLANG := true', file=test_config)
elif compiler == 'gcc':
print('LOCAL_CLANG := false', file=test_config)
def extract_build_cmds(commands, exe_name):
"""Extracts build command information from `ninja -t commands` output.
if bitness == 32:
print('LOCAL_MULTILIB := 32', file=test_config)
elif bitness == 64:
print('LOCAL_MULTILIB := 64', file=test_config)
Args:
commands: String containing the output of `ninja -t commands` for the
libcxx_test_template.
exe_name: The basename of the built executable.
if compiler == 'clang':
print('LOCAL_CXX := $(LOCAL_PATH)/buildcmdscc $(CLANG_CXX)',
file=test_config)
else:
if host:
prefix = 'HOST_'
else:
prefix = 'TARGET_'
print('LOCAL_CXX := $(LOCAL_PATH)/buildcmdscc '
'$($(LOCAL_2ND_ARCH_VAR_PREFIX){}CXX)'.format(prefix),
file=test_config)
Returns:
Tuple of (compiler, compiler_flags, linker_flags).
"""
cc = None
cflags = None
ldflags = None
template_name = 'external/libcxx/libcxx_test_template.cpp'
if host:
print('include $(BUILD_HOST_EXECUTABLE)', file=test_config)
else:
print('include $(BUILD_EXECUTABLE)', file=test_config)
for cmd in commands.splitlines():
cmd_args = cmd.split()
if cc is None and template_name in cmd_args:
for i, arg in enumerate(cmd_args):
if arg == '-o':
cmd_args[i + 1] = '%OUT%'
elif arg == template_name:
cmd_args[i] = '%SOURCE%'
# Drop dependency tracking args since they can cause file
# not found errors at test time.
if arg == '-MD':
cmd_args[i] = ''
if arg == '-MF':
cmd_args[i] = ''
cmd_args[i + 1] = ''
if cmd_args[0] == 'PWD=/proc/self/cwd':
cmd_args = cmd_args[1:]
if cmd_args[0].endswith('gomacc'):
cmd_args = cmd_args[1:]
cc = cmd_args[0]
cflags = cmd_args[1:]
if ldflags is None:
is_ld = False
for i, arg in enumerate(cmd_args):
# Here we assume that the rspfile contains the path to the
# object file and nothing else.
if arg.startswith('@'):
cmd_args[i] = '%SOURCE%'
if arg == '-o' and cmd_args[i + 1].endswith(exe_name):
cmd_args[i + 1] = '%OUT%'
is_ld = True
if is_ld:
ldflags = cmd_args[1:]
return cc, cflags, ldflags
def mmm(path):
"""Invokes the Android build command mmm."""
makefile = os.path.join(path, 'Android.mk')
main_mk = 'build/core/main.mk'
def get_build_cmds(bitness, host):
"""Use ninja -t commands to find the build commands for an executable."""
out_dir = os.getenv('OUT_DIR', os.path.join(ANDROID_DIR, 'out'))
product_out = os.getenv('ANDROID_PRODUCT_OUT')
env = dict(os.environ)
env['ONE_SHOT_MAKEFILE'] = makefile
env['LIBCXX_TESTING'] = 'true'
cmd = [
'make', '-j', '-C', ANDROID_DIR, '-f', main_mk,
'MODULES-IN-' + path.replace('/', '-'),
]
check_call(cmd, env=env)
if host:
rel_out_dir = os.path.relpath(
os.path.join(out_dir, 'soong/host/linux-x86/bin'), ANDROID_DIR)
target = os.path.join(rel_out_dir, 'libcxx_test_template64')
else:
exe_name = 'libcxx_test_template' + str(bitness)
rel_out_dir = os.path.relpath(product_out, ANDROID_DIR)
target = os.path.join(rel_out_dir, 'system/bin', exe_name)
# Generate $OUT_DIR/combined-$TARGET_PRODUCT.ninja and build the
# template target's dependencies.
check_call(['make', '-C', ANDROID_DIR, target])
def gen_build_cmds(bitness, compiler, host):
"""Generates the build commands file for the test runner."""
gen_test_config(bitness, compiler, host)
mmm('external/libcxx/buildcmds')
ninja_path = os.path.join(
out_dir, 'combined-' + os.getenv('TARGET_PRODUCT') + '.ninja')
commands = check_output([
os.path.join(ANDROID_DIR, 'prebuilts/build-tools/linux-x86/bin/ninja'),
'-C', ANDROID_DIR, '-f', ninja_path, '-t', 'commands', target
])
return extract_build_cmds(commands, os.path.basename(target))
def main():
@@ -116,20 +148,27 @@ def main():
args, lit_args = ArgParser().parse_known_args()
lit_path = os.path.join(ANDROID_DIR, 'external/llvm/utils/lit/lit.py')
gen_build_cmds(args.bitness, args.compiler, args.host)
cc, cflags, ldflags = get_build_cmds(args.bitness, args.host)
mode_str = 'host' if args.host else 'device'
android_mode_arg = '--param=android_mode=' + mode_str
cxx_under_test_arg = '--param=cxx_under_test=' + cc
cxx_template_arg = '--param=cxx_template=' + ' '.join(cflags)
link_template_arg = '--param=link_template=' + ' '.join(ldflags)
site_cfg_path = os.path.join(THIS_DIR, 'test/lit.site.cfg')
site_cfg_arg = '--param=libcxx_site_config=' + site_cfg_path
default_test_path = os.path.join(THIS_DIR, 'test')
libcxx_site_cfg_arg = '--param=libcxx_site_config=' + site_cfg_path
libcxxabi_site_cfg_arg = '--param=libcxxabi_site_config=' + site_cfg_path
default_test_paths = [
os.path.join(THIS_DIR, 'test'),
os.path.join(ANDROID_DIR, 'external/libcxxabi/test')
]
have_filter_args = False
for arg in lit_args:
# If the argument is a valid path with default_test_path, it is a test
# If the argument is a valid path with default_test_paths, it is a test
# filter.
real_path = os.path.realpath(arg)
if not real_path.startswith(default_test_path):
if not any(real_path.startswith(path) for path in default_test_paths):
continue
if not os.path.exists(real_path):
continue
@@ -137,10 +176,13 @@ def main():
have_filter_args = True
break # No need to keep scanning.
lit_args = ['-sv', android_mode_arg, site_cfg_arg] + lit_args
lit_args = [
'-sv', android_mode_arg, cxx_under_test_arg, cxx_template_arg,
link_template_arg, libcxx_site_cfg_arg, libcxxabi_site_cfg_arg
] + lit_args
cmd = ['python', lit_path] + lit_args
if not have_filter_args:
cmd.append(default_test_path)
cmd += default_test_paths
sys.exit(call(cmd))

View File

@@ -1,7 +1,6 @@
import os
import libcxx.test.config
import libcxx.android.build
import libcxx.android.test.format
@@ -9,7 +8,6 @@ class Configuration(libcxx.test.config.Configuration):
def __init__(self, lit_config, config):
super(Configuration, self).__init__(lit_config, config)
self.cxx_under_test = None
self.build_cmds_dir = None
self.cxx_template = None
self.link_template = None

View File

@@ -1,13 +0,0 @@
import os
import subprocess
def mm(path, android_build_top):
env = os.environ
env['ONE_SHOT_MAKEFILE'] = os.path.join(path, 'Android.mk')
cmd = [
'make', '-C', android_build_top, '-f', 'build/core/main.mk',
'MODULES-IN-' + path.replace('/', '-'), '-B'
]
return not subprocess.Popen(cmd, stdout=None, stderr=None, env=env).wait()

View File

@@ -2,7 +2,6 @@ import os
import re
import libcxx.test.config
import libcxx.android.build
import libcxx.android.compiler
import libcxx.android.test.format
@@ -10,11 +9,9 @@ import libcxx.android.test.format
class Configuration(libcxx.test.config.Configuration):
def __init__(self, lit_config, config):
super(Configuration, self).__init__(lit_config, config)
self.build_cmds_dir = None
def configure(self):
self.configure_src_root()
self.configure_build_cmds()
self.configure_obj_root()
self.configure_cxx()
@@ -32,34 +29,24 @@ class Configuration(libcxx.test.config.Configuration):
list(self.config.available_features))
def configure_obj_root(self):
test_config_file = os.path.join(self.build_cmds_dir, 'testconfig.mk')
if 'HOST_NATIVE_TEST' in open(test_config_file).read():
if self.lit_config.params.get('android_mode') == 'host':
self.libcxx_obj_root = os.getenv('ANDROID_HOST_OUT')
else:
self.libcxx_obj_root = os.getenv('ANDROID_PRODUCT_OUT')
def configure_build_cmds(self):
os.chdir(self.config.android_root)
self.build_cmds_dir = 'external/libcxx/buildcmds'
if not libcxx.android.build.mm(self.build_cmds_dir,
self.config.android_root):
raise RuntimeError('Could not generate build commands.')
def configure_cxx(self):
cxx_under_test_file = os.path.join(self.build_cmds_dir,
'cxx_under_test')
cxx_under_test = open(cxx_under_test_file).read().strip()
cxx_template_file = os.path.join(self.build_cmds_dir, 'cxx.cmds')
cxx_template = open(cxx_template_file).read().strip()
link_template_file = os.path.join(self.build_cmds_dir, 'link.cmds')
link_template = open(link_template_file).read().strip()
cxx_under_test = self.lit_config.params.get('cxx_under_test')
cxx_template = self.lit_config.params.get('cxx_template')
link_template = self.lit_config.params.get('link_template')
self.cxx = libcxx.android.compiler.AndroidCXXCompiler(
cxx_under_test, cxx_template, link_template)
def configure_triple(self):
# The libcxxabi test suite needs this but it doesn't actually
# use it for anything important.
self.config.host_triple = ''
self.config.target_triple = self.cxx.get_triple()
def configure_features(self):