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)
|
include $(BUILD_HOST_SHARED_LIBRARY)
|
||||||
|
|
||||||
LIT := $(ANDROID_BUILD_TOP)/external/llvm/utils/lit/lit.py
|
LIT := $(ANDROID_BUILD_TOP)/external/llvm/utils/lit/lit.py
|
||||||
test-libcxx-host: libc++
|
LIBCXX_CONFIGTESTS := $(ANDROID_BUILD_TOP)/external/libcxx/buildcmds/configtests.py
|
||||||
LIT=$(LIT) LIT_MODE=host make -f $(ANDROID_BUILD_TOP)/external/libcxx/test.mk
|
LIBCXX_TEST_MK := $(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
|
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
|
# Don't want to just make test-libcxx-(host|target) dependencies of this because
|
||||||
# the two families can't be run concurrently.
|
# the two families can't be run concurrently.
|
||||||
test-libcxx: libc++
|
test-libcxx: libc++
|
||||||
|
python buildcmds/configtests.py --host
|
||||||
LIT=$(LIT) LIT_MODE=host make -f $(ANDROID_BUILD_TOP)/external/libcxx/test.mk
|
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
|
LIT=$(LIT) LIT_MODE=device make -f $(ANDROID_BUILD_TOP)/external/libcxx/test.mk
|
||||||
|
|
||||||
endif # TARGET_BUILD_APPS
|
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)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := libc++_build_commands_$(ANDROID_DEVICE)
|
LOCAL_MODULE := libc++_build_commands_$(ANDROID_DEVICE)
|
||||||
LOCAL_CXX := $(LOCAL_PATH)/buildcmdscc $(CLANG_CXX)
|
|
||||||
LOCAL_SRC_FILES := dummy.cpp
|
LOCAL_SRC_FILES := dummy.cpp
|
||||||
LOCAL_CXX_STL := libc++
|
LOCAL_CXX_STL := libc++
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../test/support
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../test/support
|
||||||
@@ -37,7 +36,6 @@ LOCAL_CPPFLAGS := \
|
|||||||
LOCAL_CPPFLAGS += -O0
|
LOCAL_CPPFLAGS += -O0
|
||||||
|
|
||||||
LOCAL_RTTI_FLAG := -frtti
|
LOCAL_RTTI_FLAG := -frtti
|
||||||
LOCAL_CLANG := true
|
include $(LOCAL_PATH)/testconfig.mk
|
||||||
include $(BUILD_EXECUTABLE)
|
|
||||||
|
|
||||||
endif
|
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:
|
.NOTPARALLEL:
|
||||||
default:
|
default:
|
||||||
cp $(ANDROID_BUILD_TOP)/external/libcxx/test/lit.$(LIT_MODE).cfg \
|
-python $(LIT) -sv --param android_mode=$(LIT_MODE) \
|
||||||
$(ANDROID_BUILD_TOP)/external/libcxx/test/lit.site.cfg
|
$(ANDROID_BUILD_TOP)/external/libcxx/test
|
||||||
-python $(LIT) -sv $(ANDROID_BUILD_TOP)/external/libcxx/test
|
|
||||||
rm $(ANDROID_BUILD_TOP)/external/libcxx/test/lit.site.cfg
|
|
||||||
|
|||||||
135
test/lit.cfg
135
test/lit.cfg
@@ -204,6 +204,52 @@ class LibcxxTestFormat(lit.formats.FileBasedTest):
|
|||||||
return lit.Test.PASS, ""
|
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):
|
class AdbError(RuntimeError):
|
||||||
def __init__(self, cmd, out, err, exit_code):
|
def __init__(self, cmd, out, err, exit_code):
|
||||||
self.cmd = cmd
|
self.cmd = cmd
|
||||||
@@ -212,17 +258,18 @@ class AdbError(RuntimeError):
|
|||||||
self.exit_code = exit_code
|
self.exit_code = exit_code
|
||||||
|
|
||||||
|
|
||||||
class AndroidLibcxxTestFormat(LibcxxTestFormat):
|
class AndroidLibcxxTestFormat(AndroidHostLibcxxTestFormat):
|
||||||
def __init__(self, cxx_under_test, libcxx_src_root, libcxx_obj_root,
|
def __init__(self, cxx_under_test, libcxx_src_root, libcxx_obj_root,
|
||||||
cxx_template, link_template, device_dir, timeout):
|
cxx_template, link_template, device_dir, timeout):
|
||||||
self.cxx_under_test = cxx_under_test
|
AndroidHostLibcxxTestFormat.__init__(
|
||||||
self.libcxx_src_root = libcxx_src_root
|
self,
|
||||||
self.libcxx_obj_root = libcxx_obj_root
|
cxx_under_test,
|
||||||
self.cxx_template = cxx_template
|
libcxx_src_root,
|
||||||
self.link_template = link_template
|
libcxx_obj_root,
|
||||||
|
cxx_template,
|
||||||
|
link_template,
|
||||||
|
timeout)
|
||||||
self.device_dir = device_dir
|
self.device_dir = device_dir
|
||||||
self.timeout = timeout
|
|
||||||
self.use_verify_for_fail = False
|
|
||||||
|
|
||||||
def _working_directory(self, file_name):
|
def _working_directory(self, file_name):
|
||||||
return os.path.join(self.device_dir, file_name)
|
return os.path.join(self.device_dir, file_name)
|
||||||
@@ -242,23 +289,6 @@ class AndroidLibcxxTestFormat(LibcxxTestFormat):
|
|||||||
if exit_code != 0:
|
if exit_code != 0:
|
||||||
raise AdbError(cmd, out, err, exit_code)
|
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,
|
def _build(self, exec_path, source_path, compile_only=False,
|
||||||
use_verify=False):
|
use_verify=False):
|
||||||
cmd, report, rc = LibcxxTestFormat._build(
|
cmd, report, rc = LibcxxTestFormat._build(
|
||||||
@@ -793,23 +823,56 @@ class AndroidConfiguration(Configuration):
|
|||||||
self.link_template = open(link_template_file).read().strip()
|
self.link_template = open(link_template_file).read().strip()
|
||||||
|
|
||||||
def configure_triple(self):
|
def configure_triple(self):
|
||||||
match = re.search(r'-target\s+(\S+)', self.cxx_template)
|
if 'clang' in self.cxx_under_test:
|
||||||
if not match:
|
triple = self.configure_clang_triple()
|
||||||
|
else:
|
||||||
|
triple = self.configure_gcc_triple()
|
||||||
|
|
||||||
|
if not triple:
|
||||||
raise RuntimeError('Could not determine target 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):
|
def configure_features(self):
|
||||||
self.config.available_features.add('long_tests')
|
self.config.available_features.add('long_tests')
|
||||||
|
|
||||||
def get_test_format(self):
|
def get_test_format(self):
|
||||||
return AndroidLibcxxTestFormat(
|
mode = self.lit_config.params.get('android_mode', 'device')
|
||||||
self.cxx_under_test,
|
if mode == 'device':
|
||||||
self.src_root,
|
return AndroidLibcxxTestFormat(
|
||||||
self.obj_root,
|
self.cxx_under_test,
|
||||||
self.cxx_template,
|
self.src_root,
|
||||||
self.link_template,
|
self.obj_root,
|
||||||
getattr(self.config, 'device_dir', '/data/local/tmp/'),
|
self.cxx_template,
|
||||||
getattr(self.config, 'timeout', '60'))
|
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.
|
# 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