File: IncludeFindCurl.cmake

package info (click to toggle)
warzone2100 4.6.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 660,320 kB
  • sloc: cpp: 676,209; ansic: 391,201; javascript: 78,238; python: 16,632; php: 4,294; sh: 4,094; makefile: 2,629; lisp: 1,492; cs: 489; xml: 404; perl: 224; ruby: 156; java: 89
file content (186 lines) | stat: -rw-r--r-- 8,428 bytes parent folder | download | duplicates (2)
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
# This file finds CURL
#
# Attempts to determine its linked / available SSL backend(s):
# - CURL_SUPPORTED_SSL_BACKENDS
#
# And then attempts to determine if its linked SSL backend(s)
# require specific thread-safety / lock callback initialization
# (see: https://curl.haxx.se/libcurl/c/threaded-ssl.html)
#
# - CURL_GNUTLS_REQUIRES_CALLBACKS
# - CURL_OPENSSL_REQUIRES_CALLBACKS
#
# The above two variables are:
# - defined to `YES` if CURL has the backend, and the backend's
#   version is old enough to require callback initialization
# - defined to `NO` if CURL has the backend, and it can be
#   determined that the backend's version is new enough to *NOT*
#   require callback initialization
# - defined to `UNKNOWN` if CURL has the backend, but the backend's
#   version cannot be determined
#

find_package(CURL CONFIG QUIET) # Deliberately quiet, so we can handle the result
if(NOT CURL_FOUND)
	# CONFIG mode failed - fallback to MODULE mode
	# In CMake 3.5 this does not define a target, but it will in 3.12
	# (see https://cmake.org/cmake/help/git-stage/module/FindCURL.html for details).
	# Until then, define the target ourselves if it is missing.
	find_package(CURL MODULE REQUIRED) # Use REQUIRED the second time to fail out
	if (NOT TARGET CURL::libcurl)
		add_library(CURL::libcurl UNKNOWN IMPORTED)
		set_property(TARGET CURL::libcurl
			APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CURL_INCLUDE_DIR}"
		)
		set_property(TARGET CURL::libcurl
			APPEND PROPERTY IMPORTED_LOCATION "${CURL_LIBRARY}"
		)
	endif()
else()
	# Determine cURL version found
	set(CURL_VERSION_STRING "${CURL_VERSION}")
endif()

##############################################################
# Attempt to determine which SSL backend(s) cURL is linked to

