mirror of
https://github.com/darlinghq/darling-libcxx.git
synced 2024-11-26 21:30:42 +00:00
[libc++] Move the linker script generation step to CMake
Summary: This allows the linker script generation to query CMake properties (specifically the dependencies of libc++.so) instead of having to carry these dependencies around manually in global variables. Notice the removal of the LIBCXX_INTERFACE_LIBRARIES global variable. Reviewers: phosek, EricWF Subscribers: mgorny, christof, jkorous, dexonsmith, libcxx-commits Tags: #libc Differential Revision: https://reviews.llvm.org/D68343 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@374116 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d265021834
commit
ef2d23967e
@ -380,9 +380,6 @@ 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()
|
||||
if (NOT LIBCXX_ENABLE_SHARED)
|
||||
message(FATAL_ERROR "LIBCXX_ENABLE_ABI_LINKER_SCRIPT is only available for shared library builds.")
|
||||
endif()
|
||||
@ -447,12 +444,9 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR})
|
||||
# LIBCXX_COMPILE_FLAGS: Compile only flags.
|
||||
# LIBCXX_LINK_FLAGS: Linker only flags.
|
||||
# LIBCXX_LIBRARIES: libraries libc++ is linked to.
|
||||
# LIBCXX_INTERFACE_LIBRARIES: Libraries that must be linked when using libc++
|
||||
# These libraries are exposed in the linker script.
|
||||
set(LIBCXX_COMPILE_FLAGS "")
|
||||
set(LIBCXX_LINK_FLAGS "")
|
||||
set(LIBCXX_LIBRARIES "")
|
||||
set(LIBCXX_INTERFACE_LIBRARIES "")
|
||||
|
||||
# Include macros for adding and removing libc++ flags.
|
||||
include(HandleLibcxxFlags)
|
||||
|
50
cmake/Modules/DefineLinkerScript.cmake
Normal file
50
cmake/Modules/DefineLinkerScript.cmake
Normal file
@ -0,0 +1,50 @@
|
||||
# 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 (TARGET "${lib}")
|
||||
list(APPEND link_libraries "${CMAKE_LINK_LIBRARY_FLAG}$<TARGET_PROPERTY:${lib},OUTPUT_NAME>")
|
||||
else()
|
||||
list(APPEND link_libraries "${CMAKE_LINK_LIBRARY_FLAG}${lib}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
list(JOIN 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()
|
@ -177,12 +177,10 @@ if (LIBCXX_ENABLE_SHARED)
|
||||
if (LIBCXXABI_USE_LLVM_UNWINDER)
|
||||
if (NOT LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY AND (TARGET unwind_shared OR HAVE_LIBUNWIND))
|
||||
target_link_libraries(cxx_shared PUBLIC unwind_shared)
|
||||
list(APPEND LIBCXX_INTERFACE_LIBRARIES unwind_shared) # For the linker script
|
||||
elseif (LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY AND (TARGET unwind_static OR HAVE_LIBUNWIND))
|
||||
# libunwind is already included in libc++abi
|
||||
else()
|
||||
target_link_libraries(cxx_shared PRIVATE unwind)
|
||||
list(APPEND LIBCXX_INTERFACE_LIBRARIES unwind) # For the linker script
|
||||
target_link_libraries(cxx_shared PUBLIC unwind)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -195,7 +193,6 @@ if (LIBCXX_ENABLE_SHARED)
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(cxx_shared PUBLIC "${LIBCXX_CXX_SHARED_ABI_LIBRARY}")
|
||||
list(APPEND LIBCXX_INTERFACE_LIBRARIES "${LIBCXX_CXX_SHARED_ABI_LIBRARY}") # For the linker script
|
||||
endif()
|
||||
|
||||
# Maybe re-export symbols from libc++abi
|
||||
@ -222,31 +219,10 @@ if (LIBCXX_ENABLE_SHARED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Generate a linker script in place of a libc++.so symlink. Rerun this command
|
||||
# after cxx builds.
|
||||
# Generate a linker script in place of a libc++.so symlink.
|
||||
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(LIBCXX_INTERFACE_LIBRARY_NAMES)
|
||||
foreach(lib ${LIBCXX_INTERFACE_LIBRARIES})
|
||||
# FIXME: Handle cxxabi_static and unwind_static.
|
||||
if (TARGET ${lib} OR
|
||||
(${lib} MATCHES "cxxabi(_static|_shared)?" AND HAVE_LIBCXXABI) OR
|
||||
(${lib} MATCHES "unwind(_static|_shared)?" AND HAVE_LIBUNWIND))
|
||||
list(APPEND LIBCXX_INTERFACE_LIBRARY_NAMES "$<TARGET_PROPERTY:${lib},OUTPUT_NAME>")
|
||||
else()
|
||||
list(APPEND LIBCXX_INTERFACE_LIBRARY_NAMES "${lib}")
|
||||
endif()
|
||||
endforeach()
|
||||
add_custom_command(TARGET cxx_shared POST_BUILD
|
||||
COMMAND
|
||||
${PYTHON_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/utils/gen_link_script.py
|
||||
ARGS
|
||||
--input "$<TARGET_SONAME_FILE:cxx_shared>"
|
||||
--output "$<TARGET_LINKER_FILE:cxx_shared>"
|
||||
${LIBCXX_INTERFACE_LIBRARY_NAMES}
|
||||
WORKING_DIRECTORY ${LIBCXX_BUILD_DIR}
|
||||
)
|
||||
include(DefineLinkerScript)
|
||||
define_linker_script(cxx_shared)
|
||||
endif()
|
||||
|
||||
list(APPEND LIBCXX_BUILD_TARGETS "cxx_shared")
|
||||
|
@ -1,58 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#===----------------------------------------------------------------------===##
|
||||
#
|
||||
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
# See https://llvm.org/LICENSE.txt for license information.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
#===----------------------------------------------------------------------===##
|
||||
|
||||
"""
|
||||
Generate a linker script that links libc++ to the proper ABI library.
|
||||
An example script for c++abi would look like "INPUT(libc++.so.1 -lc++abi)".
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--dryrun", help="Don't write any output",
|
||||
action="store_true", default=False)
|
||||
parser.add_argument("--rename", action="store_true", default=False,
|
||||
help="Rename the output as input so we can replace it")
|
||||
parser.add_argument("--input", help="Path to libc++ library", required=True)
|
||||
parser.add_argument("--output", help="Path to libc++ linker script",
|
||||
required=True)
|
||||
parser.add_argument("libraries", nargs="+",
|
||||
help="List of libraries libc++ depends on")
|
||||
args = parser.parse_args()
|
||||
|
||||
# Use the relative path for the libc++ library.
|
||||
libcxx = os.path.relpath(args.input, os.path.dirname(args.output))
|
||||
|
||||
# Prepare the list of public libraries to link.
|
||||
public_libs = ['-l%s' % l for l in args.libraries]
|
||||
|
||||
# Generate the linker script contents.
|
||||
contents = "INPUT(%s)" % ' '.join([libcxx] + public_libs)
|
||||
|
||||
if args.dryrun:
|
||||
print("GENERATING SCRIPT: '%s' as file %s" % (contents, args.output))
|
||||
return 0
|
||||
|
||||
# Remove the existing libc++ symlink if it exists.
|
||||
if os.path.islink(args.output):
|
||||
os.unlink(args.output)
|
||||
|
||||
# Replace it with the linker script.
|
||||
with open(args.output, 'w') as f:
|
||||
f.write(contents + "\n")
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
Loading…
Reference in New Issue
Block a user