[libcxx-commits] [libcxx] r374116 - [libc++] Move the linker script generation step to CMake

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Tue Oct 8 14:10:20 PDT 2019


Author: ldionne
Date: Tue Oct  8 14:10:20 2019
New Revision: 374116

URL: http://llvm.org/viewvc/llvm-project?rev=374116&view=rev
Log:
[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

Added:
    libcxx/trunk/cmake/Modules/DefineLinkerScript.cmake
Removed:
    libcxx/trunk/utils/gen_link_script.py
Modified:
    libcxx/trunk/CMakeLists.txt
    libcxx/trunk/src/CMakeLists.txt

Modified: libcxx/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/CMakeLists.txt?rev=374116&r1=374115&r2=374116&view=diff
==============================================================================
--- libcxx/trunk/CMakeLists.txt (original)
+++ libcxx/trunk/CMakeLists.txt Tue Oct  8 14:10:20 2019
@@ -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 ${LIB
 # 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)

Added: libcxx/trunk/cmake/Modules/DefineLinkerScript.cmake
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/cmake/Modules/DefineLinkerScript.cmake?rev=374116&view=auto
==============================================================================
--- libcxx/trunk/cmake/Modules/DefineLinkerScript.cmake (added)
+++ libcxx/trunk/cmake/Modules/DefineLinkerScript.cmake Tue Oct  8 14:10:20 2019
@@ -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()

Modified: libcxx/trunk/src/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/CMakeLists.txt?rev=374116&r1=374115&r2=374116&view=diff
==============================================================================
--- libcxx/trunk/src/CMakeLists.txt (original)
+++ libcxx/trunk/src/CMakeLists.txt Tue Oct  8 14:10:20 2019
@@ -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")

Removed: libcxx/trunk/utils/gen_link_script.py
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/gen_link_script.py?rev=374115&view=auto
==============================================================================
--- libcxx/trunk/utils/gen_link_script.py (original)
+++ libcxx/trunk/utils/gen_link_script.py (removed)
@@ -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())




More information about the libcxx-commits mailing list