[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