Index: test/lit.cfg
===================================================================
--- test/lit.cfg
+++ test/lit.cfg
@@ -28,31 +28,31 @@
FOO.fail.cpp - Negative test case which is expected to fail compilation.
"""
- def __init__(self, cxx_under_test, use_verify_for_fail,
- cpp_flags, ld_flags, exec_env):
+ def __init__(self, cxx_under_test,
+ cpp_flags, ld_flags, exec_env,
+ use_clang_verify=False):
self.cxx_under_test = cxx_under_test
- self.use_verify_for_fail = use_verify_for_fail
self.cpp_flags = list(cpp_flags)
self.ld_flags = list(ld_flags)
self.exec_env = dict(exec_env)
-
- def execute_command(self, command, in_dir=None):
- kwargs = {
- 'stdin' :subprocess.PIPE,
- 'stdout':subprocess.PIPE,
- 'stderr':subprocess.PIPE,
- }
- if in_dir:
- kwargs['cwd'] = in_dir
- p = subprocess.Popen(command, **kwargs)
- out,err = p.communicate()
- exitCode = p.wait()
-
- # Detect Ctrl-C in subprocess.
- if exitCode == -signal.SIGINT:
- raise KeyboardInterrupt
-
- return out, err, exitCode
+ self.use_clang_verify = use_clang_verify
+
+ def execute_command(self, cmd, cwd=None, env=None):
+ out,err,exitCode = lit.util.executeCommand(cmd,cwd=cwd,env=env)
+ report = """Command: %s\n""" %\
+ ' '.join(["'%s'" % a for a in cmd])
+ if cwd is not None:
+ report += """Current Directory: %s\n""" % cwd
+ if env is not None:
+ report += """Environment: %s\n""" %\
+ ' '.join(["'%s'='%s'" % (k,v) for k,v in env.iteritems()])
+ report += """Exit Code: %d\n""" % exitCode
+ if out:
+ report += """Standard Output:\n--\n%s--\n""" % out
+ if err:
+ report += """Standard Error:\n--\n%s--\n""" % err
+ report += '\n'
+ return out,err,exitCode,report
def execute(self, test, lit_config):
while True:
@@ -79,7 +79,7 @@
elif 'UNSUPPORTED:' in ln:
items = ln[ln.index('UNSUPPORTED:') + 12:].split(',')
unsupported.extend([s.strip() for s in items])
- elif 'USE_VERIFY' in ln and self.use_verify_for_fail:
+ elif 'USE_VERIFY' in ln and self.use_clang_verify:
use_verify = True
elif not ln.strip().startswith("//") and ln.strip():
# Stop at the first non-empty line that is not a C++
@@ -106,9 +106,9 @@
', '.join(unsupported_features),))
# Evaluate the test.
- return self._evaluate_test(test, use_verify, lit_config)
+ return self._evaluate_test(test, lit_config, use_verify)
- def _evaluate_test(self, test, use_verify, lit_config):
+ def _evaluate_test(self, test, lit_config, use_verify):
name = test.path_in_suite[-1]
source_path = test.getSourcePath()
source_dir = os.path.dirname(source_path)
@@ -125,19 +125,11 @@
if use_verify:
cmd += ['-Xclang', '-verify']
expected_rc = 0
- out, err, rc = self.execute_command(cmd)
+ out,err,rc,report = self.execute_command(cmd)
if rc == expected_rc:
return lit.Test.PASS, ""
else:
- report = """Command: %s\n""" % ' '.join(["'%s'" % a
- for a in cmd])
- report += """Exit Code: %d\n""" % rc
- if out:
- report += """Standard Output:\n--\n%s--""" % out
- if err:
- report += """Standard Error:\n--\n%s--""" % err
- report += "\n\nExpected compilation to fail!"
- return lit.Test.FAIL, report
+ return lit.Test.FAIL, report + 'Expected compilation to fail!'
else:
exec_file = tempfile.NamedTemporaryFile(suffix="exe", delete=False)
exec_path = exec_file.name
@@ -147,17 +139,9 @@
compile_cmd = [self.cxx_under_test, '-o', exec_path,
source_path] + self.cpp_flags + self.ld_flags
cmd = compile_cmd
- out, err, exitCode = self.execute_command(cmd)
- if exitCode != 0:
- report = """Command: %s\n""" % ' '.join(["'%s'" % a
- for a in cmd])
- report += """Exit Code: %d\n""" % exitCode
- if out:
- report += """Standard Output:\n--\n%s--""" % out
- if err:
- report += """Standard Error:\n--\n%s--""" % err
- report += "\n\nCompilation failed unexpectedly!"
- return lit.Test.FAIL, report
+ out,err,rc,report = self.execute_command(cmd)
+ if rc != 0:
+ return lit.Test.FAIL, report + 'Compilation failed unexpectedly!'
cmd = []
if self.exec_env:
@@ -167,19 +151,11 @@
cmd.append(exec_path)
if lit_config.useValgrind:
cmd = lit_config.valgrindArgs + cmd
- out, err, exitCode = self.execute_command(cmd, source_dir)
- if exitCode != 0:
+ out,err,rc,report = self.execute_command(cmd, cwd=source_dir)
+ if rc != 0:
report = """Compiled With: %s\n""" % \
- ' '.join(["'%s'" % a for a in compile_cmd])
- report += """Command: %s\n""" % \
- ' '.join(["'%s'" % a for a in cmd])
- report += """Exit Code: %d\n""" % exitCode
- if out:
- report += """Standard Output:\n--\n%s--""" % out
- if err:
- report += """Standard Error:\n--\n%s--""" % err
- report += "\n\nCompiled test failed unexpectedly!"
- return lit.Test.FAIL, report
+ ' '.join(["'%s'" % a for a in compile_cmd]) + report
+ return lit.Test.FAIL, report + "Compiled test failed unexpectedly!"
finally:
try:
os.remove(exec_path)
@@ -196,8 +172,8 @@
self.src_root = None
self.obj_root = None
self.env = {}
- self.compile_flags = []
- self.library_paths = []
+ self.compile_flags = ['-nostdinc++']
+ self.library_paths = ['-nodefaultlibs']
self.link_flags = []
self.use_system_lib = False
self.use_clang_verify = False
@@ -231,20 +207,25 @@
self.configure_obj_root()
self.configure_use_system_lib()
self.configure_use_clang_verify()
- self.configure_env()
self.configure_std_flag()
self.configure_compile_flags()
self.configure_link_flags()
self.configure_sanitizer()
+ self.configure_warnings()
self.configure_features()
+ # Print some relevent configuration information.
+ self.lit_config.note('Using compile_flags: %s\n' % self.compile_flags)
+ self.lit_config.note('Using link_flags: %s\n' % self.link_flags)
+ self.lit_config.note('Using available_features: %s\n' %\
+ self.config.available_features)
def get_test_format(self):
return LibcxxTestFormat(
self.cxx,
- self.use_clang_verify,
- cpp_flags=['-nostdinc++'] + self.compile_flags,
- ld_flags=['-nodefaultlibs'] + self.link_flags,
- exec_env=self.env)
+ cpp_flags=self.compile_flags,
+ ld_flags=self.link_flags,
+ exec_env=self.env,
+ use_clang_verify=self.use_clang_verify)
def configure_cxx(self):
# Gather various compiler parameters.
@@ -359,54 +340,66 @@
self.compile_flags += ['-D_LIBCPP_HAS_NO_MONOTONIC_CLOCK']
def configure_compile_flags(self):
+ libcxx_headers = self.get_lit_conf('libcxx_headers',
+ os.path.join(self.src_root, 'include'))
# Configure extra compiler flags.
- self.compile_flags += ['-I' + self.src_root + '/include',
+ self.compile_flags += ['-I' + libcxx_headers,
'-I' + self.src_root + '/test/support']
if sys.platform.startswith('linux'):
self.compile_flags += ['-D__STDC_FORMAT_MACROS',
'-D__STDC_LIMIT_MACROS',
'-D__STDC_CONSTANT_MACROS']
+ compile_flags_str = self.get_lit_conf('compile_flags')
+ if compile_flags_str:
+ self.compile_flags += shlex.split(compile_flags_str)
def configure_link_flags(self):
+ libcxx_library = self.get_lit_conf('libcxx_library')
+ if self.use_system_lib and libcxx_library is not None:
+ self.lit_config.fatal(
+ 'conflicting options given: use_system_lib and libcxx_library')
+ # Link to the specific libc++ library if specified. Otherwise link to -lc++
+ # and add the build directory as a search path if use_system_lib is False.
+ if libcxx_library:
+ self.link_flags += [libcxx_library,
+ '-Wl,-rpath,' + os.path.dirname(libcxx_library)]
+ else:
+ self.link_flags += ['-lc++']
+ if not self.use_system_lib:
+ self.link_flags += ['-L' + self.obj_root + '/lib',
+ '-Wl,-rpath,' + os.path.join(self.obj_root, 'lib')]
# Configure library search paths
abi_library_path = self.get_lit_conf('abi_library_path', '')
- self.link_flags += ['-L' + self.obj_root + '/lib']
- if not self.use_system_lib:
- self.link_flags += ['-Wl,-rpath', '-Wl,' + self.obj_root + '/lib']
if abi_library_path:
self.link_flags += ['-L' + abi_library_path,
- '-Wl,-rpath', '-Wl,' + abi_library_path]
+ '-Wl,-rpath,' + abi_library_path]
# Configure libraries
- self.link_flags += ['-lc++']
- link_flags_str = self.get_lit_conf('link_flags')
- if link_flags_str is None:
- cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi')
- if cxx_abi == 'libstdc++':
- self.link_flags += ['-lstdc++']
- elif cxx_abi == 'libsupc++':
- self.link_flags += ['-lsupc++']
- elif cxx_abi == 'libcxxabi':
- self.link_flags += ['-lc++abi']
- elif cxx_abi == 'libcxxrt':
- self.link_flags += ['-lcxxrt']
- elif cxx_abi == 'none':
- pass
- else:
- self.lit_config.fatal(
- 'C++ ABI setting %s unsupported for tests' % cxx_abi)
-
- if sys.platform == 'darwin':
- self.link_flags += ['-lSystem']
- elif sys.platform.startswith('linux'):
- self.link_flags += ['-lgcc_eh', '-lc', '-lm', '-lpthread',
- '-lrt', '-lgcc_s']
- elif sys.platform.startswith('freebsd'):
- self.link_flags += ['-lc', '-lm', '-pthread', '-lgcc_s']
- else:
- self.lit_config.fatal("unrecognized system: %r" % sys.platform)
+ cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi')
+ if cxx_abi == 'libstdc++':
+ self.link_flags += ['-lstdc++']
+ elif cxx_abi == 'libsupc++':
+ self.link_flags += ['-lsupc++']
+ elif cxx_abi == 'libcxxabi':
+ self.link_flags += ['-lc++abi']
+ elif cxx_abi == 'libcxxrt':
+ self.link_flags += ['-lcxxrt']
+ elif cxx_abi == 'none':
+ pass
+ else:
+ self.lit_config.fatal(
+ 'C++ ABI setting %s unsupported for tests' % cxx_abi)
- self.lit_config.note(
- "inferred link_flags as: %r" % self.link_flags)
+ if sys.platform == 'darwin':
+ self.link_flags += ['-lSystem']
+ elif sys.platform.startswith('linux'):
+ self.link_flags += ['-lgcc_eh', '-lc', '-lm', '-lpthread',
+ '-lrt', '-lgcc_s']
+ elif sys.platform.startswith('freebsd'):
+ self.link_flags += ['-lc', '-lm', '-pthread', '-lgcc_s']
+ else:
+ self.lit_config.fatal("unrecognized system: %r" % sys.platform)
+
+ link_flags_str = self.get_lit_conf('link_flags')
if link_flags_str:
self.link_flags += shlex.split(link_flags_str)
@@ -423,7 +416,7 @@
self.config.available_features.add(std)
def configure_sanitizer(self):
- san = self.get_lit_conf('llvm_use_sanitizer', '').strip()
+ san = self.get_lit_conf('use_sanitizer', '').strip()
if san:
self.compile_flags += ['-fno-omit-frame-pointer']
if sys.platform.startswith('linux'):
@@ -445,6 +438,12 @@
self.lit_config.fatal('unsupported value for '
'libcxx_use_san: {0}'.format(san))
+ def configure_warnings(self):
+ enable_warn = self.get_lit_bool('enable_warnings')
+ if enable_warn:
+ self.compile_flags += ['-Wall', '-Wextra', '-pedantic',
+ '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER']
+
def configure_triple(self):
# Get or infer the target triple.
self.config.target_triple = self.get_lit_conf('target_triple')
@@ -470,13 +469,6 @@
self.lit_config.note(
"inferred target_triple as: %r" % self.config.target_triple)
- def configure_env(self):
- # Configure extra linker parameters.
- if sys.platform == 'darwin':
- if not self.use_system_lib:
- self.env['DYLD_LIBRARY_PATH'] = os.path.join(self.obj_root,
- 'lib')
-
# name: The name of this test suite.
config.name = 'libc++'
Index: test/lit.site.cfg.in
===================================================================
--- test/lit.site.cfg.in
+++ test/lit.site.cfg.in
@@ -6,7 +6,7 @@
config.python_executable = "@PYTHON_EXECUTABLE@"
config.enable_shared = @LIBCXX_ENABLE_SHARED@
config.cxx_abi = "@LIBCXX_CXX_ABI_LIBNAME@"
-config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@"
+config.use_sanitizer = "@LLVM_USE_SANITIZER@"
config.abi_library_path = "@LIBCXX_CXX_ABI_LIBRARY_PATH@"
# Let the main config do the real work.
Index: www/index.html
===================================================================
--- www/index.html
+++ www/index.html
@@ -475,6 +475,7 @@
<type_traits>
Excellent notes by Marshall Clow
Status of debug mode
+LIT usage guide
Index: www/lit_usage.html
===================================================================
--- /dev/null
+++ www/lit_usage.html
@@ -0,0 +1,168 @@
+
+
+
+
+
+ Testing libc++ using LIT
+
+
+
+
+
+
+
+
+
+
+
Testing libc++ using LIT
+
+
+libc++ uses LIT to configure and run it's tests. The primary way to run the
+libc++ tests is by using make check-libcxx
. However since libc++
+can be used in any number of possible configurations it is important to
+customize the way LIT builds and runs the tests. This guide provides
+information on how to use LIT directly to test libc++.
+
+
+Documentation for LIT can be found
+here .
+
+
+
+
Getting Started
+
+
+After building libc++ use the following commands before you start using LIT to
+test.
+
+
+ alias lit='python path/to/llvm/utils/lit/lit.py'
+ ln -s path/to/libcxx-build/test/lit.site.cfg path/to/libcxx/test/lit.site.cfg
+
+
+You can now run the libc++ tests by running:
+
+
+ cd path/to/libcxx
+ lit -sv ./test
+
+
+To only run a subsection of the tests use:
+
+ lit -sv test/numerics # Run only the numeric tests
+
+
+
+
Customization Options
+
+
+libc++'s testsuite provides multiple options to configure the way the tests
+are build and run. To use these options you pass them on the LIT command line
+as --param NAME
or --param NAME=VALUE
. Some options
+have default values specified during CMake's configuration. Passing the option
+on the command line will override the default.
+
+
+
+
libcxx_headers=<path/to/headers>
+
+Specify the libc++ headers that are tested. By default the headers in the source
+tree are used.
+
+
+
+
+
libcxx_library=<path/to/libc++.so>
+
+Specify the libc++ library that is tested. By default the library in the build
+directory is used. This option has no effect if use_system_lib
is provided.
+
+
+
+
+
use_system_lib=<bool>
+
+Default: False
+Enable or disable testing against the installed version of libc++ library.
+Note: This does not use the installed headers.
+
+
+
+
+
compile_flags="<list-of-args>"
+
+Specify an additional list of compile flags to use.
+Note: This options should not be used to change the standard version used.
+
+
+
+
+
link_flags="<list-of-args>"
+
+Specify an additional list of linker flags to use.
+
+
+
+
+
std=<standard version>
+
+Values: c++98, c++03, c++11, c++1z, c++14
+Change the standard version used when building the tests.
+
+
+
+
+
use_sanitizer=<sanitizer name>
+
+Values: Memory, MemoryWithOrigins, Address, Undefined
+Run the tests using the given sanitizer. If LLVM_USE_SANITIZER
+was given when building libc++ then that sanitizer will be used by default.
+
+
+
+
+
enable_warnings[=<bool>]
+
+Default: False
+Enable -Wall -Wextra -pedantic
as well as disabling
+the system header pragmas.
+
+
+
+
+
+
+