Make it easier to run test variants.
This adds all the permutations for tests as make targets of the form test-libcxx-(host|target)-(clang|gcc)-(32|64). This also changes the host tests to use the Android build system (like I had done with https://android-review.googlesource.com/#/c/111924/). This probably should have been a separate patch, but I got carried away (and wanted to make sure this new approach would work for both), and now they're non-trivial to split. Change-Id: Ie99caf6c3ff21c833408f99d37299d966ee7bc94
This commit is contained in:
49
Android.mk
49
Android.mk
@@ -126,15 +126,56 @@ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
|
||||
include $(BUILD_HOST_SHARED_LIBRARY)
|
||||
|
||||
LIT := $(ANDROID_BUILD_TOP)/external/llvm/utils/lit/lit.py
|
||||
test-libcxx-host: libc++
|
||||
LIT=$(LIT) LIT_MODE=host make -f $(ANDROID_BUILD_TOP)/external/libcxx/test.mk
|
||||
test-libcxx-target: libc++
|
||||
LIT=$(LIT) LIT_MODE=device make -f $(ANDROID_BUILD_TOP)/external/libcxx/test.mk
|
||||
LIBCXX_CONFIGTESTS := $(ANDROID_BUILD_TOP)/external/libcxx/buildcmds/configtests.py
|
||||
LIBCXX_TEST_MK := $(ANDROID_BUILD_TOP)/external/libcxx/test.mk
|
||||
|
||||
test-libcxx-target: test-libcxx-target-clang
|
||||
test-libcxx-host: test-libcxx-host-clang
|
||||
|
||||
test-libcxx-target-clang: libc++
|
||||
python $(LIBCXX_CONFIGTESTS) --compiler=clang
|
||||
LIT=$(LIT) LIT_MODE=device make -f $(LIBCXX_TEST_MK)
|
||||
test-libcxx-target-gcc: libc++
|
||||
python $(LIBCXX_CONFIGTESTS) --compiler=gcc
|
||||
LIT=$(LIT) LIT_MODE=device make -f $(LIBCXX_TEST_MK)
|
||||
test-libcxx-target-clang-32: libc++
|
||||
python $(LIBCXX_CONFIGTESTS) --bitness=32 --compiler=clang
|
||||
LIT=$(LIT) LIT_MODE=device make -f $(LIBCXX_TEST_MK)
|
||||
test-libcxx-target-gcc-32: libc++
|
||||
python $(LIBCXX_CONFIGTESTS) --bitness=32 --compiler=gcc
|
||||
LIT=$(LIT) LIT_MODE=device make -f $(LIBCXX_TEST_MK)
|
||||
test-libcxx-target-clang-64: libc++
|
||||
python $(LIBCXX_CONFIGTESTS) --bitness=64 --compiler=clang
|
||||
LIT=$(LIT) LIT_MODE=device make -f $(LIBCXX_TEST_MK)
|
||||
test-libcxx-target-gcc-64: libc++
|
||||
python $(LIBCXX_CONFIGTESTS) --bitness=64 --compiler=gcc
|
||||
LIT=$(LIT) LIT_MODE=device make -f $(LIBCXX_TEST_MK)
|
||||
|
||||
test-libcxx-host-clang: libc++
|
||||
python $(LIBCXX_CONFIGTESTS) --compiler=clang --host
|
||||
LIT=$(LIT) LIT_MODE=host make -f $(LIBCXX_TEST_MK)
|
||||
test-libcxx-host-gcc: libc++
|
||||
python $(LIBCXX_CONFIGTESTS) --compiler=gcc --host
|
||||
LIT=$(LIT) LIT_MODE=host make -f $(LIBCXX_TEST_MK)
|
||||
test-libcxx-host-clang-32: libc++
|
||||
python $(LIBCXX_CONFIGTESTS) --bitness=32 --compiler=clang --host
|
||||
LIT=$(LIT) LIT_MODE=host make -f $(LIBCXX_TEST_MK)
|
||||
test-libcxx-host-gcc-32: libc++
|
||||
python $(LIBCXX_CONFIGTESTS) --bitness=32 --compiler=gcc --host
|
||||
LIT=$(LIT) LIT_MODE=host make -f $(LIBCXX_TEST_MK)
|
||||
test-libcxx-host-clang-64: libc++
|
||||
python $(LIBCXX_CONFIGTESTS) --bitness=64 --compiler=clang --host
|
||||
LIT=$(LIT) LIT_MODE=host make -f $(LIBCXX_TEST_MK)
|
||||
test-libcxx-host-gcc-64: libc++
|
||||
python $(LIBCXX_CONFIGTESTS) --bitness=64 --compiler=gcc --host
|
||||
LIT=$(LIT) LIT_MODE=host make -f $(LIBCXX_TEST_MK)
|
||||
|
||||
# Don't want to just make test-libcxx-(host|target) dependencies of this because
|
||||
# the two families can't be run concurrently.
|
||||
test-libcxx: libc++
|
||||
python buildcmds/configtests.py --host
|
||||
LIT=$(LIT) LIT_MODE=host make -f $(ANDROID_BUILD_TOP)/external/libcxx/test.mk
|
||||
python buildcmds/configtests.py
|
||||
LIT=$(LIT) LIT_MODE=device make -f $(ANDROID_BUILD_TOP)/external/libcxx/test.mk
|
||||
|
||||
endif # TARGET_BUILD_APPS
|
||||
|
||||
4
buildcmds/.gitignore
vendored
Normal file
4
buildcmds/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
cxx_under_test
|
||||
cxx.cmds
|
||||
link.cmds
|
||||
testconfig.mk
|
||||
@@ -21,7 +21,6 @@ ifeq (,$(TARGET_BUILD_APPS))
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := libc++_build_commands_$(ANDROID_DEVICE)
|
||||
LOCAL_CXX := $(LOCAL_PATH)/buildcmdscc $(CLANG_CXX)
|
||||
LOCAL_SRC_FILES := dummy.cpp
|
||||
LOCAL_CXX_STL := libc++
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../test/support
|
||||
@@ -37,7 +36,6 @@ LOCAL_CPPFLAGS := \
|
||||
LOCAL_CPPFLAGS += -O0
|
||||
|
||||
LOCAL_RTTI_FLAG := -frtti
|
||||
LOCAL_CLANG := true
|
||||
include $(BUILD_EXECUTABLE)
|
||||
include $(LOCAL_PATH)/testconfig.mk
|
||||
|
||||
endif
|
||||
|
||||
61
buildcmds/configtests.py
Normal file
61
buildcmds/configtests.py
Normal file
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import getopt
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
opts, _ = getopt.getopt(sys.argv[1:], '', [
|
||||
'bitness=', 'compiler=', 'host'])
|
||||
except getopt.GetoptError as err:
|
||||
sys.exit(err)
|
||||
|
||||
bitness = None
|
||||
compiler = 'clang'
|
||||
host = False
|
||||
for opt, val in opts:
|
||||
if opt == '--bitness':
|
||||
bitness = int(val)
|
||||
if bitness not in (32, 64):
|
||||
sys.exit('Invalid bitness: {}'.format(bitness))
|
||||
elif opt == '--compiler':
|
||||
if val not in ('clang', 'gcc'):
|
||||
sys.exit('Unknown compiler: {}'.format(val))
|
||||
compiler = val
|
||||
elif opt == '--host':
|
||||
host = True
|
||||
else:
|
||||
raise NotImplementedError('unhandled option: {}'.format(opt))
|
||||
|
||||
with open('external/libcxx/buildcmds/testconfig.mk', 'w') as test_config:
|
||||
if compiler == 'clang':
|
||||
print('LOCAL_CLANG := true', file=test_config)
|
||||
elif compiler == 'gcc':
|
||||
print('LOCAL_CLANG := false', file=test_config)
|
||||
|
||||
if bitness == 32:
|
||||
print('LOCAL_MULTILIB := 32', file=test_config)
|
||||
elif bitness == 64:
|
||||
print('LOCAL_MULTILIB := 64', file=test_config)
|
||||
|
||||
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)
|
||||
|
||||
if host:
|
||||
print('include $(BUILD_HOST_EXECUTABLE)', file=test_config)
|
||||
else:
|
||||
print('include $(BUILD_EXECUTABLE)', file=test_config)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
6
test.mk
6
test.mk
@@ -1,6 +1,4 @@
|
||||
.NOTPARALLEL:
|
||||
default:
|
||||
cp $(ANDROID_BUILD_TOP)/external/libcxx/test/lit.$(LIT_MODE).cfg \
|
||||
$(ANDROID_BUILD_TOP)/external/libcxx/test/lit.site.cfg
|
||||
-python $(LIT) -sv $(ANDROID_BUILD_TOP)/external/libcxx/test
|
||||
rm $(ANDROID_BUILD_TOP)/external/libcxx/test/lit.site.cfg
|
||||
-python $(LIT) -sv --param android_mode=$(LIT_MODE) \
|
||||
$(ANDROID_BUILD_TOP)/external/libcxx/test
|
||||
|
||||
135
test/lit.cfg
135
test/lit.cfg
@@ -204,6 +204,52 @@ class LibcxxTestFormat(lit.formats.FileBasedTest):
|
||||
return lit.Test.PASS, ""
|
||||
|
||||
|
||||
class AndroidHostLibcxxTestFormat(LibcxxTestFormat):
|
||||
def __init__(self, cxx_under_test, libcxx_src_root, libcxx_obj_root,
|
||||
cxx_template, link_template, timeout):
|
||||
self.cxx_under_test = cxx_under_test
|
||||
self.libcxx_src_root = libcxx_src_root
|
||||
self.libcxx_obj_root = libcxx_obj_root
|
||||
self.cxx_template = cxx_template
|
||||
self.link_template = link_template
|
||||
self.timeout = timeout
|
||||
self.use_verify_for_fail = False
|
||||
|
||||
def _compile(self, output_path, source_path, use_verify=False):
|
||||
if use_verify:
|
||||
raise NotImplementedError(
|
||||
'AndroidConfiguration does not support use_verify mode.')
|
||||
cxx_args = self.cxx_template.replace('%OUT%', output_path)
|
||||
cxx_args = cxx_args.replace('%SOURCE%', source_path)
|
||||
cmd = [self.cxx_under_test] + shlex.split(cxx_args)
|
||||
out, err, exit_code = lit.util.executeCommand(cmd)
|
||||
return cmd, out, err, exit_code
|
||||
|
||||
def _link(self, exec_path, object_path):
|
||||
link_args = self.link_template.replace('%OUT%', exec_path)
|
||||
link_args = link_args.replace('%SOURCE%', object_path)
|
||||
cmd = [self.cxx_under_test] + shlex.split(link_args)
|
||||
out, err, exit_code = lit.util.executeCommand(cmd)
|
||||
return cmd, out, err, exit_code
|
||||
|
||||
def _run(self, exec_path, lit_config, in_dir=None):
|
||||
cmd = [exec_path]
|
||||
# We need to use LD_LIBRARY_PATH because the build system's rpath is
|
||||
# relative, which won't work since we're running from /tmp. We can
|
||||
# either scan `cxx_under_test`/`link_template` to determine whether
|
||||
# we're 32-bit or 64-bit, scan testconfig.mk, or just add both
|
||||
# directories and let the linker sort it out. I'm choosing the lazy
|
||||
# option.
|
||||
outdir = os.getenv('ANDROID_HOST_OUT')
|
||||
libpath = os.pathsep.join([
|
||||
os.path.join(outdir, 'lib'),
|
||||
os.path.join(outdir, 'lib64'),
|
||||
])
|
||||
out, err, rc = lit.util.executeCommand(
|
||||
cmd, cwd=in_dir, env={'LD_LIBRARY_PATH': libpath})
|
||||
return self._make_report(cmd, out, err, rc)
|
||||
|
||||
|
||||
class AdbError(RuntimeError):
|
||||
def __init__(self, cmd, out, err, exit_code):
|
||||
self.cmd = cmd
|
||||
@@ -212,17 +258,18 @@ class AdbError(RuntimeError):
|
||||
self.exit_code = exit_code
|
||||
|
||||
|
||||
class AndroidLibcxxTestFormat(LibcxxTestFormat):
|
||||
class AndroidLibcxxTestFormat(AndroidHostLibcxxTestFormat):
|
||||
def __init__(self, cxx_under_test, libcxx_src_root, libcxx_obj_root,
|
||||
cxx_template, link_template, device_dir, timeout):
|
||||
self.cxx_under_test = cxx_under_test
|
||||
self.libcxx_src_root = libcxx_src_root
|
||||
self.libcxx_obj_root = libcxx_obj_root
|
||||
self.cxx_template = cxx_template
|
||||
self.link_template = link_template
|
||||
AndroidHostLibcxxTestFormat.__init__(
|
||||
self,
|
||||
cxx_under_test,
|
||||
libcxx_src_root,
|
||||
libcxx_obj_root,
|
||||
cxx_template,
|
||||
link_template,
|
||||
timeout)
|
||||
self.device_dir = device_dir
|
||||
self.timeout = timeout
|
||||
self.use_verify_for_fail = False
|
||||
|
||||
def _working_directory(self, file_name):
|
||||
return os.path.join(self.device_dir, file_name)
|
||||
@@ -242,23 +289,6 @@ class AndroidLibcxxTestFormat(LibcxxTestFormat):
|
||||
if exit_code != 0:
|
||||
raise AdbError(cmd, out, err, exit_code)
|
||||
|
||||
def _compile(self, output_path, source_path, use_verify=False):
|
||||
if use_verify:
|
||||
raise NotImplementedError(
|
||||
'AndroidConfiguration does not support use_verify mode.')
|
||||
cxx_args = self.cxx_template.replace('%OUT%', output_path)
|
||||
cxx_args = cxx_args.replace('%SOURCE%', source_path)
|
||||
cmd = [self.cxx_under_test] + shlex.split(cxx_args)
|
||||
out, err, exit_code = lit.util.executeCommand(cmd)
|
||||
return cmd, out, err, exit_code
|
||||
|
||||
def _link(self, exec_path, object_path):
|
||||
link_args = self.link_template.replace('%OUT%', exec_path)
|
||||
link_args = link_args.replace('%SOURCE%', object_path)
|
||||
cmd = [self.cxx_under_test] + shlex.split(link_args)
|
||||
out, err, exit_code = lit.util.executeCommand(cmd)
|
||||
return cmd, out, err, exit_code
|
||||
|
||||
def _build(self, exec_path, source_path, compile_only=False,
|
||||
use_verify=False):
|
||||
cmd, report, rc = LibcxxTestFormat._build(
|
||||
@@ -793,23 +823,56 @@ class AndroidConfiguration(Configuration):
|
||||
self.link_template = open(link_template_file).read().strip()
|
||||
|
||||
def configure_triple(self):
|
||||
match = re.search(r'-target\s+(\S+)', self.cxx_template)
|
||||
if not match:
|
||||
if 'clang' in self.cxx_under_test:
|
||||
triple = self.configure_clang_triple()
|
||||
else:
|
||||
triple = self.configure_gcc_triple()
|
||||
|
||||
if not triple:
|
||||
raise RuntimeError('Could not determine target triple.')
|
||||
self.config.target_triple = match.group(1)
|
||||
self.config.target_triple = triple
|
||||
|
||||
def configure_clang_triple(self):
|
||||
match = re.search(r'-target\s+(\S+)', self.cxx_template)
|
||||
if match:
|
||||
return match.group(1)
|
||||
return None
|
||||
|
||||
def configure_gcc_triple(self):
|
||||
proc = subprocess.Popen([self.cxx_under_test, '-v'],
|
||||
stderr=subprocess.PIPE)
|
||||
_, stderr = proc.communicate()
|
||||
for line in stderr.split('\n'):
|
||||
print 'Checking {}'.format(line)
|
||||
match = re.search(r'^Target: (.+)$', line)
|
||||
if match:
|
||||
return match.group(1)
|
||||
return None
|
||||
|
||||
def configure_features(self):
|
||||
self.config.available_features.add('long_tests')
|
||||
|
||||
def get_test_format(self):
|
||||
return AndroidLibcxxTestFormat(
|
||||
self.cxx_under_test,
|
||||
self.src_root,
|
||||
self.obj_root,
|
||||
self.cxx_template,
|
||||
self.link_template,
|
||||
getattr(self.config, 'device_dir', '/data/local/tmp/'),
|
||||
getattr(self.config, 'timeout', '60'))
|
||||
mode = self.lit_config.params.get('android_mode', 'device')
|
||||
if mode == 'device':
|
||||
return AndroidLibcxxTestFormat(
|
||||
self.cxx_under_test,
|
||||
self.src_root,
|
||||
self.obj_root,
|
||||
self.cxx_template,
|
||||
self.link_template,
|
||||
getattr(self.config, 'device_dir', '/data/local/tmp/'),
|
||||
getattr(self.config, 'timeout', '60'))
|
||||
elif mode == 'host':
|
||||
return AndroidHostLibcxxTestFormat(
|
||||
self.cxx_under_test,
|
||||
self.src_root,
|
||||
self.obj_root,
|
||||
self.cxx_template,
|
||||
self.link_template,
|
||||
getattr(self.config, 'timeout', '60'))
|
||||
else:
|
||||
raise RuntimeError('Invalid android_mode: {}'.format(mode))
|
||||
|
||||
|
||||
# name: The name of this test suite.
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import os
|
||||
|
||||
android_root = os.getenv('ANDROID_BUILD_TOP')
|
||||
config.cxx_under_test = os.path.join(
|
||||
android_root, 'prebuilts/clang/linux-x86/host/3.5/bin/clang++')
|
||||
config.cxx_has_stdcxx0x_flag = True
|
||||
config.libcxx_src_root = os.path.join(android_root, 'external/libcxx')
|
||||
config.libcxx_obj_root = os.getenv('ANDROID_HOST_OUT')
|
||||
config.python_executable = "/usr/bin/python"
|
||||
config.enable_shared = True
|
||||
config.cxx_abi = "none"
|
||||
|
||||
# Let the main config do the real work.
|
||||
lit_config.load_config(
|
||||
config, os.path.join(config.libcxx_src_root, 'test/lit.cfg'))
|
||||
Reference in New Issue
Block a user