From b8f8e4530c47754f0384c9a824ae9917a449436c Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 2 Aug 2022 20:30:28 -0400 Subject: [libc++] Simplify how we define the linker script for libc++ Trying to be generic didn't work properly because we had to special-case some interface libraries that we didn't want in the linker script. Instead, only look at the ABI and the unwinding libraries explicitly. This should solve the issue reported by @dim in [1]. [1]: https://discourse.llvm.org/t/15-0-0-rc1-has-been-tagged/64174/22 Differential Revision: https://reviews.llvm.org/D131037 (cherry picked from commit b7fb8563974d83f9eb8191fdfbebfd04147a2cbd) --- libcxx/cmake/Modules/DefineLinkerScript.cmake | 56 --------------------------- libcxx/src/CMakeLists.txt | 40 +++++++++++-------- 2 files changed, 24 insertions(+), 72 deletions(-) delete mode 100644 libcxx/cmake/Modules/DefineLinkerScript.cmake diff --git a/libcxx/cmake/Modules/DefineLinkerScript.cmake b/libcxx/cmake/Modules/DefineLinkerScript.cmake deleted file mode 100644 index 71a43086727c..000000000000 --- a/libcxx/cmake/Modules/DefineLinkerScript.cmake +++ /dev/null @@ -1,56 +0,0 @@ -# This function defines a linker script in place of the symlink traditionally -# created for shared libraries. -# -# More specifically, this function goes through the PUBLIC and INTERFACE -# library dependencies of and gathers them into a linker script, -# such that those libraries are linked against when the shared library for -# is linked against. -# -# Arguments: -# : A target representing a shared library. A linker script will be -# created in place of that target's TARGET_LINKER_FILE, which is -# the symlink pointing to the actual shared library (usually -# libFoo.so pointing to libFoo.so.1, which itself points to -# libFoo.so.1.0). - -function(define_linker_script target) - if (NOT TARGET "${target}") - message(FATAL_ERROR "The provided target '${target}' is not actually a target.") - endif() - - get_target_property(target_type "${target}" TYPE) - if (NOT "${target_type}" STREQUAL "SHARED_LIBRARY") - message(FATAL_ERROR "The provided target '${target}' is not a shared library (its type is '${target_type}').") - endif() - - set(symlink "$") - set(soname "$") - - get_target_property(interface_libs "${target}" INTERFACE_LINK_LIBRARIES) - - set(link_libraries) - if (interface_libs) - foreach(lib IN LISTS interface_libs) - if ("${lib}" MATCHES "cxx-headers|ParallelSTL") - continue() - endif() - # If ${lib} is not a target, we use a dummy target which we know will - # have an OUTPUT_NAME property so that CMake doesn't fail when evaluating - # the non-selected branch of the `IF`. It doesn't matter what it evaluates - # to because it's not selected, but it must not cause an error. - # See https://gitlab.kitware.com/cmake/cmake/-/issues/21045. - set(output_name_tgt "$,${lib},${target}>") - set(libname "$,$,${lib}>") - list(APPEND link_libraries "${CMAKE_LINK_LIBRARY_FLAG}${libname}") - endforeach() - endif() - string(REPLACE ";" " " link_libraries "${link_libraries}") - - set(linker_script "INPUT(${soname} ${link_libraries})") - add_custom_command(TARGET "${target}" POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E remove "${symlink}" - COMMAND "${CMAKE_COMMAND}" -E echo "${linker_script}" > "${symlink}" - COMMENT "Generating linker script: '${linker_script}' as file ${symlink}" - VERBATIM - ) -endfunction() diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index 61c60f934599..9abf548abbb9 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -212,20 +212,6 @@ if (LIBCXX_ENABLE_SHARED) cxx_add_common_build_flags(cxx_shared) cxx_set_common_defines(cxx_shared) - # Link against LLVM libunwind - # Note that we do need to link against libunwind directly to ensure that the correct - # dependencies are recorded when creating a linker script. - # TODO: Look into modifying the linker script creation to recursively consider interface libraries - if (LIBCXXABI_USE_LLVM_UNWINDER) - if (LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY) - # libunwind is already included in libc++abi - elseif (TARGET unwind_shared OR HAVE_LIBUNWIND) - target_link_libraries(cxx_shared PUBLIC unwind_shared) - else() - target_link_libraries(cxx_shared PUBLIC unwind) - endif() - endif() - # Link against libc++abi if (LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY) target_link_libraries(cxx_shared PRIVATE libcxx-abi-shared-objects) @@ -254,8 +240,30 @@ if (LIBCXX_ENABLE_SHARED) # Generate a linker script in place of a libc++.so symlink. if (LIBCXX_ENABLE_ABI_LINKER_SCRIPT) - include(DefineLinkerScript) - define_linker_script(cxx_shared) + set(link_libraries) + + set(imported_libname "$") + set(output_name "$") + string(APPEND link_libraries "${CMAKE_LINK_LIBRARY_FLAG}$,${imported_libname},${output_name}>") + + # TODO: Move to the same approach as above for the unwind library + if (LIBCXXABI_USE_LLVM_UNWINDER) + if (LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY) + # libunwind is already included in libc++abi + elseif (TARGET unwind_shared OR HAVE_LIBUNWIND) + string(APPEND link_libraries " ${CMAKE_LINK_LIBRARY_FLAG}$") + else() + string(APPEND link_libraries " ${CMAKE_LINK_LIBRARY_FLAG}unwind") + endif() + endif() + + set(linker_script "INPUT($ ${link_libraries})") + add_custom_command(TARGET cxx_shared POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E remove "$" + COMMAND "${CMAKE_COMMAND}" -E echo "${linker_script}" > "$" + COMMENT "Generating linker script: '${linker_script}' as file $" + VERBATIM + ) endif() list(APPEND LIBCXX_BUILD_TARGETS "cxx_shared") -- cgit v1.2.3