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', '-Werror', + '-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. +

    + +

    +You can now run the libc++ tests by running: +

    + +

    +To only run a subsection of the tests use: +

    + + +

    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 -Werror as well as disabling +the system header pragmas. +
    +

    + + +
    + +