forked from OSchip/llvm-project
[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
This commit is contained in:
parent
44b4f4df31
commit
b7fb856397
|
@ -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 <target> and gathers them into a linker script,
|
||||
# such that those libraries are linked against when the shared library for
|
||||
# <target> is linked against.
|
||||
#
|
||||
# Arguments:
|
||||
# <target>: 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 "$<TARGET_LINKER_FILE:${target}>")
|
||||
set(soname "$<TARGET_SONAME_FILE_NAME:${target}>")
|
||||
|
||||
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 "$<IF:$<TARGET_EXISTS:${lib}>,${lib},${target}>")
|
||||
set(libname "$<IF:$<TARGET_EXISTS:${lib}>,$<TARGET_PROPERTY:${output_name_tgt},OUTPUT_NAME>,${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()
|
|
@ -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 "$<TARGET_PROPERTY:libcxx-abi-shared,IMPORTED_LIBNAME>")
|
||||
set(output_name "$<TARGET_PROPERTY:libcxx-abi-shared,OUTPUT_NAME>")
|
||||
string(APPEND link_libraries "${CMAKE_LINK_LIBRARY_FLAG}$<IF:$<BOOL:${imported_libname}>,${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}$<TARGET_PROPERTY:unwind_shared,OUTPUT_NAME>")
|
||||
else()
|
||||
string(APPEND link_libraries " ${CMAKE_LINK_LIBRARY_FLAG}unwind")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(linker_script "INPUT($<TARGET_SONAME_FILE_NAME:cxx_shared> ${link_libraries})")
|
||||
add_custom_command(TARGET cxx_shared POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E remove "$<TARGET_LINKER_FILE:cxx_shared>"
|
||||
COMMAND "${CMAKE_COMMAND}" -E echo "${linker_script}" > "$<TARGET_LINKER_FILE:cxx_shared>"
|
||||
COMMENT "Generating linker script: '${linker_script}' as file $<TARGET_LINKER_FILE:cxx_shared>"
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND LIBCXX_BUILD_TARGETS "cxx_shared")
|
||||
|
|
Loading…
Reference in New Issue