[libcxx] r250319 - [libcxx] Make it drastically simpler to link libc++.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 14 12:54:03 PDT 2015


Author: ericwf
Date: Wed Oct 14 14:54:03 2015
New Revision: 250319

URL: http://llvm.org/viewvc/llvm-project?rev=250319&view=rev
Log:
[libcxx] Make it drastically simpler to link libc++.

Summary:
Currently on most platforms you have to manually link the c++ abi library used with libc++ whenever you use libc++. So your typical libc++ command like invocation might look like:

```
clang++ -stdlib=libc++ foo.cpp -lc++abi
```

Having to manually link `libc++abi.so` makes it harder for libc++ to be used generically. This patch fixes that by generating a linker script for `libc++.so` that correctly links the ABI library. On linux the linker script for libc++abi would look like:

```
# libc++.so
INPUT(libc++.so.1 -lc++abi)
```

With the linker script you can now use libc++ using only `-stdlib=libc++`. This is the technique that is used on FreeBSD in ordered to link cxxrt and I think it's the best approach to make our users lives simpler.

The CMake option used to enable this is `LIBCXX_ENABLE_ABI_LINKER_SCRIPT`. In future I would like to enable this by default on all platforms except for Darwin.

Reviewers: mclow.lists, danalbert, rsmith, jroelofs, EricWF

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D12508

Added:
    libcxx/trunk/utils/gen_link_script/
    libcxx/trunk/utils/gen_link_script/gen_link_script.py   (with props)
Modified:
    libcxx/trunk/CMakeLists.txt
    libcxx/trunk/lib/CMakeLists.txt
    libcxx/trunk/test/CMakeLists.txt

Modified: libcxx/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/CMakeLists.txt?rev=250319&r1=250318&r2=250319&view=diff
==============================================================================
--- libcxx/trunk/CMakeLists.txt (original)
+++ libcxx/trunk/CMakeLists.txt Wed Oct 14 14:54:03 2015
@@ -69,6 +69,11 @@ set_property(CACHE LIBCXX_CXX_ABI PROPER
 
 option(LIBCXX_ENABLE_STATIC_ABI_LIBRARY "Statically link the ABI library" OFF)
 
+# Generate and install a linker script inplace of libc++.so. The linker script
+# will link libc++ to the correct ABI library.
+option(LIBCXX_ENABLE_ABI_LINKER_SCRIPT
+      "Use and install a linker script for the given ABI library" OFF)
+
 # Build libc++abi with libunwind. We need this option to determine whether to
 # link with libunwind or libgcc_s while running the test cases.
 option(LIBCXXABI_USE_LLVM_UNWINDER "Build and use the LLVM unwinder." OFF)
@@ -153,6 +158,21 @@ if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY)
   endif()
 endif()
 
