xref: /netbsd-src/external/apache2/llvm/dist/libcxx/cmake/Modules/DefineLinkerScript.cmake (revision 4d6fc14bc9b0c5bf3e30be318c143ee82cadd108)
1*4d6fc14bSjoerg# This function defines a linker script in place of the symlink traditionally
2*4d6fc14bSjoerg# created for shared libraries.
3*4d6fc14bSjoerg#
4*4d6fc14bSjoerg# More specifically, this function goes through the PUBLIC and INTERFACE
5*4d6fc14bSjoerg# library dependencies of <target> and gathers them into a linker script,
6*4d6fc14bSjoerg# such that those libraries are linked against when the shared library for
7*4d6fc14bSjoerg# <target> is linked against.
8*4d6fc14bSjoerg#
9*4d6fc14bSjoerg# Arguments:
10*4d6fc14bSjoerg#   <target>: A target representing a shared library. A linker script will be
11*4d6fc14bSjoerg#             created in place of that target's TARGET_LINKER_FILE, which is
12*4d6fc14bSjoerg#             the symlink pointing to the actual shared library (usually
13*4d6fc14bSjoerg#             libFoo.so pointing to libFoo.so.1, which itself points to
14*4d6fc14bSjoerg#             libFoo.so.1.0).
15*4d6fc14bSjoerg
16*4d6fc14bSjoergfunction(define_linker_script target)
17*4d6fc14bSjoerg  if (NOT TARGET "${target}")
18*4d6fc14bSjoerg    message(FATAL_ERROR "The provided target '${target}' is not actually a target.")
19*4d6fc14bSjoerg  endif()
20*4d6fc14bSjoerg
21*4d6fc14bSjoerg  get_target_property(target_type "${target}" TYPE)
22*4d6fc14bSjoerg  if (NOT "${target_type}" STREQUAL "SHARED_LIBRARY")
23*4d6fc14bSjoerg    message(FATAL_ERROR "The provided target '${target}' is not a shared library (its type is '${target_type}').")
24*4d6fc14bSjoerg  endif()
25*4d6fc14bSjoerg
26*4d6fc14bSjoerg  set(symlink "$<TARGET_LINKER_FILE:${target}>")
27*4d6fc14bSjoerg  set(soname "$<TARGET_SONAME_FILE_NAME:${target}>")
28*4d6fc14bSjoerg
29*4d6fc14bSjoerg  get_target_property(interface_libs "${target}" INTERFACE_LINK_LIBRARIES)
30*4d6fc14bSjoerg
31*4d6fc14bSjoerg  set(link_libraries)
32*4d6fc14bSjoerg  if (interface_libs)
33*4d6fc14bSjoerg    foreach(lib IN LISTS interface_libs)
34*4d6fc14bSjoerg      if ("${lib}" STREQUAL "cxx-headers")
35*4d6fc14bSjoerg        continue()
36*4d6fc14bSjoerg      endif()
37*4d6fc14bSjoerg      # If ${lib} is not a target, we use a dummy target which we know will
38*4d6fc14bSjoerg      # have an OUTPUT_NAME property so that CMake doesn't fail when evaluating
39*4d6fc14bSjoerg      # the non-selected branch of the `IF`. It doesn't matter what it evaluates
40*4d6fc14bSjoerg      # to because it's not selected, but it must not cause an error.
41*4d6fc14bSjoerg      # See https://gitlab.kitware.com/cmake/cmake/-/issues/21045.
42*4d6fc14bSjoerg      set(output_name_tgt "$<IF:$<TARGET_EXISTS:${lib}>,${lib},${target}>")
43*4d6fc14bSjoerg      set(libname "$<IF:$<TARGET_EXISTS:${lib}>,$<TARGET_PROPERTY:${output_name_tgt},OUTPUT_NAME>,${lib}>")
44*4d6fc14bSjoerg      list(APPEND link_libraries "${CMAKE_LINK_LIBRARY_FLAG}${libname}")
45*4d6fc14bSjoerg    endforeach()
46*4d6fc14bSjoerg  endif()
47*4d6fc14bSjoerg  string(REPLACE ";" " " link_libraries "${link_libraries}")
48*4d6fc14bSjoerg
49*4d6fc14bSjoerg  set(linker_script "INPUT(${soname} ${link_libraries})")
50*4d6fc14bSjoerg  add_custom_command(TARGET "${target}" POST_BUILD
51*4d6fc14bSjoerg    COMMAND "${CMAKE_COMMAND}" -E remove "${symlink}"
52*4d6fc14bSjoerg    COMMAND "${CMAKE_COMMAND}" -E echo "${linker_script}" > "${symlink}"
53*4d6fc14bSjoerg    COMMENT "Generating linker script: '${linker_script}' as file ${symlink}"
54*4d6fc14bSjoerg    VERBATIM
55*4d6fc14bSjoerg  )
56*4d6fc14bSjoergendfunction()
57