[libcxxabi] r212672 - Add lit configs for libcxxabi tests.

Dan Albert danalbert at google.com
Wed Jul 9 19:20:12 PDT 2014


Author: danalbert
Date: Wed Jul  9 21:20:11 2014
New Revision: 212672

URL: http://llvm.org/viewvc/llvm-project?rev=212672&view=rev
Log:
Add lit configs for libcxxabi tests.

This makes running libcxxabi tests on Linux _much_ easier.
Adds a check-libcxxabi target to cmake.

Also defaults to building a dynamic libc++abi. This is so that the
default options still test the libc++abi that is being built. There are
two problems with testing a static libc++abi. In the case of a
standalone build, the tests will link the system's libc++, which might
not have been built against our libc++abi. In the case of an in tree
build, libc++ will prefer a dynamic libc++abi from the system over a
static libc++abi from the output directory.

Added:
    libcxxabi/trunk/test/CMakeLists.txt
    libcxxabi/trunk/test/lit.cfg
    libcxxabi/trunk/test/lit.site.cfg.in
Modified:
    libcxxabi/trunk/CMakeLists.txt
    libcxxabi/trunk/src/CMakeLists.txt
    libcxxabi/trunk/www/index.html

Modified: libcxxabi/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/CMakeLists.txt?rev=212672&r1=212671&r2=212672&view=diff
==============================================================================
--- libcxxabi/trunk/CMakeLists.txt (original)
+++ libcxxabi/trunk/CMakeLists.txt Wed Jul  9 21:20:11 2014
@@ -53,6 +53,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURR
   if(EXISTS ${LLVMCONFIG_FILE})
     list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}")
     include(${LLVMCONFIG_FILE})
+    include("${LLVM_CMAKE_PATH}/AddLLVM.cmake")
   else()
     message(FATAL_ERROR "Not found: ${LLVMCONFIG_FILE}")
   endif()
@@ -91,6 +92,8 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURR
   set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
 
   set(LIBCXXABI_BUILT_STANDALONE 1)
+else()
+  set(LLVM_LIT "${CMAKE_SOURCE_DIR}/utils/lit/lit.py")
 endif()
 
 #===============================================================================
@@ -101,7 +104,26 @@ endif()
 option(LIBCXXABI_ENABLE_ASSERTIONS "Enable assertions independent of build mode." ON)
 option(LIBCXXABI_ENABLE_PEDANTIC "Compile with pedantic enabled." ON)
 option(LIBCXXABI_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF)
-option(LIBCXXABI_ENABLE_SHARED "Build libc++abi as a shared library." OFF)
+
+# Default to building a shared library so that the default options still test
+# the libc++abi that is being built. There are two problems with testing a
+# static libc++abi. In the case of a standalone build, the tests will link the
+# system's libc++, which might not have been built against our libc++abi. In the
+# case of an in tree build, libc++ will prefer a dynamic libc++abi from the
+# system over a static libc++abi from the output directory.
+option(LIBCXXABI_ENABLE_SHARED "Build libc++abi as a shared library." ON)
+
+find_path(
+  LIBCXXABI_LIBCXX_INCLUDES
+  vector
+  PATHS ${LIBCXXABI_LIBCXX_INCLUDES}
+        ${CMAKE_BINARY_DIR}/${LIBCXXABI_LIBCXX_INCLUDES}
+        ${LLVM_MAIN_SRC_DIR}/projects/libcxx/include
+        ${LLVM_INCLUDE_DIR}/c++/v1
+  )
+
+set(LIBCXXABI_LIBCXX_INCLUDES "${LIBCXXABI_LIBCXX_INCLUDES}" CACHE STRING
+    "Specify path to libc++ includes." FORCE)
 
 #===============================================================================
 # Configure System
@@ -210,3 +232,16 @@ include_directories(include)
 # Add source code. This also contains all of the logic for deciding linker flags
 # soname, etc...
 add_subdirectory(src)
+
+if(NOT LIBCXXABI_ENABLE_SHARED)
+  # TODO: Fix the libc++ cmake files so that libc++abi can be statically linked.
+  # As it is now, libc++ will prefer linking against a dynamic libc++abi in the
+  # system library paths over a static libc++abi in the out directory. This
+  # would test the system library rather than the one we just built, which isn't
+  # very helpful.
+  message(WARNING "The libc++abi tests are currently only valid when "
+                  "LIBCXXABI_ENABLE_SHARED is on, no check target will be "
+                  "available!")
+else()
+  add_subdirectory(test)
+endif()