+if (LIBCXX_ENABLE_ABI_LINKER_SCRIPT)
+    if (APPLE)
+      message(FATAL_ERROR "LIBCXX_ENABLE_ABI_LINKER_SCRIPT cannot be used on APPLE targets")
+    endif()
+    if (NOT PYTHONINTERP_FOUND)
+      message(FATAL_ERROR "LIBCXX_ENABLE_ABI_LINKER_SCRIPT requires python but it was not found.")
+    endif()
+endif()
+
+if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY AND LIBCXX_ENABLE_ABI_LINKER_SCRIPT)
+    message(FATAL_ERROR "Conflicting options given.
+        LIBCXX_ENABLE_STATIC_ABI_LIBRARY cannot be specified with
+        LIBCXX_ENABLE_ABI_LINKER_SCRIPT")
+endif()
+
 #===============================================================================
 # Configure System
 #===============================================================================

Modified: libcxx/trunk/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/lib/CMakeLists.txt?rev=250319&r1=250318&r2=250319&view=diff
==============================================================================
--- libcxx/trunk/lib/CMakeLists.txt (original)
+++ libcxx/trunk/lib/CMakeLists.txt Wed Oct 14 14:54:03 2015
@@ -133,11 +133,40 @@ set_target_properties(cxx
     SOVERSION     "${LIBCXX_ABI_VERSION}"
   )
 
+# Generate a linker script inplace of a libc++.so symlink. Rerun this command
+# after cxx builds.
+if (LIBCXX_ENABLE_ABI_LINKER_SCRIPT)
+  # Get the name of the ABI library and handle the case where CXXABI_LIBNAME
+  # is a target name and not a library. Ex cxxabi_shared.
+  set(SCRIPT_ABI_LIBNAME "${CXXABI_LIBNAME}")
+  if (SCRIPT_ABI_LIBNAME STREQUAL "cxxabi_shared")
+    set("${SCRIPT_ABI_LIBNAME}" "c++abi")
+  endif()
+  # Generate a linker script inplace of a libc++.so symlink. Rerun this command
+  # after cxx builds.
+  add_custom_command(TARGET cxx POST_BUILD
+    COMMAND
+      ${PYTHON_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/utils/gen_link_script/gen_link_script.py
+    ARGS
+      "$<TARGET_LINKER_FILE:cxx>"
+      "${SCRIPT_ABI_LIBNAME}"
+    WORKING_DIRECTORY ${LIBCXX_BUILD_DIR}
+  )
+endif()
+
+
 if (LIBCXX_INSTALL_LIBRARY)
   install(TARGETS cxx
     LIBRARY DESTINATION lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT libcxx
     ARCHIVE DESTINATION lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT libcxx
     )
+  # NOTE: This install command must go after the cxx install command otherwise
+  # it will not be executed after the library symlinks are installed.
+  if (LIBCXX_ENABLE_ABI_LINKER_SCRIPT)
+    install(FILES "$<TARGET_LINKER_FILE:cxx>"
+      DESTINATION lib${LIBCXX_LIBDIR_SUFFIX}
+      COMPONENT libcxx)
+  endif()
 endif()
 
 if (NOT CMAKE_CONFIGURATION_TYPES AND (LIBCXX_INSTALL_LIBRARY OR

Modified: libcxx/trunk/test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/CMakeLists.txt?rev=250319&r1=250318&r2=250319&view=diff
==============================================================================
--- libcxx/trunk/test/CMakeLists.txt (original)
+++ libcxx/trunk/test/CMakeLists.txt Wed Oct 14 14:54:03 2015
@@ -17,10 +17,11 @@ pythonize_bool(LIBCXX_GENERATE_COVERAGE)
 pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)
 
 # The tests shouldn't link to any ABI library when it has been linked into
-# libc++ statically.
-if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY)
+# libc++ statically or via a linker script.
+if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY OR LIBCXX_ENABLE_ABI_LINKER_SCRIPT)
   set(LIBCXX_CXX_ABI_LIBNAME "none")
 endif()
+
 set(LIBCXX_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
     "TargetInfo to use when setting up test environment.")
 set(LIBCXX_EXECUTOR "None" CACHE STRING

Added: libcxx/trunk/utils/gen_link_script/gen_link_script.py
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/gen_link_script/gen_link_script.py?rev=250319&view=auto
==============================================================================
--- libcxx/trunk/utils/gen_link_script/gen_link_script.py (added)
+++ libcxx/trunk/utils/gen_link_script/gen_link_script.py Wed Oct 14 14:54:03 2015
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+import os
+import sys
+
+def print_and_exit(msg):
+    sys.stderr.write(msg + '\n')
+    sys.exit(1)
+
+def usage_and_exit():
+    print_and_exit("Usage: ./gen_link_script.py [--help] [--dryrun] <path/to/libcxx.so> <abi_libname>")
+
+def help_and_exit():
+    help_msg = \
+"""Usage
+
+  gen_link_script.py [--help] [--dryrun] <path/to/libcxx.so> <abi_libname>
+
+  Generate a linker script that links libc++ to the proper ABI library.
+  The script replaces the specified libc++ symlink.
+  An example script for c++abi would look like "INPUT(libc++.so.1 -lc++abi)".
+
+Arguments
+  <path/to/libcxx.so> - The top level symlink to the versioned libc++ shared
+                        library. This file is replaced with a linker script.
+  <abi_libname>       - The name of the ABI library to use in the linker script.
+                        The name must be one of [c++abi, stdc++, supc++, cxxrt].
+
+Exit Status:
+  0 if OK,
+  1 if the action failed.
+"""
+    print_and_exit(help_msg)
+
+def parse_args():
+    args = list(sys.argv)
+    del args[0]
+    if len(args) == 0:
+        usage_and_exit()
+    if args[0] == '--help':
+        help_and_exit()
+    dryrun = '--dryrun' == args[0]
+    if dryrun:
+        del args[0]
+    if len(args) != 2:
+        usage_and_exit()
+    symlink_file = args[0]
+    abi_libname = args[1]
+    return dryrun, symlink_file, abi_libname
+
+def main():
+    dryrun, symlink_file, abi_libname = parse_args()
+
+    # Check that the given libc++.so file is a valid symlink.
+    if not os.path.islink(symlink_file):
+        print_and_exit("symlink file %s is not a symlink" % symlink_file)
+
+    # Read the symlink so we know what libc++ to link to in the linker script.
+    linked_libcxx = os.readlink(symlink_file)
+
+    # Check that the abi_libname is one of the supported values.
+    supported_abi_list = ['c++abi', 'stdc++', 'supc++', 'cxxrt']
+    if abi_libname not in supported_abi_list:
+        print_and_exit("abi name '%s' is not supported: Use one of %r" %
+                        (abi_libname, supported_abi_list))
+
+    # Generate the linker script contents and print the script and destination
+    # information.
+    contents = "INPUT(%s -l%s)" % (linked_libcxx, abi_libname)
+    print("GENERATING SCRIPT: '%s' as file %s" % (contents, symlink_file))
+
+    # Remove the existing libc++ symlink and replace it with the script.
+    if not dryrun:
+        os.unlink(symlink_file)
+        with open(symlink_file, 'w') as f:
+            f.write(contents + "\n")
+
+
+if __name__ == '__main__':
+    main()

Propchange: libcxx/trunk/utils/gen_link_script/gen_link_script.py
------------------------------------------------------------------------------
    svn:executable = *




More information about the cfe-commits mailing list