1# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2# file Copyright.txt or https://cmake.org/licensing for details.
3
4#[=======================================================================[.rst:
5FindCURL
6--------
7
8Find the native CURL headers and libraries.
9
10.. versionadded:: 3.14
11  This module accept optional COMPONENTS to check supported features and
12  protocols:
13
14::
15
16  PROTOCOLS: ICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS LDAP LDAPS POP3
17             POP3S RTMP RTSP SCP SFTP SMB SMBS SMTP SMTPS TELNET TFTP
18  FEATURES:  SSL IPv6 UnixSockets libz AsynchDNS IDN GSS-API PSL SPNEGO
19             Kerberos NTLM NTLM_WB TLS-SRP HTTP2 HTTPS-proxy
20
21IMPORTED Targets
22^^^^^^^^^^^^^^^^
23
24.. versionadded:: 3.12
25
26This module defines :prop_tgt:`IMPORTED` target ``CURL::libcurl``, if
27curl has been found.
28
29Result Variables
30^^^^^^^^^^^^^^^^
31
32This module defines the following variables:
33
34``CURL_FOUND``
35  "True" if ``curl`` found.
36
37``CURL_INCLUDE_DIRS``
38  where to find ``curl``/``curl.h``, etc.
39
40``CURL_LIBRARIES``
41  List of libraries when using ``curl``.
42
43``CURL_VERSION_STRING``
44  The version of ``curl`` found.
45
46.. versionadded:: 3.13
47  Debug and Release variants are found separately.
48
49CURL CMake
50^^^^^^^^^^
51
52.. versionadded:: 3.17
53
54If CURL was built using the CMake buildsystem then it provides its own
55``CURLConfig.cmake`` file for use with the :command:`find_package` command's
56config mode. This module looks for this file and, if found,
57returns its results with no further action.
58
59Set ``CURL_NO_CURL_CMAKE`` to ``ON`` to disable this search.
60
61#]=======================================================================]
62
63include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
64
65if(NOT CURL_NO_CURL_CMAKE)
66  # do a find package call to specifically look for the CMake version
67  # of curl
68  find_package(CURL QUIET NO_MODULE)
69  mark_as_advanced(CURL_DIR)
70
71  # if we found the CURL cmake package then we are done, and
72  # can print what we found and return.
73  if(CURL_FOUND)
74    find_package_handle_standard_args(CURL HANDLE_COMPONENTS CONFIG_MODE)
75    return()
76  endif()
77endif()
78
79find_package(PkgConfig QUIET)
80if(PKG_CONFIG_FOUND)
81  pkg_check_modules(PC_CURL QUIET libcurl)
82  if(PC_CURL_FOUND)
83    set(CURL_VERSION_STRING ${PC_CURL_VERSION})
84    pkg_get_variable(CURL_SUPPORTED_PROTOCOLS libcurl supported_protocols)
85    pkg_get_variable(CURL_SUPPORTED_FEATURES libcurl supported_features)
86  endif()
87endif()
88
89# Look for the header file.
90find_path(CURL_INCLUDE_DIR
91          NAMES curl/curl.h
92          HINTS ${PC_CURL_INCLUDE_DIRS})
93mark_as_advanced(CURL_INCLUDE_DIR)
94
95if(NOT CURL_LIBRARY)
96  # Look for the library (sorted from most current/relevant entry to least).
97  find_library(CURL_LIBRARY_RELEASE NAMES
98      curl
99    # Windows MSVC prebuilts:
100      curllib
101      libcurl_imp
102      curllib_static
103    # Windows older "Win32 - MSVC" prebuilts (libcurl.lib, e.g. libcurl-7.15.5-win32-msvc.zip):
104      libcurl
105      NAMES_PER_DIR
106      HINTS ${PC_CURL_LIBRARY_DIRS}
107  )
108  mark_as_advanced(CURL_LIBRARY_RELEASE)
109
110  find_library(CURL_LIBRARY_DEBUG NAMES
111    # Windows MSVC CMake builds in debug configuration on vcpkg:
112      libcurl-d_imp
113      libcurl-d
114      NAMES_PER_DIR
115      HINTS ${PC_CURL_LIBRARY_DIRS}
116  )
117  mark_as_advanced(CURL_LIBRARY_DEBUG)
118
119  include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
120  select_library_configurations(CURL)
121endif()
122
123if(CURL_INCLUDE_DIR AND NOT CURL_VERSION_STRING)
124  foreach(_curl_version_header curlver.h curl.h)
125    if(EXISTS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}")
126      file(STRINGS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}" curl_version_str REGEX "^#define[\t ]+LIBCURL_VERSION[\t ]+\".*\"")
127
128      string(REGEX REPLACE "^#define[\t ]+LIBCURL_VERSION[\t ]+\"([^\"]*)\".*" "\\1" CURL_VERSION_STRING "${curl_version_str}")
129      unset(curl_version_str)
130      break()
131    endif()
132  endforeach()
133endif()
134
135if(CURL_FIND_COMPONENTS)
136  set(CURL_KNOWN_PROTOCOLS ICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS LDAP LDAPS POP3 POP3S RTMP RTSP SCP SFTP SMB SMBS SMTP SMTPS TELNET TFTP)
137  set(CURL_KNOWN_FEATURES  SSL IPv6 UnixSockets libz AsynchDNS IDN GSS-API PSL SPNEGO Kerberos NTLM NTLM_WB TLS-SRP HTTP2 HTTPS-proxy)
138  foreach(component IN LISTS CURL_KNOWN_PROTOCOLS CURL_KNOWN_FEATURES)
139    set(CURL_${component}_FOUND FALSE)
140  endforeach()
141  if(NOT PC_CURL_FOUND)
142    find_program(CURL_CONFIG_EXECUTABLE NAMES curl-config)
143    if(CURL_CONFIG_EXECUTABLE)
144      execute_process(COMMAND ${CURL_CONFIG_EXECUTABLE} --version
145                      OUTPUT_VARIABLE CURL_CONFIG_VERSION_STRING
146                      ERROR_QUIET
147                      OUTPUT_STRIP_TRAILING_WHITESPACE)
148      execute_process(COMMAND ${CURL_CONFIG_EXECUTABLE} --feature
149                      OUTPUT_VARIABLE CURL_CONFIG_FEATURES_STRING
150                      ERROR_QUIET
151                      OUTPUT_STRIP_TRAILING_WHITESPACE)
152      string(REPLACE "\n" ";" CURL_SUPPORTED_FEATURES "${CURL_CONFIG_FEATURES_STRING}")
153      execute_process(COMMAND ${CURL_CONFIG_EXECUTABLE} --protocols
154                      OUTPUT_VARIABLE CURL_CONFIG_PROTOCOLS_STRING
155                      ERROR_QUIET
156                      OUTPUT_STRIP_TRAILING_WHITESPACE)
157      string(REPLACE "\n" ";" CURL_SUPPORTED_PROTOCOLS "${CURL_CONFIG_PROTOCOLS_STRING}")
158    endif()
159
160  endif()
161  foreach(component IN LISTS CURL_FIND_COMPONENTS)
162    list(FIND CURL_KNOWN_PROTOCOLS ${component} _found)
163    if(NOT _found EQUAL -1)
164      list(FIND CURL_SUPPORTED_PROTOCOLS ${component} _found)
165      if(NOT _found EQUAL -1)
166        set(CURL_${component}_FOUND TRUE)
167      elseif(CURL_FIND_REQUIRED)
168        message(FATAL_ERROR "CURL: Required protocol ${component} is not found")
169      endif()
170    else()
171      list(FIND CURL_SUPPORTED_FEATURES ${component} _found)
172      if(NOT _found EQUAL -1)
173        set(CURL_${component}_FOUND TRUE)
174      elseif(CURL_FIND_REQUIRED)
175        message(FATAL_ERROR "CURL: Required feature ${component} is not found")
176      endif()
177    endif()
178  endforeach()
179endif()
180
181find_package_handle_standard_args(CURL
182                                  REQUIRED_VARS CURL_LIBRARY CURL_INCLUDE_DIR
183                                  VERSION_VAR CURL_VERSION_STRING
184                                  HANDLE_COMPONENTS)
185
186if(CURL_FOUND)
187  set(CURL_LIBRARIES ${CURL_LIBRARY})
188  set(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIR})
189
190  if(NOT TARGET CURL::libcurl)
191    add_library(CURL::libcurl UNKNOWN IMPORTED)
192    set_target_properties(CURL::libcurl PROPERTIES
193      INTERFACE_INCLUDE_DIRECTORIES "${CURL_INCLUDE_DIRS}")
194
195    if(EXISTS "${CURL_LIBRARY}")
196      set_target_properties(CURL::libcurl PROPERTIES
197        IMPORTED_LINK_INTERFACE_LANGUAGES "C"
198        IMPORTED_LOCATION "${CURL_LIBRARY}")
199    endif()
200    if(CURL_LIBRARY_RELEASE)
201      set_property(TARGET CURL::libcurl APPEND PROPERTY
202        IMPORTED_CONFIGURATIONS RELEASE)
203      set_target_properties(CURL::libcurl PROPERTIES
204        IMPORTED_LINK_INTERFACE_LANGUAGES "C"
205        IMPORTED_LOCATION_RELEASE "${CURL_LIBRARY_RELEASE}")
206    endif()
207    if(CURL_LIBRARY_DEBUG)
208      set_property(TARGET CURL::libcurl APPEND PROPERTY
209        IMPORTED_CONFIGURATIONS DEBUG)
210      set_target_properties(CURL::libcurl PROPERTIES
211        IMPORTED_LINK_INTERFACE_LANGUAGES "C"
212        IMPORTED_LOCATION_DEBUG "${CURL_LIBRARY_DEBUG}")
213    endif()
214  endif()
215endif()
216