Modified: libcxxabi/trunk/src/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/CMakeLists.txt?rev=212672&r1=212671&r2=212672&view=diff
==============================================================================
--- libcxxabi/trunk/src/CMakeLists.txt (original)
+++ libcxxabi/trunk/src/CMakeLists.txt Wed Jul  9 21:20:11 2014
@@ -48,13 +48,7 @@ else()
     )
 endif()
 
-if (LIBCXXABI_LIBCXX_INCLUDES)
-  include_directories("${LIBCXXABI_LIBCXX_INCLUDES}")
-elseif (NOT LIBCXXABI_BUILT_STANDALONE)
-  include_directories("${LLVM_MAIN_SRC_DIR}/projects/libcxx/include")
-else()
-  include_directories("${LLVM_INCLUDE_DIR}/c++/v1")
-endif()
+include_directories("${LIBCXXABI_LIBCXX_INCLUDES}")
 
 # Generate library list.
 set(libraries ${LIBCXXABI_CXX_ABI_LIBRARIES})

Added: libcxxabi/trunk/test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/CMakeLists.txt?rev=212672&view=auto
==============================================================================
--- libcxxabi/trunk/test/CMakeLists.txt (added)
+++ libcxxabi/trunk/test/CMakeLists.txt Wed Jul  9 21:20:11 2014
@@ -0,0 +1,28 @@
+macro(pythonize_bool var)
+  if (${var})
+    set(${var} True)
+  else()
+    set(${var} False)
+  endif()
+endmacro()
+
+set(LIBCXXABI_COMPILER ${CMAKE_CXX_COMPILER})
+set(LIBCXXABI_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/..)
+set(LIBCXXABI_BINARY_DIR ${CMAKE_BINARY_DIR})
+pythonize_bool(LIBCXXABI_ENABLE_SHARED)
+
+set(AUTO_GEN_COMMENT "## Autogenerated by libcxxabi configuration.\n# Do not edit!")
+configure_file(
+  ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+  ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+  @ONLY)
+
+set(LIBCXXABI_TEST_DEPS cxxabi)
+if (NOT LIBCXXABI_BUILT_STANDALONE)
+  list(APPEND LIBCXXABI_TEST_DEPS cxx)
+endif()
+
+add_lit_testsuite(check-libcxxabi "Running libcxxabi tests"
+  ${CMAKE_CURRENT_BINARY_DIR}
+  DEPENDS ${LIBCXXABI_TEST_DEPS}
+  )

