Welcome to mirror list, hosted at ThFree Co, Russian Federation.

pkg-utils.cmake « cmake - github.com/mumble-voip/mumble.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: fabccdd266ec4a2398ceca37a4fac10ae8254529 (plain)
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
# Copyright 2020-2022 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()

		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()

	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()

	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()