Add std::filesystem support.
Test: ./run_tests.py --bitness 32 Test: ./run_tests.py --bitness 64 Test: ./run_tests.py --bitness 64 --host Bug: None Change-Id: Ie277f503b754321eba04b906fa4ee6d670b2c1b2
This commit is contained in:
41
Android.bp
41
Android.bp
@@ -146,6 +146,29 @@ cc_library_static {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cc_library_static {
|
||||||
|
name: "libc++fs",
|
||||||
|
defaults: ["libc++ defaults"],
|
||||||
|
srcs: [
|
||||||
|
"src/filesystem/directory_iterator.cpp",
|
||||||
|
"src/filesystem/operations.cpp",
|
||||||
|
],
|
||||||
|
multilib: {
|
||||||
|
lib32: {
|
||||||
|
// off_t usage is constrained to within the libc++ source (not the
|
||||||
|
// headers), so we can build the filesystem library with a 64-bit
|
||||||
|
// off_t on LP32 to get large file support without needing all users
|
||||||
|
// of the library to match.
|
||||||
|
cflags: ["-D_FILE_OFFSET_BITS=64"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
target: {
|
||||||
|
windows: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// This target is used to extract the build commands for a test executable.
|
// This target is used to extract the build commands for a test executable.
|
||||||
// See run_tests.py.
|
// See run_tests.py.
|
||||||
cc_binary {
|
cc_binary {
|
||||||
@@ -170,6 +193,7 @@ cc_binary {
|
|||||||
],
|
],
|
||||||
static_libs: [
|
static_libs: [
|
||||||
"libc++experimental",
|
"libc++experimental",
|
||||||
|
"libc++fs",
|
||||||
],
|
],
|
||||||
rtti: true,
|
rtti: true,
|
||||||
local_include_dirs: [
|
local_include_dirs: [
|
||||||
@@ -196,3 +220,20 @@ cc_binary {
|
|||||||
gnu_extensions: false,
|
gnu_extensions: false,
|
||||||
cpp_std: "c++17",
|
cpp_std: "c++17",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
python_test {
|
||||||
|
name: "filesystem_dynamic_test_helper.py",
|
||||||
|
main: "test/support/filesystem_dynamic_test_helper.py",
|
||||||
|
srcs: [
|
||||||
|
"test/support/filesystem_dynamic_test_helper.py",
|
||||||
|
],
|
||||||
|
version: {
|
||||||
|
py2: {
|
||||||
|
enabled: true,
|
||||||
|
embedded_launcher: true,
|
||||||
|
},
|
||||||
|
py3: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ from __future__ import print_function
|
|||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import posixpath
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
THIS_DIR = os.path.dirname(os.path.realpath(__file__))
|
THIS_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||||
@@ -144,9 +145,14 @@ def get_build_cmds(bitness, host):
|
|||||||
|
|
||||||
def setup_test_directory():
|
def setup_test_directory():
|
||||||
"""Prepares a device test directory for use by the shell user."""
|
"""Prepares a device test directory for use by the shell user."""
|
||||||
|
stdfs_test_data = os.path.join(
|
||||||
|
THIS_DIR, 'test/std/input.output/filesystems/Inputs/static_test_env')
|
||||||
device_dir = '/data/local/tmp/libcxx'
|
device_dir = '/data/local/tmp/libcxx'
|
||||||
|
dynamic_dir = posixpath.join(device_dir, 'dynamic_test_env')
|
||||||
check_call(['adb', 'shell', 'rm', '-rf', device_dir])
|
check_call(['adb', 'shell', 'rm', '-rf', device_dir])
|
||||||
check_call(['adb', 'shell', 'mkdir', '-p', device_dir])
|
check_call(['adb', 'shell', 'mkdir', '-p', device_dir])
|
||||||
|
check_call(['adb', 'shell', 'mkdir', '-p', dynamic_dir])
|
||||||
|
check_call(['adb', 'push', '--sync', stdfs_test_data, device_dir])
|
||||||
check_call(['adb', 'shell', 'chown', '-R', 'shell:shell', device_dir])
|
check_call(['adb', 'shell', 'chown', '-R', 'shell:shell', device_dir])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ class AndroidCXXCompiler(libcxx.compiler.CXXCompiler):
|
|||||||
self.link_template = link_template
|
self.link_template = link_template
|
||||||
self.build_top = os.getenv('ANDROID_BUILD_TOP')
|
self.build_top = os.getenv('ANDROID_BUILD_TOP')
|
||||||
|
|
||||||
|
# The file system tests require a handful of defines that we can't add
|
||||||
|
# to the Android.bp since they require absolute paths.
|
||||||
|
self.extra_cflags = []
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
return copy.deepcopy(self)
|
return copy.deepcopy(self)
|
||||||
|
|
||||||
@@ -60,7 +64,7 @@ class AndroidCXXCompiler(libcxx.compiler.CXXCompiler):
|
|||||||
source_files = [source_files]
|
source_files = [source_files]
|
||||||
cxx_args = self.cxx_template.replace('%OUT%', out)
|
cxx_args = self.cxx_template.replace('%OUT%', out)
|
||||||
cxx_args = cxx_args.replace('%SOURCE%', ' '.join(source_files))
|
cxx_args = cxx_args.replace('%SOURCE%', ' '.join(source_files))
|
||||||
return [self.path] + shlex.split(cxx_args)
|
return [self.path] + shlex.split(cxx_args) + self.extra_cflags
|
||||||
|
|
||||||
def linkCmd(self, source_files, out=None, flags=None):
|
def linkCmd(self, source_files, out=None, flags=None):
|
||||||
if out is None:
|
if out is None:
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
import libcxx.test.config
|
import libcxx.test.config
|
||||||
import libcxx.android.compiler
|
import libcxx.android.compiler
|
||||||
@@ -9,6 +10,12 @@ import libcxx.android.test.format
|
|||||||
class Configuration(libcxx.test.config.Configuration):
|
class Configuration(libcxx.test.config.Configuration):
|
||||||
def __init__(self, lit_config, config):
|
def __init__(self, lit_config, config):
|
||||||
super(Configuration, self).__init__(lit_config, config)
|
super(Configuration, self).__init__(lit_config, config)
|
||||||
|
self.exec_env = {}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_host(self):
|
||||||
|
"""Returns True if configured to run host tests."""
|
||||||
|
return self.lit_config.params.get('android_mode') == 'host'
|
||||||
|
|
||||||
def configure(self):
|
def configure(self):
|
||||||
self.configure_src_root()
|
self.configure_src_root()
|
||||||
@@ -17,6 +24,10 @@ class Configuration(libcxx.test.config.Configuration):
|
|||||||
self.configure_cxx()
|
self.configure_cxx()
|
||||||
self.configure_triple()
|
self.configure_triple()
|
||||||
self.configure_features()
|
self.configure_features()
|
||||||
|
if self.is_host:
|
||||||
|
self.configure_filesystem_host()
|
||||||
|
else:
|
||||||
|
self.configure_filesystem_device()
|
||||||
|
|
||||||
def print_config_info(self):
|
def print_config_info(self):
|
||||||
self.lit_config.note(
|
self.lit_config.note(
|
||||||
@@ -29,7 +40,7 @@ class Configuration(libcxx.test.config.Configuration):
|
|||||||
list(self.config.available_features))
|
list(self.config.available_features))
|
||||||
|
|
||||||
def configure_obj_root(self):
|
def configure_obj_root(self):
|
||||||
if self.lit_config.params.get('android_mode') == 'host':
|
if self.is_host:
|
||||||
self.libcxx_obj_root = os.getenv('ANDROID_HOST_OUT')
|
self.libcxx_obj_root = os.getenv('ANDROID_HOST_OUT')
|
||||||
else:
|
else:
|
||||||
self.libcxx_obj_root = os.getenv('ANDROID_PRODUCT_OUT')
|
self.libcxx_obj_root = os.getenv('ANDROID_PRODUCT_OUT')
|
||||||
@@ -49,9 +60,53 @@ class Configuration(libcxx.test.config.Configuration):
|
|||||||
|
|
||||||
self.config.target_triple = self.cxx.get_triple()
|
self.config.target_triple = self.cxx.get_triple()
|
||||||
|
|
||||||
|
def configure_filesystem_host(self):
|
||||||
|
# TODO: We shouldn't be writing to the source directory for the host.
|
||||||
|
static_env = os.path.join(self.libcxx_src_root, 'test', 'std',
|
||||||
|
'input.output', 'filesystems', 'Inputs',
|
||||||
|
'static_test_env')
|
||||||
|
static_env = os.path.realpath(static_env)
|
||||||
|
assert os.path.isdir(static_env)
|
||||||
|
self.cxx.extra_cflags.append(
|
||||||
|
'-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="{}"'.format(static_env))
|
||||||
|
|
||||||
|
dynamic_env = os.path.join(self.config.test_exec_root, 'filesystem',
|
||||||
|
'Output', 'dynamic_env')
|
||||||
|
dynamic_env = os.path.realpath(dynamic_env)
|
||||||
|
if not os.path.isdir(dynamic_env):
|
||||||
|
os.makedirs(dynamic_env)
|
||||||
|
self.cxx.extra_cflags.append(
|
||||||
|
'-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT="{}"'.format(dynamic_env))
|
||||||
|
self.exec_env['LIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT'] = dynamic_env
|
||||||
|
|
||||||
|
dynamic_helper = os.path.join(self.libcxx_src_root, 'test', 'support',
|
||||||
|
'filesystem_dynamic_test_helper.py')
|
||||||
|
assert os.path.isfile(dynamic_helper)
|
||||||
|
self.cxx.extra_cflags.append(
|
||||||
|
'-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER="{} {}"'.format(
|
||||||
|
sys.executable, dynamic_helper))
|
||||||
|
|
||||||
|
def configure_filesystem_device(self):
|
||||||
|
static_env = '/data/local/tmp/libcxx/static_test_env'
|
||||||
|
self.cxx.extra_cflags.append(
|
||||||
|
'-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="{}"'.format(static_env))
|
||||||
|
|
||||||
|
dynamic_env = '/data/local/tmp/libcxx/dynamic_test_env'
|
||||||
|
self.cxx.extra_cflags.append(
|
||||||
|
'-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT="{}"'.format(dynamic_env))
|
||||||
|
self.exec_env['LIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT'] = dynamic_env
|
||||||
|
|
||||||
|
dynamic_helper = ('/data/nativetest/filesystem_dynamic_test_helper.py/'
|
||||||
|
'filesystem_dynamic_test_helper.py')
|
||||||
|
self.cxx.extra_cflags.append(
|
||||||
|
'-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER="{}"'.format(
|
||||||
|
dynamic_helper))
|
||||||
|
|
||||||
def configure_features(self):
|
def configure_features(self):
|
||||||
self.config.available_features.add('long_tests')
|
self.config.available_features.add('long_tests')
|
||||||
self.config.available_features.add('c++experimental')
|
self.config.available_features.add('c++experimental')
|
||||||
|
self.config.available_features.add('c++fs')
|
||||||
|
self.config.available_features.add('c++filesystem')
|
||||||
std_pattern = re.compile(r'-std=(c\+\+\d[0-9x-z])')
|
std_pattern = re.compile(r'-std=(c\+\+\d[0-9x-z])')
|
||||||
match = std_pattern.search(self.cxx.cxx_template)
|
match = std_pattern.search(self.cxx.cxx_template)
|
||||||
if match:
|
if match:
|
||||||
@@ -65,12 +120,14 @@ class Configuration(libcxx.test.config.Configuration):
|
|||||||
self.libcxx_src_root,
|
self.libcxx_src_root,
|
||||||
self.libcxx_obj_root,
|
self.libcxx_obj_root,
|
||||||
getattr(self.config, 'device_dir', '/data/local/tmp/'),
|
getattr(self.config, 'device_dir', '/data/local/tmp/'),
|
||||||
getattr(self.config, 'timeout', '60'))
|
getattr(self.config, 'timeout', '60'),
|
||||||
|
self.exec_env)
|
||||||
elif mode == 'host':
|
elif mode == 'host':
|
||||||
return libcxx.android.test.format.HostTestFormat(
|
return libcxx.android.test.format.HostTestFormat(
|
||||||
self.cxx,
|
self.cxx,
|
||||||
self.libcxx_src_root,
|
self.libcxx_src_root,
|
||||||
self.libcxx_obj_root,
|
self.libcxx_obj_root,
|
||||||
getattr(self.config, 'timeout', '60'))
|
getattr(self.config, 'timeout', '60'),
|
||||||
|
self.exec_env)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError('Invalid android_mode: {}'.format(mode))
|
raise RuntimeError('Invalid android_mode: {}'.format(mode))
|
||||||
|
|||||||
@@ -29,8 +29,10 @@ class HostTestFormat(libcxx.test.format.LibcxxTestFormat):
|
|||||||
os.path.join(outdir, 'lib'),
|
os.path.join(outdir, 'lib'),
|
||||||
os.path.join(outdir, 'lib64'),
|
os.path.join(outdir, 'lib64'),
|
||||||
])
|
])
|
||||||
default_env = {'LD_LIBRARY_PATH': libpath}
|
env = {'LD_LIBRARY_PATH': libpath}
|
||||||
self.exec_env = default_env if exec_env is None else exec_env
|
if exec_env is not None:
|
||||||
|
env.update(exec_env)
|
||||||
|
self.exec_env = env
|
||||||
|
|
||||||
|
|
||||||
class TestFormat(HostTestFormat):
|
class TestFormat(HostTestFormat):
|
||||||
|
|||||||
Reference in New Issue
Block a user