Added: libcxxabi/trunk/test/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/lit.cfg?rev=212672&view=auto
==============================================================================
--- libcxxabi/trunk/test/lit.cfg (added)
+++ libcxxabi/trunk/test/lit.cfg Wed Jul  9 21:20:11 2014
@@ -0,0 +1,236 @@
+# -*- Python -*- vim: set syntax=python tabstop=4 expandtab cc=80:
+
+# Configuration file for the 'lit' test runner.
+
+import errno
+import os
+import platform
+import re
+import shlex
+import signal
+import subprocess
+import sys
+import tempfile
+import time
+
+import lit.Test
+import lit.formats
+import lit.util
+
+class LibcxxabiTestFormat(lit.formats.FileBasedTest):
+    """
+    Custom test format handler for use with the test format use by libc++abi.
+    """
+
+    def __init__(self, cxx_under_test, cpp_flags, ld_flags, exec_env):
+        self.cxx_under_test = cxx_under_test
+        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
+
+    def execute(self, test, lit_config):
+        while True:
+            try:
+                return self._execute(test, lit_config)
+            except OSError, oe:
+                if oe.errno != errno.ETXTBSY:
+                    raise
+                time.sleep(0.1)
+
+    def _execute(self, test, lit_config):
+        # Extract test metadata from the test file.
+        requires = []
+        with open(test.getSourcePath()) as f:
+            for ln in f:
+                if 'XFAIL:' in ln:
+                    items = ln[ln.index('XFAIL:') + 6:].split(',')
+                    test.xfails.extend([s.strip() for s in items])
+                elif 'REQUIRES:' in ln:
+                    items = ln[ln.index('REQUIRES:') + 9:].split(',')
+                    requires.extend([s.strip() for s in items])
+                elif not ln.startswith("//") and ln.strip():
+                    # Stop at the first non-empty line that is not a C++
+                    # comment.
+                    break
+
+        # Check that we have the required features.
+        #
+        # FIXME: For now, this is cribbed from lit.TestRunner, to avoid
+        # introducing a dependency there. What we more ideally would like to do
+        # is lift the "requires" handling to be a core lit framework feature.
+        missing_required_features = [f for f in requires
+                                     if f not in test.config.available_features]
+        if missing_required_features:
+            return (lit.Test.UNSUPPORTED,
+                    "Test requires the following features: %s" % (
+                      ', '.join(missing_required_features),))
+
+        # Evaluate the test.
+        return self._evaluate_test(test, lit_config)
+
+    def _evaluate_test(self, test, lit_config):
+        name = test.path_in_suite[-1]
+        source_path = test.getSourcePath()
+        source_dir = os.path.dirname(source_path)
+
+        # If this is a compile (failure) test, build it and check for failure.
+        exec_file = tempfile.NamedTemporaryFile(suffix="exe", delete=False)
+        exec_path = exec_file.name
+        exec_file.close()
+
+        try:
+            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
+
+            cmd = []
+            if self.exec_env:
+                cmd.append('env')
+                cmd.extend('%s=%s' % (name, value)
+                           for name,value in self.exec_env.items())
+            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:
+                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
+        finally:
+            try:
+                os.remove(exec_path)
+            except:
+                pass
+        return lit.Test.PASS, ""
+
+# name: The name of this test suite.
+config.name = 'libc++abi'
+
+# suffixes: A list of file extensions to treat as test files.
+config.suffixes = ['.cpp']
+
+# test_source_root: The root path where tests are located.
+config.test_source_root = os.path.dirname(__file__)
+
+# Gather various compiler parameters.
+cxx_under_test = lit_config.params.get('cxx_under_test', None)
+if cxx_under_test is None:
+    cxx_under_test = getattr(config, 'cxx_under_test', None)
+
+    # If no specific cxx_under_test was given, attempt to infer it as clang++.
+    if cxx_under_test is None:
+        clangxx = lit.util.which('clang++', config.environment['PATH'])
+        if clangxx is not None:
+            cxx_under_test = clangxx
+    lit_config.note("inferred cxx_under_test as: %r" % (cxx_under_test,))
+if cxx_under_test is None:
+    lit_config.fatal('must specify user parameter cxx_under_test '
+                     '(e.g., --param=cxx_under_test=clang++)')
+
+libcxxabi_src_root = lit_config.params.get('libcxxabi_src_root', None)
+if libcxxabi_src_root is None:
+    libcxxabi_src_root = getattr(config, 'libcxxabi_src_root', None)
+    if libcxxabi_src_root is None:
+        libcxxabi_src_root = os.path.dirname(config.test_source_root)
+
+libcxxabi_obj_root = lit_config.params.get('libcxxabi_obj_root', None)
+if libcxxabi_obj_root is None:
+    libcxxabi_obj_root = getattr(config, 'libcxxabi_obj_root', None)
+    if libcxxabi_obj_root is None:
+        libcxxabi_obj_root = libcxxabi_src_root
+
+libcxx_includes = lit_config.params.get('libcxx_includes', None)
+if libcxx_includes is None:
+    libcxx_includes = getattr(config, 'libcxx_includes', None)
+    if libcxx_includes is None:
+        lit_config.fatal("libcxx_includes must be defined")
+
+enable_shared = lit_config.params.get('enable_shared', None)
+if enable_shared is None:
+    enable_shared = getattr(config, 'enable_shared', None)
+    if enable_shared is None:
+        lit_config.fatal("enable_shared must be defined")
+
+link_flags = []
+link_flags_str = lit_config.params.get('link_flags', None)
+if link_flags_str is None:
+    link_flags_str = getattr(config, 'link_flags', None)
+    if link_flags_str is None:
+        if enable_shared:
+            link_flags += ['-lc++abi']
+        if sys.platform == 'darwin':
+            link_flags += ['-lSystem']
+        elif sys.platform == 'linux2':
+            link_flags += ['-lgcc_eh', '-lc', '-lm', '-lpthread', '-lgcc_s']
+        else:
+            lit_config.fatal("unrecognized system")
+
+        lit_config.note("inferred link_flags as: %r" % (link_flags,))
+if link_flags_str is not None:
+    link_flags += shlex.split(link_flags_str)
+
+# Configure extra compiler flags.
+include_paths = ['-I' + libcxxabi_src_root + '/include',
+                 '-I' + libcxx_includes]
+library_paths = ['-L' + libcxxabi_obj_root + '/lib']
+compile_flags = ['-std=c++11']
+
+# Configure extra linker parameters.
+exec_env = {}
+if sys.platform == 'darwin':
+    exec_env['DYLD_LIBRARY_PATH'] = os.path.join(libcxxabi_obj_root, 'lib')
+elif sys.platform == 'linux2':
+    link_flags += ['-Wl,-R', libcxxabi_obj_root + '/lib']
+else:
+    lit_config.fatal("unrecognized system")
+
+config.test_format = LibcxxabiTestFormat(
+    cxx_under_test,
+    cpp_flags = ['-nostdinc++'] + compile_flags + include_paths,
+    ld_flags = ['-nodefaultlibs'] + library_paths + ['-lc++'] + link_flags,
+    exec_env = exec_env)
+
+# Get or infer the target triple.
+config.target_triple = lit_config.params.get('target_triple', None)
+# If no target triple was given, try to infer it from the compiler under test.
+if config.target_triple is None:
+    config.target_triple = lit.util.capture(
+        [cxx_under_test, '-dumpmachine']).strip()
+    lit_config.note("inferred target_triple as: %r" % (config.target_triple,))

