1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
|
# Copyright 2020-2023 The Mumble Developers. All rights reserved.
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file at the root of the
# Mumble source tree or at <https://www.mumble.info/LICENSE>.
if(debug-dependency-search)
# Don't be quiet if the user wants to debug the dependency-search
set(QUIET_STR "")
else()
set(QUIET_STR "QUIET")
endif()
find_package(PkgConfig ${QUIET_STR})
include(FindPackageMessage)
function(pkgconfig_search MODULE)
if(NOT PkgConfig_FOUND)
return()
endif()
# We don't want pkg_search_module() to write into the variables that will be passed to the pkgconfig_search()'s caller.
set(PRIVATE "PRIVATE_${MODULE}")
pkg_search_module(${PRIVATE} ${MODULE} ${QUIET_STR})
if(NOT ${PRIVATE}_FOUND)
return()
endif()
if(NOT ${PRIVATE}_LINK_LIBRARIES)
foreach(LIBRARY ${${PRIVATE}_LIBRARIES})
# A cache entry named by <VAR> is created to store the result of find_library().
# If the library is found the result is stored in the variable and the search will not be repeated unless the variable is cleared.
# Using a name that depends on the loop-item is suggested in contrast to clearing the variable.
# @ref https://cmake.org/pipermail/cmake/2011-November/047171.html
find_library(${LIBRARY}_LINK ${PRIVATE_LIBRARY} PATHS ${${PRIVATE}_LIBRARY_DIRS})
list(APPEND ${PRIVATE}_LINK_LIBRARIES ${${LIBRARY}_LINK})
endforeach()
endif()
set(${MODULE}_INCLUDE_DIRS ${${PRIVATE}_INCLUDE_DIRS} PARENT_SCOPE)
set(${MODULE}_LIBRARIES ${${PRIVATE}_LINK_LIBRARIES} PARENT_SCOPE)
set(${MODULE}_VERSION ${${PRIVATE}_VERSION} PARENT_SCOPE)
set(${MODULE}_FOUND ${${PRIVATE}_FOUND} PARENT_SCOPE)
endfunction()
# This macro's main purpose is to call find_package() with CONFIG and then with MODULE if it fails.
# It also handles multiple package names and searches them with pkg-config if they are not found.
macro(find_pkg ARG_ALIASES)
# We specify "CONFIG", "MODULE" and "NO_MODULE" so that they are not considered unparsed arguments (passed to find_package()).
cmake_parse_arguments(FIND_PACKAGE "ARG_ALIASES;CONFIG;MODULE;NO_DEFAULT_PATH;NO_MODULE;REQUIRED;QUIET" "" "COMPONENTS;OPTIONAL_COMPONENTS;PATHS" ${ARGN})
if(FIND_PACKAGE_PATHS)
list(APPEND FIND_PACKAGE_ARGUMENTS "PATHS" ${FIND_PACKAGE_PATHS})
endif()
if(FIND_PACKAGE_NO_DEFAULT_PATH)
list(APPEND FIND_PACKAGE_ARGUMENTS "NO_DEFAULT_PATH")
endif()
# We add the aliases to a clean list because of an issue with list(GET).
# If we pass the argument list directly to it, LAST_ALIAS is always set to "NOTFOUND".
foreach(ALIAS ${ARG_ALIASES})
list(APPEND ALIASES ${ALIAS})
endforeach()
list(REMOVE_DUPLICATES ALIASES)
list(GET ALIASES -1 LAST_ALIAS)
foreach(ALIAS ${ALIASES})
set(NAME ${ALIAS})
if(FIND_PACKAGE_COMPONENTS)
foreach(COMPONENT ${FIND_PACKAGE_COMPONENTS})
find_package(${NAME} COMPONENTS ${COMPONENT} ${FIND_PACKAGE_ARGUMENTS} ${QUIET_STR} CONFIG ${FIND_PACKAGE_UNPARSED_ARGUMENTS})
if(NOT ${NAME}_FOUND)
find_package(${NAME} COMPONENTS ${COMPONENT} ${FIND_PACKAGE_ARGUMENTS} ${QUIET_STR} MODULE ${FIND_PACKAGE_UNPARSED_ARGUMENTS})
endif()
if(NOT ${NAME}_FOUND)
if(NOT ${NAME} STREQUAL ${LAST_ALIAS})
break()
else()
if(FIND_PACKAGE_REQUIRED)
message(FATAL_ERROR "${NAME} component not found: ${COMPONENT}")
endif()
if(NOT FIND_PACKAGE_QUIET)
message(STATUS "${NAME} component not found: ${COMPONENT}")
endif()
break()
endif()
endif()
if(NOT FIND_PACKAGE_QUIET)
if(${NAME}_VERSION)
find_package_message(${NAME} "${NAME} component found: ${COMPONENT} | Version: ${${NAME}_VERSION}" "[${NAME}][${COMPONENT}][${${NAME}_VERSION}]")
else()
find_package_message(${NAME} "${NAME} component found: ${COMPONENT}" "[${NAME}][${COMPONENT}]")
endif()
endif()
endforeach()
if(NOT ${NAME}_FOUND)
continue()
endif()
else()
find_package(${NAME} ${FIND_PACKAGE_ARGUMENTS} ${QUIET_STR} CONFIG ${FIND_PACKAGE_UNPARSED_ARGUMENTS})
if(NOT ${NAME}_FOUND)
find_package(${NAME} ${FIND_PACKAGE_ARGUMENTS} ${QUIET_STR} MODULE ${FIND_PACKAGE_UNPARSED_ARGUMENTS})
if(NOT ${NAME}_FOUND)
pkgconfig_search(${NAME})
endif()
endif()
if(NOT ${NAME}_FOUND)
if(NOT ${NAME} STREQUAL ${LAST_ALIAS})
continue()
else()
if(FIND_PACKAGE_REQUIRED)
message(FATAL_ERROR "${NAME} not found")
endif()
if(NOT FIND_PACKAGE_QUIET)
message(STATUS "${NAME} not found")
endif()
break()
endif()
endif()
if(NOT FIND_PACKAGE_QUIET)
if(${NAME}_VERSION)
find_package_message(${NAME} "${NAME} found | Version: ${${NAME}_VERSION}" "[${NAME}][${${NAME}_VERSION}]")
else()
find_package_message(${NAME} "${NAME} found" "[${NAME}]")
endif()
endif()
endif()
if(FIND_PACKAGE_OPTIONAL_COMPONENTS)
foreach(COMPONENT ${FIND_PACKAGE_OPTIONAL_COMPONENTS})
find_package(${NAME} COMPONENTS ${COMPONENT} ${FIND_PACKAGE_ARGUMENTS} ${QUIET_STR} CONFIG ${FIND_PACKAGE_UNPARSED_ARGUMENTS})
if(NOT ${NAME}_FOUND)
find_package(${NAME} COMPONENTS ${COMPONENT} ${FIND_PACKAGE_ARGUMENTS} ${QUIET_STR} MODULE ${FIND_PACKAGE_UNPARSED_ARGUMENTS})
endif()
if(${NAME}_FOUND AND NOT FIND_PACKAGE_QUIET)
if(${NAME}_VERSION)
find_package_message(${NAME} "${NAME} optional component found: ${COMPONENT} | Version: ${${NAME}_VERSION}" "[${NAME}][${COMPONENT}][${${NAME}_VERSION}]")
else()
find_package_message(${NAME} "${NAME} optional component found: ${COMPONENT}" "[${NAME}][${COMPONENT}]")
endif()
endif()
endforeach()
endif()
if(${NAME}_FOUND)
break()
endif()
endforeach()
unset(LAST_ALIAS)
unset(FIND_PACKAGE_ARGUMENTS)
if(${NAME}_FOUND)
if(NOT ${NAME}_VERSION OR NOT ${NAME}_LIBRARIES)
# The FindOpenSSL module defines the variables with an uppercase prefix.
string(TOUPPER ${NAME} NAME_UPPER)
if(NOT ${NAME}_VERSION)
set(${NAME}_VERSION ${${NAME_UPPER}_VERSION})
endif()
if(NOT ${NAME}_LIBRARIES)
set(${NAME}_LIBRARIES ${${NAME_UPPER}_LIBRARIES})
endif()
unset(NAME_UPPER)
endif()
# If multiple capitalizations are searched for this will ensure that the
# lowercase name of the library's variables are set as well.
# Simplifying usage of find_pkg on case-insensitive file systems.
string(TOLOWER ${NAME} NAME_LOWER)
if(NOT ${NAME} STREQUAL NAME_LOWER AND ${NAME_LOWER} IN_LIST ALIASES)
if(NOT ${NAME_LOWER}_VERSION)
set(${NAME_LOWER}_VERSION ${${NAME}_VERSION})
endif()
if(NOT ${NAME_LOWER}_LIBRARIES)
set(${NAME_LOWER}_LIBRARIES ${${NAME}_LIBRARIES})
endif()
if(NOT ${NAME_LOWER}_FOUND)
set(${NAME_LOWER}_FOUND ${${NAME}_FOUND})
endif()
if(NOT ${NAME_LOWER}_INCLUDE_DIRS)
set(${NAME_LOWER}_INCLUDE_DIRS ${${NAME}_INCLUDE_DIRS})
endif()
endif()
unset(NAME_LOWER)
elseif(NOT FIND_PACKAGE_QUIET)
if(NOT PkgConfig_FOUND)
message(WARNING "pkg-config was not found, consider installing it for better chances of finding a package")
endif()
endif()
unset(ALIASES)
unset(NAME)
endmacro()
# Uses pkg-config to obtain the value of a module variable
# In contrast to standard cmake's pkg_get_variable, this function abstracts the
# difference between pkg-config and pkgconf where one of them uses underscores in
# the variable names, whereas the other does not. Thus, when provided with a
# variable name that contains underscores and for which no value could be fetched,
# the function will automatically check whether removing the underscores from the
# variable name will yield a non-empty value and if this is the case, this value
# will be returned.
#
# OUTPUT_VARIABLE <varName> Name of the output variable (Required)
# MODULE <module> Name of the module to search for (Required)
# VARIABLE_NAME <varName> Name of the variable to search for within the module (Required)
# Note: This name should be the one containing underscores.
# QUIET Don't print any status messages
# REQUIRED Error, if no non-empty value could be retrieved
# DEBUG Print status messages intended to debug this function
function(get_pkgconf_variable)
set(options QUIET REQUIRED DEBUG)
set(oneValueArgs OUTPUT_VARIABLE MODULE VARIABLE_NAME)
set(multiValueArgs)
cmake_parse_arguments(GET_PKGCONF_VAR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
# Handle required args
set(REQUIRED_ARGS ${oneValueArgs})
foreach(CURRENT IN LISTS REQUIRED_ARGS)
if (NOT GET_PKGCONF_VAR_${CURRENT})
message(FATAL_ERROR "get_pkgconf_variable: Missing mandatory parameter \"${CURRENT}\"")
endif()
endforeach()
# Check that we have found pkg-config to begin with
if(NOT PkgConfig_FOUND)
message(FATAL_ERROR "get_pkgconf_variable: pkg-config was not found - can't use it to fetch variables")
endif()
pkg_search_module("PKGCONF_MODULE" "${GET_PKGCONF_VAR_MODULE}" QUIET)
if(NOT PKGCONF_MODULE_FOUND)
if(GET_PKGCONF_VAR_DEBUG)
message(STATUS "Unable to find module \"${GET_PKGCONF_VAR_MODULE}\" via pkg-conf")
set(VAR_VALUE "NOTFOUND")
endif()
else()
if(GET_PKGCONF_VAR_DEBUG)
message(STATUS "get_pkgconf_variable: Searching for \"${GET_PKGCONF_VAR_VARIABLE_NAME}\" in module \"${GET_PKGCONF_VAR_MODULE}\"")
endif()
pkg_get_variable(VAR_VALUE "${GET_PKGCONF_VAR_MODULE}" "${GET_PKGCONF_VAR_VARIABLE_NAME}")
if(NOT VAR_VALUE AND GET_PKGCONF_VAR_VARIABLE_NAME MATCHES ".*_.*")
# There seems to be a difference between pkgconf and pkg-config where one uses underscores
# in variable names, whereas the other does not. We assume that VAR_NAME is the version with
# the underscores, so if that failed to fetch a value, we try again without the underscores.
string(REPLACE "_" "" VAR_NAME_WITHOUT_UNDERSCORES "${GET_PKGCONF_VAR_VARIABLE_NAME}")
if(GET_PKGCONF_VAR_DEBUG)
message(STATUS "get_pkgconf_variable: Removed underscores from variable name")
message(STATUS "get_pkgconf_variable: Now searching for variable \"${VAR_NAME_WITHOUT_UNDERSCORES}\"")
endif()
pkg_get_variable(VAR_VALUE "${GET_PKGCONF_VAR_MODULE}" "${VAR_NAME_WITHOUT_UNDERSCORES}")
endif()
endif()
if(NOT VAR_VALUE)
if(GET_PKGCONF_VAR_REQUIRED)
message(FATAL_ERROR "get_pkgconf_variable: Failed to fetch \"${GET_PKGCONF_VAR_VARIABLE_NAME}\" of module \"${GET_PKGCONF_VAR_MODULE}\"")
endif()
if(NOT GET_PKGCONF_VAR_QUIET)
message(WARNING "get_pkgconf_variable: Failed to fetch \"${GET_PKGCONF_VAR_VARIABLE_NAME}\" of module \"${GET_PKGCONF_VAR_MODULE}\"")
endif()
endif()
if(GET_PKGCONF_VAR_DEBUG)
message(STATUS "get_pkgconf_variable: Determined ${GET_PKGCONF_VAR_VARIABLE_NAME}=\"${VAR_VALUE}\"")
endif()
set(${GET_PKGCONF_VAR_OUTPUT_VARIABLE} "${VAR_VALUE}" PARENT_SCOPE)
endfunction()
|