Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame^] | 1 | # |
| 2 | # SPDX-License-Identifier: BSD-3-Clause |
| 3 | # SPDX-FileCopyrightText: Copyright TF-RMM Contributors. |
| 4 | # |
| 5 | |
| 6 | # |
| 7 | # Helper functions for collecting all the source files and include paths that |
| 8 | # are used in the RMM build |
| 9 | # |
| 10 | |
| 11 | function(is_valid_target_name target_name output_variable) |
| 12 | string(FIND ${target_name} "NOTFOUND" notfound_pos) |
| 13 | string(FIND ${target_name} "::@" link_addr_pos) |
| 14 | string(FIND ${target_name} "$<$<" gen_expr_pos) |
| 15 | if((NOT ${notfound_pos} EQUAL "-1") OR |
| 16 | (NOT ${link_addr_pos} EQUAL "-1") OR |
| 17 | (NOT ${gen_expr_pos} EQUAL "-1")) |
| 18 | set(${output_variable} FALSE PARENT_SCOPE) |
| 19 | else() |
| 20 | set(${output_variable} TRUE PARENT_SCOPE) |
| 21 | endif() |
| 22 | endfunction() |
| 23 | |
| 24 | function(normalise_property_value target_name output_variable) |
| 25 | foreach(value_prefix "INSTALL_INTERFACE" "BUILD_INTERFACE" "LINK_ONLY") |
| 26 | string(REGEX REPLACE "^.*${value_prefix}:([^>]+)>$" "\\1" target_name ${target_name}) |
| 27 | endforeach() |
| 28 | set(${output_variable} ${target_name} PARENT_SCOPE) |
| 29 | endfunction() |
| 30 | |
| 31 | function(collect_targets_recursively collected_targets new_target output_variable) |
| 32 | normalise_property_value("${new_target}" new_target) |
| 33 | |
| 34 | if ("${new_target}" IN_LIST collected_targets) |
| 35 | set("${output_variable}" "${collected_targets}" PARENT_SCOPE) |
| 36 | return() |
| 37 | endif() |
| 38 | |
| 39 | set(extended_target_list "${collected_targets}") |
| 40 | list(APPEND extended_target_list "${new_target}") |
| 41 | |
| 42 | foreach(link_property "INTERFACE_LINK_LIBRARIES" "LINK_LIBRARIES") |
| 43 | # workaround for cmake older than 3.19: |
| 44 | # INTERFACE_LIBRARY targets may only have whitelisted properties. This is typically |
| 45 | # property names starting with 'INTERFACE_' |
| 46 | get_target_property(target_type ${new_target} TYPE) |
| 47 | if(${target_type} STREQUAL "INTERFACE_LIBRARY") |
| 48 | string(FIND "${link_property}" "INTERFACE_" interface_pos) |
| 49 | if (NOT interface_pos EQUAL 0) |
| 50 | continue() |
| 51 | endif() |
| 52 | endif() |
| 53 | |
| 54 | get_target_property(target_interface "${new_target}" "${link_property}") |
| 55 | if(NOT "${target_interface}" STREQUAL "target_interface-NOTFOUND") |
| 56 | foreach(target_lib ${target_interface}) |
| 57 | is_valid_target_name(${target_lib} valid_target_name) |
| 58 | if (valid_target_name) |
| 59 | collect_targets_recursively("${extended_target_list}" "${target_lib}" extended_target_list) |
| 60 | endif() |
| 61 | endforeach() |
| 62 | endif() |
| 63 | endforeach() |
| 64 | |
| 65 | set("${output_variable}" "${extended_target_list}" PARENT_SCOPE) |
| 66 | endfunction() |
| 67 | |
| 68 | function(add_include_from_target target_name) |
| 69 | foreach(include_property "INTERFACE_INCLUDE_DIRECTORIES" "INCLUDE_DIRECTORIES") |
| 70 | # workaround for cmake older than 3.19: |
| 71 | # INTERFACE_LIBRARY targets may only have whitelisted properties. This is typically |
| 72 | # property names starting with 'INTERFACE_' |
| 73 | get_target_property(target_type ${target_name} TYPE) |
| 74 | if(${target_type} STREQUAL "INTERFACE_LIBRARY") |
| 75 | string(FIND "${include_property}" "INTERFACE_" interface_pos) |
| 76 | if (NOT interface_pos EQUAL 0) |
| 77 | continue() |
| 78 | endif() |
| 79 | endif() |
| 80 | |
| 81 | get_target_property(target_includes_dir ${target_name} ${include_property}) |
| 82 | if(NOT "${target_includes_dir}" STREQUAL "target_includes_dir-NOTFOUND") |
| 83 | foreach(target_includes_dir ${target_includes_dir}) |
| 84 | normalise_property_value(${target_includes_dir} target_includes_dir) |
| 85 | list(APPEND rmm_implementation_includes "-I${target_includes_dir}") |
| 86 | endforeach() |
| 87 | set (rmm_implementation_includes ${rmm_implementation_includes} PARENT_SCOPE) |
| 88 | endif() |
| 89 | endforeach() |
| 90 | endfunction() |
| 91 | |
| 92 | function(add_source_and_include_from_target target_name) |
| 93 | add_include_from_target(${target_name} ${level}) |
| 94 | set (rmm_implementation_includes ${rmm_implementation_includes} PARENT_SCOPE) |
| 95 | |
| 96 | # workaround for cmake older than 3.19: |
| 97 | # INTERFACE_LIBRARY targets may only have whitelisted properties. This is typically |
| 98 | # property names starting with 'INTERFACE_'. So SOURCES.* is not allowed. |
| 99 | get_target_property(target_type ${target_name} TYPE) |
| 100 | if(${target_type} STREQUAL "INTERFACE_LIBRARY") |
| 101 | return() |
| 102 | endif() |
| 103 | |
| 104 | get_target_property(target_srcs ${target_name} SOURCES) |
| 105 | get_target_property(target_srcs_dir ${target_name} SOURCE_DIR) |
| 106 | if((NOT "${target_srcs}" STREQUAL "target_srcs-NOTFOUND") AND |
| 107 | (NOT "${target_srcs_dir}" STREQUAL "target_srcs_dir-NOTFOUND")) |
| 108 | foreach(target_src ${target_srcs}) |
| 109 | list(APPEND rmm_implementation_srcs "${target_srcs_dir}/${target_src}") |
| 110 | endforeach() |
| 111 | set (rmm_implementation_srcs ${rmm_implementation_srcs} PARENT_SCOPE) |
| 112 | endif() |
| 113 | endfunction() |
| 114 | |
| 115 | function(add_source_and_include_recursively target_name) |
| 116 | collect_targets_recursively("" "${target_name}" rmm_target_list) |
| 117 | |
| 118 | foreach(target_lib ${rmm_target_list}) |
| 119 | add_source_and_include_from_target("${target_lib}") |
| 120 | endforeach() |
| 121 | |
| 122 | set (rmm_implementation_srcs ${rmm_implementation_srcs} PARENT_SCOPE) |
| 123 | set (rmm_implementation_includes ${rmm_implementation_includes} PARENT_SCOPE) |
| 124 | endfunction() |