STRING(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" CURL_VERSION_STRING "${CURL_VERSION_STRING}")
message(STATUS "CURL_VERSION_STRING=\"${CURL_VERSION_STRING}\"")

unset(CURL_SUPPORTED_SSL_BACKENDS)
unset(CURL_GNUTLS_REQUIRES_CALLBACKS)
unset(CURL_OPENSSL_REQUIRES_CALLBACKS)

find_program(CURL_CONFIG_EXECUTABLE NAMES curl-config)
if(CURL_CONFIG_EXECUTABLE)
	set(_min_curl_version_for_ssl_backends "7.58.0")
	if ((CURL_VERSION_STRING VERSION_EQUAL "${_min_curl_version_for_ssl_backends}") OR (CURL_VERSION_STRING VERSION_GREATER "${_min_curl_version_for_ssl_backends}"))

		execute_process(COMMAND ${CURL_CONFIG_EXECUTABLE} --ssl-backends
						RESULT_VARIABLE _result_ssl_backends
						OUTPUT_VARIABLE CURL_CONFIG_SSL_BACKENDS_STRING
						ERROR_QUIET
						OUTPUT_STRIP_TRAILING_WHITESPACE)
		if (_result_ssl_backends EQUAL 0)
			string(REPLACE "," ";" CURL_SUPPORTED_SSL_BACKENDS "${CURL_CONFIG_SSL_BACKENDS_STRING}")
		else()
			message(STATUS "curl-config (\"${CURL_CONFIG_EXECUTABLE}\") doesn't seem to support --ssl-backends - it may be a different version than the detected libcurl")
		endif()

	else()

		# cURL < 7.58.0 does not support curl-config --ssl-backends
		# Try to parse ssl backend (options) from curl-config --configure
		execute_process(COMMAND ${CURL_CONFIG_EXECUTABLE} --configure
						OUTPUT_VARIABLE CURL_CONFIG_CONFIGURE_STRING
						ERROR_QUIET
						OUTPUT_STRIP_TRAILING_WHITESPACE)
		message(STATUS "CURL_CONFIG_CONFIGURE_STRING=\"${CURL_CONFIG_CONFIGURE_STRING}\"")
		set(CURL_SUPPORTED_SSL_BACKENDS)
		if ((CURL_CONFIG_CONFIGURE_STRING MATCHES "--with-ssl") OR (NOT CURL_CONFIG_CONFIGURE_STRING MATCHES "--without-ssl"))
			# Linked to OpenSSL (or similar)
			list(APPEND CURL_SUPPORTED_SSL_BACKENDS "OpenSSL")
		endif()
		if (CURL_CONFIG_CONFIGURE_STRING MATCHES "--with-gnutls")
			# Linked to GnuTLS
			list(APPEND CURL_SUPPORTED_SSL_BACKENDS "GnuTLS")
		endif()
		if (CURL_CONFIG_CONFIGURE_STRING MATCHES "--with-default-ssl-backend=([^'\" \t\n\r]+)")
			set(_default_ssl_backend "${CMAKE_MATCH_1}")
			message(STATUS "default-ssl-backend=\"${_default_ssl_backend}\"")
			# A default ssl backend was specified - need to parse and check if it's OpenSSL or GnuTLS
			# Filter the CURL_SUPPORTED_SSL_BACKENDS list
			if (_default_ssl_backend MATCHES "gnutls")
				# If GnuTLS is the default, remove OpenSSL from the list of backends processed
				list(REMOVE_ITEM CURL_SUPPORTED_SSL_BACKENDS "OpenSSL")
			elseif (_default_ssl_backend MATCHES "openssl")
				# If OpenSSL is the default, remove GnuTLS from the list of backends processed
				list(REMOVE_ITEM CURL_SUPPORTED_SSL_BACKENDS "GnuTLS")
			else()
				# Anything else the default? Remove both, and ensure the default backend is in the list
				list(REMOVE_ITEM CURL_SUPPORTED_SSL_BACKENDS "GnuTLS")
				list(REMOVE_ITEM CURL_SUPPORTED_SSL_BACKENDS "OpenSSL")
				list(APPEND CURL_SUPPORTED_SSL_BACKENDS "${_default_ssl_backend}")
			endif()
		else()
			# TODO: Handle "implicit default" case?
		endif()
	endif()

	message(STATUS "CURL_SUPPORTED_SSL_BACKENDS=\"${CURL_SUPPORTED_SSL_BACKENDS}\"")

	if ("GnuTLS" IN_LIST CURL_SUPPORTED_SSL_BACKENDS)
		# GnuTLS found
		find_package(GnuTLS QUIET)
		if(GNUTLS_FOUND)
			# Detect GnuTLS version #
			if(NOT DEFINED GNUTLS_VERSION_STRING OR GNUTLS_VERSION_STRING STREQUAL "")
				foreach(_gnutls_include_dir ${GNUTLS_INCLUDE_DIRS})
					# message(STATUS "_gnutls_include_dir: \"${_gnutls_include_dir}\"")
					set(_expected_gnutls_include_file "${_gnutls_include_dir}/gnutls/gnutls.h")
					if(EXISTS "${_expected_gnutls_include_file}")
						# message(STATUS "Searching in file: ${_expected_gnutls_include_file}")
						file(STRINGS "${_expected_gnutls_include_file}" GNUTLS_VERSION_STRING_LINE REGEX "^#define[ \t]+GNUTLS_VERSION[ \t]+\"[.0-9]+\"$")
						if(NOT DEFINED GNUTLS_VERSION_STRING_LINE OR GNUTLS_VERSION_STRING_LINE STREQUAL "")
							# Fall-back to LIBGNUTLS_VERSION, for earlier versions
							file(STRINGS "${_expected_gnutls_include_file}" GNUTLS_VERSION_STRING_LINE REGEX "^#define[ \t]+LIBGNUTLS_VERSION[ \t]+\"[.0-9]+\"$")
						endif()
						string(REGEX REPLACE "^#define[ \t]+[^ \t]*GNUTLS_VERSION[ \t]+\"([.0-9]+)\"$" "\\1" GNUTLS_VERSION_STRING "${GNUTLS_VERSION_STRING_LINE}")
						unset(GNUTLS_VERSION_STRING_LINE)
						break()
					endif()
				endforeach()
			endif()
			message(STATUS "GNUTLS_VERSION_STRING=\"${GNUTLS_VERSION_STRING}\"")
			if (GNUTLS_VERSION_STRING VERSION_LESS "2.11.0")
				# Explicit gcry_control() is required when GnuTLS < 2.11.0
				set(CURL_GNUTLS_REQUIRES_CALLBACKS "YES")
			else()
				# No explicit callback setup is required
				set(CURL_GNUTLS_REQUIRES_CALLBACKS "NO")
			endif()
		else()
			# cURL is linked to GnuTLS, but GnuTLS was not found
			set(CURL_GNUTLS_REQUIRES_CALLBACKS "UNKNOWN")
		endif()
		message(STATUS "GnuTLS requires explicit thread-safety callback init: ${CURL_GNUTLS_REQUIRES_CALLBACKS}")
	endif()
	# NOTE: cURL may list OpenSSL as "OpenSSL", "OpenSSL v3+" (but this is not guaranteed for all build configurations, even *if* OpenSSL is >= 3), etc
	# So instead of exact matches, look for any list entry that begins with OpenSSL
	set(_curl_hasOpenSSLBackend FALSE)
	set(_curl_openSSLBackendName "")
	foreach (backend IN LISTS CURL_SUPPORTED_SSL_BACKENDS)
		if (backend MATCHES "^OpenSSL.*")
			set(_curl_hasOpenSSLBackend TRUE)
			set(_curl_openSSLBackendName "${backend}")
		endif()
	endforeach()
	if (_curl_hasOpenSSLBackend)
		# OpenSSL found
		find_package(OpenSSL QUIET)
		if(OPENSSL_FOUND)
			string(REGEX REPLACE "^([0-9]+[.][0-9]+[.][0-9]+).*$" "\\1" OPENSSL_VERSION_NUMBERS "${OPENSSL_VERSION}")
			message(STATUS "OPENSSL_VERSION_NUMBERS=${OPENSSL_VERSION_NUMBERS}")
			if (OPENSSL_VERSION_NUMBERS VERSION_LESS "1.1.0")
				# OpenSSL < 1.1.0 requires thread id and locking callbacks to be initialized
				set(CURL_OPENSSL_REQUIRES_CALLBACKS "YES")
			else()
				# No callbacks are required for OpenSSL >= 1.1.0
				set(CURL_OPENSSL_REQUIRES_CALLBACKS "NO")
			endif()
		else()
			# cURL is linked to OpenSSL, but OpenSSL was not found
			if (_curl_openSSLBackendName MATCHES "^OpenSSL v3")
				# if cURL OpenSSL backend is "OpenSSL v3+", then we can assume it's >= 3.0, and no callbacks are required
				set(CURL_OPENSSL_REQUIRES_CALLBACKS "NO")
			else()
				# otherwise, unknown
				set(CURL_OPENSSL_REQUIRES_CALLBACKS "UNKNOWN")
			endif()
		endif()
		message(STATUS "OpenSSL requires explicit thread-safety callback init: ${CURL_OPENSSL_REQUIRES_CALLBACKS}")
	endif()
else()
	# curl-config was not found; if curl is built with ssl backend(s) OpenSSL or GnuTLS, this may result in thread-safety issues
	unset(CURL_SUPPORTED_SSL_BACKENDS)
endif()