From 3bf8a9cb678c26268c5d1ba6074f68632b825ca8 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Sun, 9 Oct 2016 21:34:03 +0000 Subject: [PATCH] Fix linker script generation for in-tree builds git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@283700 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 8 ++-- cmake/Modules/HandleLibcxxFlags.cmake | 8 ++++ lib/CMakeLists.txt | 47 +++++++++++++----------- test/CMakeLists.txt | 18 ++++++--- utils/gen_link_script/gen_link_script.py | 10 +++-- 5 files changed, 56 insertions(+), 35 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b7e36334e..27cddec0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -270,13 +270,13 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR}) # LIBCXX_CXX_FLAGS: General flags for both the compiler and linker. # LIBCXX_COMPILE_FLAGS: Compile only flags. # LIBCXX_LINK_FLAGS: Linker only flags. -# LIBCXX_LIBRARIES: Private libraries libc++ is linked to. -# LIBCXX_LIBRARIES_PUBLIC: Public libraries libc++ is linked to, -# also exposed in the linker script. +# LIBCXX_LIBRARIES: libraries libc++ is linked to. +# LIBCXX_INTERFACE_LIBRARIES: Libraries that must be linked when using libc++ +# There libraries are exposed in the linker script. set(LIBCXX_COMPILE_FLAGS "") set(LIBCXX_LINK_FLAGS "") set(LIBCXX_LIBRARIES "") -set(LIBCXX_LIBRARIES_PUBLIC "") +set(LIBCXX_INTERFACE_LIBRARIES "") # Include macros for adding and removing libc++ flags. include(HandleLibcxxFlags) diff --git a/cmake/Modules/HandleLibcxxFlags.cmake b/cmake/Modules/HandleLibcxxFlags.cmake index 325c1bdf7..7077c6e38 100644 --- a/cmake/Modules/HandleLibcxxFlags.cmake +++ b/cmake/Modules/HandleLibcxxFlags.cmake @@ -188,6 +188,14 @@ macro(add_library_flags_if condition) endif() endmacro() +# Add a list of libraries or link flags to 'LIBCXX_LIBRARIES'. +macro(add_interface_library) + foreach(lib ${ARGN}) + list(APPEND LIBCXX_LIBRARIES ${lib}) + list(APPEND LIBCXX_INTERFACE_LIBRARIES ${lib}) + endforeach() +endmacro() + # Turn a comma separated CMake list into a space separated string. macro(split_list listname) string(REPLACE ";" " " ${listname} "${${listname}}") diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 154be0cc8..12fbf886b 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -33,16 +33,19 @@ add_link_flags_if(LIBCXX_CXX_ABI_LIBRARY_PATH "-L${LIBCXX_CXX_ABI_LIBRARY_PATH}" add_library_flags_if(LIBCXX_COVERAGE_LIBRARY "${LIBCXX_COVERAGE_LIBRARY}") +if (APPLE AND (LIBCXX_CXX_ABI_LIBNAME STREQUAL "libcxxabi" OR + LIBCXX_CXX_ABI_LIBNAME STREQUAL "none")) + set(LIBCXX_OSX_REEXPORT_SYSTEM_ABI_LIBRARY ON) +endif() + if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) add_library_flags("-Wl,--whole-archive" "-Wl,-Bstatic") add_library_flags("${LIBCXX_CXX_ABI_LIBRARY}") add_library_flags("-Wl,-Bdynamic" "-Wl,--no-whole-archive") -elseif (APPLE AND (LIBCXX_CXX_ABI_LIBNAME STREQUAL "libcxxabi" OR - LIBCXX_CXX_ABI_LIBNAME STREQUAL "none")) - # Apple re-exports libc++abi in libc++, so don't make it public +elseif (LIBCXX_OSX_REEXPORT_SYSTEM_ABI_LIBRARY) add_library_flags("${LIBCXX_CXX_ABI_LIBRARY}") -else() - list(APPEND LIBCXX_LIBRARIES_PUBLIC "${LIBCXX_CXX_ABI_LIBRARY}") +else () + add_interface_library("${LIBCXX_CXX_ABI_LIBRARY}") endif() if (APPLE AND LLVM_USE_SANITIZER) @@ -85,7 +88,13 @@ add_library_flags_if(LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB atomic) # Add the unwinder library. if (LIBCXXABI_USE_LLVM_UNWINDER) - list(APPEND LIBCXX_LIBRARIES_PUBLIC unwind) + if (TARGET unwind_shared) + add_interface_library(unwind_shared) + elseif (TARGET unwind_static) + add_interface_library(unwind_static) + else() + add_interface_library(unwind) + endif() endif() # Setup flags. @@ -94,8 +103,7 @@ if (NOT WIN32) endif() add_link_flags_if_supported(-nodefaultlibs) -if ( APPLE AND (LIBCXX_CXX_ABI_LIBNAME STREQUAL "libcxxabi" OR - LIBCXX_CXX_ABI_LIBNAME STREQUAL "none")) +if (LIBCXX_OSX_REEXPORT_SYSTEM_ABI_LIBRARY) if (NOT DEFINED LIBCXX_LIBCPPABI_VERSION) set(LIBCXX_LIBCPPABI_VERSION "2") # Default value execute_process( @@ -164,9 +172,7 @@ set(LIBCXX_TARGETS) # Build the shared library. if (LIBCXX_ENABLE_SHARED) add_library(cxx_shared SHARED $) - target_link_libraries(cxx_shared - PRIVATE ${LIBCXX_LIBRARIES} - PUBLIC ${LIBCXX_LIBRARIES_PUBLIC}) + target_link_libraries(cxx_shared ${LIBCXX_LIBRARIES}) set_target_properties(cxx_shared PROPERTIES LINK_FLAGS "${LIBCXX_LINK_FLAGS}" @@ -180,9 +186,7 @@ endif() # Build the static library. if (LIBCXX_ENABLE_STATIC) add_library(cxx_static STATIC $) - target_link_libraries(cxx_static - PRIVATE ${LIBCXX_LIBRARIES} - PUBLIC ${LIBCXX_LIBRARIES_PUBLIC}) + target_link_libraries(cxx_static ${LIBCXX_LIBRARIES}) set_target_properties(cxx_static PROPERTIES LINK_FLAGS "${LIBCXX_LINK_FLAGS}" @@ -244,15 +248,16 @@ endif() if (LIBCXX_ENABLE_SHARED AND 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(LIBCXX_LIBRARIES_PUBLIC_NAMES) - foreach(lib ${LIBCXX_LIBRARIES_PUBLIC}) - if (lib STREQUAL "cxxabi_shared") - list(APPEND LIBCXX_LIBRARIES_PUBLIC_NAMES "c++abi") + set(LIBCXX_INTERFACE_LIBRARY_NAMES) + foreach(lib ${LIBCXX_INTERFACE_LIBRARIES}) + # FIXME: Handle cxxabi_static and unwind_static. + if (TARGET ${lib}) + list(APPEND LIBCXX_INTERFACE_LIBRARY_NAMES "$") else() - list(APPEND LIBCXX_LIBRARIES_PUBLIC_NAMES "${lib}") + list(APPEND LIBCXX_INTERFACE_LIBRARY_NAMES "${lib}") endif() endforeach() - + #split_list(LIBCXX_INTERFACE_LIBRARY_NAMES) # Generate a linker script inplace of a libc++.so symlink. Rerun this command # after cxx builds. add_custom_command(TARGET cxx_shared POST_BUILD @@ -260,7 +265,7 @@ if (LIBCXX_ENABLE_SHARED AND LIBCXX_ENABLE_ABI_LINKER_SCRIPT) ${PYTHON_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/utils/gen_link_script/gen_link_script.py ARGS "$" - "\"${LIBCXX_LIBRARIES_PUBLIC_NAMES}\"" + ${LIBCXX_INTERFACE_LIBRARY_NAMES} WORKING_DIRECTORY ${LIBCXX_BUILD_DIR} ) endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d9be0df8d..edebaee55 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -11,6 +11,18 @@ endmacro() set(LIBCXX_LIT_VARIANT "libcxx" CACHE STRING "Configuration variant to use for LIT.") +# The tests shouldn't link to any ABI library when it has been linked into +# 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() + +# The tests shouldn't link to libunwind if we have a linker script which +# already does so. +if (LIBCXX_ENABLE_ABI_LINKER_SCRIPT) + set(LIBCXXABI_USE_LLVM_UNWINDER OFF) +endif() + pythonize_bool(LIBCXX_ENABLE_EXCEPTIONS) pythonize_bool(LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY) pythonize_bool(LIBCXX_ENABLE_FILESYSTEM) @@ -24,12 +36,6 @@ pythonize_bool(LIBCXX_HAS_ATOMIC_LIB) pythonize_bool(LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB) pythonize_bool(LIBCXX_HAS_EXTERNAL_THREAD_API) -# The tests shouldn't link to any ABI library when it has been linked into -# 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() - # By default, for non-standalone builds, libcxx and libcxxabi share a library # directory. if (NOT LIBCXX_CXX_ABI_LIBRARY_PATH) diff --git a/utils/gen_link_script/gen_link_script.py b/utils/gen_link_script/gen_link_script.py index cb42af9c4..cce8fb4b1 100755 --- a/utils/gen_link_script/gen_link_script.py +++ b/utils/gen_link_script/gen_link_script.py @@ -16,13 +16,13 @@ def print_and_exit(msg): sys.exit(1) def usage_and_exit(): - print_and_exit("Usage: ./gen_link_script.py [--help] [--dryrun] ") + print_and_exit("Usage: ./gen_link_script.py [--help] [--dryrun] ...") def help_and_exit(): help_msg = \ """Usage - gen_link_script.py [--help] [--dryrun] + gen_link_script.py [--help] [--dryrun] ... Generate a linker script that links libc++ to the proper ABI library. The script replaces the specified libc++ symlink. @@ -49,10 +49,12 @@ def parse_args(): dryrun = '--dryrun' == args[0] if dryrun: del args[0] - if len(args) != 2: + if len(args) < 2: usage_and_exit() symlink_file = args[0] - public_libs = args[1].split(';') + del args[0] + public_libs = list(args) + print('%r' % public_libs) return dryrun, symlink_file, public_libs def main():