Added: libcxxabi/trunk/test/lit.site.cfg.in
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/lit.site.cfg.in?rev=212672&view=auto
==============================================================================
--- libcxxabi/trunk/test/lit.site.cfg.in (added)
+++ libcxxabi/trunk/test/lit.site.cfg.in Wed Jul  9 21:20:11 2014
@@ -0,0 +1,10 @@
+ at AUTO_GEN_COMMENT@
+config.cxx_under_test        = "@LIBCXXABI_COMPILER@"
+config.libcxxabi_src_root    = "@LIBCXXABI_SOURCE_DIR@"
+config.libcxxabi_obj_root    = "@LIBCXXABI_BINARY_DIR@"
+config.python_executable     = "@PYTHON_EXECUTABLE@"
+config.enable_shared         = @LIBCXXABI_ENABLE_SHARED@
+config.libcxx_includes       = "@LIBCXXABI_LIBCXX_INCLUDES@"
+
+# Let the main config do the real work.
+lit_config.load_config(config, "@LIBCXXABI_SOURCE_DIR@/test/lit.cfg")

Modified: libcxxabi/trunk/www/index.html
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/www/index.html?rev=212672&r1=212671&r2=212672&view=diff
==============================================================================
--- libcxxabi/trunk/www/index.html (original)
+++ libcxxabi/trunk/www/index.html Wed Jul  9 21:20:11 2014
@@ -92,10 +92,19 @@
   <ul>
   <li><code>cd libcxxabi</code></li>
   <li><code>mkdir build && cd build</code></li>
-  <li><code>cmake -DLIBCXXABI_LIBCXX_INCLUDES=path/to/libcxx/include .. # on linux you may need -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++</code></li>
+  <li><code>cmake -DLIBCXXABI_LIBCXX_INCLUDES=path/to/libcxx/include .. # on
+    linux you may need -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++</code></li>
   <li><code>make</code></li>
   </ul>
 
+  <p>To run the tests:</p>
+  <ul>
+  <li><code>make check-libcxxabi</code></li>
+  </ul>
+  <p>Note: in a standalone build, the system's libc++ will be used for tests. If
+  the system's libc++ was statically linked against libc++abi (or linked against
+  a different ABI library), this may interfere with test results.</p>
+
   <p>Send discussions to the
   (<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev">clang mailing list</a>).</p>
 





More information about the cfe-commits mailing list