Louis Dionne | db7d4c5 | 2019-10-08 21:10:20 +0000 | [diff] [blame^] | 1 | # This function defines a linker script in place of the symlink traditionally |
| 2 | # created for shared libraries. |
| 3 | # |
| 4 | # More specifically, this function goes through the PUBLIC and INTERFACE |
| 5 | # library dependencies of <target> and gathers them into a linker script, |
| 6 | # such that those libraries are linked against when the shared library for |
| 7 | # <target> is linked against. |
| 8 | # |
| 9 | # Arguments: |
| 10 | # <target>: A target representing a shared library. A linker script will be |
| 11 | # created in place of that target's TARGET_LINKER_FILE, which is |
| 12 | # the symlink pointing to the actual shared library (usually |
| 13 | # libFoo.so pointing to libFoo.so.1, which itself points to |
| 14 | # libFoo.so.1.0). |
| 15 | |
| 16 | function(define_linker_script target) |
| 17 | if (NOT TARGET "${target}") |
| 18 | message(FATAL_ERROR "The provided target '${target}' is not actually a target.") |
| 19 | endif() |
| 20 | |
| 21 | get_target_property(target_type "${target}" TYPE) |
| 22 | if (NOT "${target_type}" STREQUAL "SHARED_LIBRARY") |
| 23 | message(FATAL_ERROR "The provided target '${target}' is not a shared library (its type is '${target_type}').") |
| 24 | endif() |
| 25 | |
| 26 | set(symlink "$<TARGET_LINKER_FILE:${target}>") |
| 27 | set(soname "$<TARGET_SONAME_FILE_NAME:${target}>") |
| 28 | |
| 29 | get_target_property(interface_libs "${target}" INTERFACE_LINK_LIBRARIES) |
| 30 | |
| 31 | set(link_libraries) |
| 32 | if (interface_libs) |
| 33 | foreach(lib IN LISTS interface_libs) |
| 34 | if (TARGET "${lib}") |
| 35 | list(APPEND link_libraries "${CMAKE_LINK_LIBRARY_FLAG}$<TARGET_PROPERTY:${lib},OUTPUT_NAME>") |
| 36 | else() |
| 37 | list(APPEND link_libraries "${CMAKE_LINK_LIBRARY_FLAG}${lib}") |
| 38 | endif() |
| 39 | endforeach() |
| 40 | endif() |
| 41 | list(JOIN link_libraries " " link_libraries) |
| 42 | |
| 43 | set(linker_script "INPUT(${soname} ${link_libraries})") |
| 44 | add_custom_command(TARGET "${target}" POST_BUILD |
| 45 | COMMAND "${CMAKE_COMMAND}" -E remove "${symlink}" |
| 46 | COMMAND "${CMAKE_COMMAND}" -E echo "${linker_script}" > "${symlink}" |
| 47 | COMMENT "Generating linker script: '${linker_script}' as file ${symlink}" |
| 48 | VERBATIM |
| 49 | ) |
| 50 | endfunction() |