Merge pull request #25883 from CrystalP/fix-slowscan
[xbmc.git] / cmake / modules / FindCurl.cmake
blob3ce4ed58297499e615b246df82a0e0a69698461e
1 #.rst:
2 # FindCurl
3 # --------
4 # Finds the Curl library
6 # This will define the following target:
8 #   ${APP_NAME_LC}::Curl   - The Curl library
10 if(NOT TARGET ${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME})
11   include(cmake/scripts/common/ModuleHelpers.cmake)
13   macro(buildCurl)
14     find_package(Brotli REQUIRED QUIET)
15     find_package(NGHttp2 REQUIRED QUIET)
16     find_package(OpenSSL REQUIRED QUIET)
18     # Darwin platforms link against toolchain provided zlib regardless
19     # They will fail when searching for static. All other platforms, prefer static
20     # if possible (requires cmake 3.24+ otherwise variable is a no-op)
21     # Windows still uses dynamic lib for zlib for other purposes, dont mix
22     if(NOT CMAKE_SYSTEM_NAME MATCHES "Darwin" AND NOT (WIN32 OR WINDOWS_STORE))
23       set(ZLIB_USE_STATIC_LIBS ON)
24     endif()
25     find_package(Zlib REQUIRED)
26     unset(ZLIB_USE_STATIC_LIBS)
28     set(CURL_VERSION ${${MODULE}_VER})
29     # Curl debug uses postfix -d for all platforms
30     set(CURL_DEBUG_POSTFIX -d)
32     if(WIN32 OR WINDOWS_STORE)
33       set(CURL_C_FLAGS -DNGHTTP2_STATICLIB)
34       set(PLATFORM_LINK_LIBS crypt32.lib)
35     endif()
37     set(CMAKE_ARGS -DBUILD_CURL_EXE=OFF
38                    -DBUILD_SHARED_LIBS=OFF
39                    -DBUILD_STATIC_LIBS=ON
40                    -DBUILD_LIBCURL_DOCS=OFF
41                    -DENABLE_CURL_MANUAL=OFF
42                    -DCURL_DISABLE_TESTS=OFF
43                    -DCURL_DISABLE_LDAP=ON
44                    -DCURL_DISABLE_LDAPS=ON
45                    -DCURL_DISABLE_SMB=OFF
46                    -DCURL_USE_OPENSSL=ON
47                    -DOPENSSL_ROOT_DIR=${DEPENDS_PATH}
48                    -DCURL_BROTLI=ON
49                    -DUSE_NGHTTP2=ON
50                    -DUSE_LIBIDN2=OFF
51                    -DCURL_USE_LIBSSH2=OFF
52                    -DCURL_USE_GSSAPI=OFF
53                    -DCURL_CA_FALLBACK=ON
54                    ${OPTIONAL_ARGS})
56     BUILD_DEP_TARGET()
58     # Link libraries for target interface
59     set(PC_CURL_LINK_LIBRARIES Brotli::Brotli NGHttp2::NGHttp2 OpenSSL::Crypto OpenSSL::SSL ZLIB::ZLIB ${PLATFORM_LINK_LIBS})
61     # Add dependencies to build target
62     add_dependencies(${MODULE_LC} Brotli::Brotli)
63     add_dependencies(${MODULE_LC} NGHttp2::NGHttp2)
64     add_dependencies(${MODULE_LC} OpenSSL::SSL)
65     add_dependencies(${MODULE_LC} OpenSSL::Crypto)
66     add_dependencies(${MODULE_LC} ZLIB::ZLIB)
67   endmacro()
69   set(MODULE_LC curl)
71   SETUP_BUILD_VARS()
73   find_package(CURL CONFIG QUIET
74                     HINTS ${DEPENDS_PATH}/lib/cmake
75                     ${${CORE_PLATFORM_NAME_LC}_SEARCH_CONFIG})
77   # Check for existing Curl. If version >= CURL-VERSION file version, dont build
78   # A corner case, but if a linux/freebsd user WANTS to build internal curl, build anyway
79   if((CURL_VERSION VERSION_LESS ${${MODULE}_VER} AND ENABLE_INTERNAL_CURL) OR
80      ((CORE_SYSTEM_NAME STREQUAL linux OR CORE_SYSTEM_NAME STREQUAL freebsd) AND ENABLE_INTERNAL_CURL))
82     buildCurl()
83   else()
84     # Maybe need to look explicitly for CURL::libcurl_static/shared?
85     if(NOT TARGET CURL::libcurl)
86       find_package(PkgConfig)
88       # We only rely on pkgconfig for non windows platforms
89       if(PKG_CONFIG_FOUND AND NOT (WIN32 OR WINDOWS_STORE))
90         pkg_check_modules(CURL libcurl QUIET)
92         # First item is the full path of the library file found
93         # pkg_check_modules does not populate a variable of the found library explicitly
94         list(GET CURL_LINK_LIBRARIES 0 CURL_LIBRARY_RELEASE)
96         # Add link libraries for static lib usage
97         if(${CURL_LIBRARY} MATCHES ".+\.a$" AND CURL_LINK_LIBRARIES)
98           # Remove duplicates
99           list(REMOVE_DUPLICATES CURL_LINK_LIBRARIES)
101           # Remove own library - eg libcurl.a
102           list(FILTER CURL_LINK_LIBRARIES EXCLUDE REGEX ".*curl.*\.a$")
103           set(PC_CURL_LINK_LIBRARIES ${CURL_LINK_LIBRARIES})
104         endif()
106         # pkgconfig sets CURL_INCLUDEDIR, map this to our "standard" variable name
107         set(CURL_INCLUDE_DIR ${CURL_INCLUDEDIR})
108       else()
109         find_path(CURL_INCLUDE_DIR NAMES curl/curl.h
110                                    HINTS ${DEPENDS_PATH}/include
111                                    ${${CORE_PLATFORM_LC}_SEARCH_CONFIG})
112         find_library(CURL_LIBRARY_RELEASE NAMES curl libcurl libcurl_imp
113                                           HINTS ${DEPENDS_PATH}/lib
114                                           ${${CORE_PLATFORM_LC}_SEARCH_CONFIG})
115       endif()
116     else()
117       # CURL::libcurl is an alias. We need to get the actual aias target, as we cant make an
118       # alias of an alias (ie our ${APP_NAME_LC}::Curl cant be an alias of Curl::libcurl)
119       get_target_property(_CURL_ALIASTARGET CURL::libcurl ALIASED_TARGET)
121       # This is for the case where a distro provides a non standard (Debug/Release) config type
122       # eg Debian's config file is CURLConfigTargets-none.cmake
123       # convert this back to either DEBUG/RELEASE or just RELEASE
124       # we only do this because we use find_package_handle_standard_args for config time output
125       # and it isnt capable of handling TARGETS, so we have to extract the info
126       get_target_property(_CURL_CONFIGURATIONS ${_CURL_ALIASTARGET} IMPORTED_CONFIGURATIONS)
127       foreach(_curl_config IN LISTS _CURL_CONFIGURATIONS)
128         # Some non standard config (eg None on Debian)
129         # Just set to RELEASE var so select_library_configurations can continue to work its magic
130         string(TOUPPER ${_curl_config} _curl_config_UPPER)
131         if((NOT ${_curl_config_UPPER} STREQUAL "RELEASE") AND
132            (NOT ${_curl_config_UPPER} STREQUAL "DEBUG"))
133           get_target_property(CURL_LIBRARY_RELEASE ${_CURL_ALIASTARGET} IMPORTED_LOCATION_${_curl_config_UPPER})
134         else()
135           get_target_property(CURL_LIBRARY_${_curl_config_UPPER} ${_CURL_ALIASTARGET} IMPORTED_LOCATION_${_curl_config_UPPER})
136         endif()
137       endforeach()
139       get_target_property(CURL_INCLUDE_DIR CURL::libcurl INTERFACE_INCLUDE_DIRECTORIES)
140     endif()
141   endif()
143   include(SelectLibraryConfigurations)
144   select_library_configurations(CURL)
145   unset(CURL_LIBRARIES)
147   include(FindPackageHandleStandardArgs)
148   find_package_handle_standard_args(Curl
149                                     REQUIRED_VARS CURL_LIBRARY CURL_INCLUDE_DIR
150                                     VERSION_VAR CURL_VERSION)
152   if(CURL_FOUND)
153     # cmake target and not building internal
154     if(TARGET CURL::libcurl AND NOT TARGET curl)
155       # CURL::libcurl is an alias. We need to get the actual aias target, as we cant make an
156       # alias of an alias (ie our ${APP_NAME_LC}::Curl cant be an alias of Curl::libcurl)
157       if(NOT _CURL_ALIASTARGET)
158         get_target_property(_CURL_ALIASTARGET CURL::libcurl ALIASED_TARGET)
159       endif()
161       add_library(${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} ALIAS ${_CURL_ALIASTARGET})
162     else()
163       add_library(${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} UNKNOWN IMPORTED)
164       set_target_properties(${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} PROPERTIES
165                                                                        INTERFACE_INCLUDE_DIRECTORIES "${CURL_INCLUDE_DIR}")
167       if(CURL_LIBRARY_RELEASE)
168         set_target_properties(${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} PROPERTIES
169                                                                          IMPORTED_CONFIGURATIONS RELEASE
170                                                                          IMPORTED_LOCATION_RELEASE "${CURL_LIBRARY_RELEASE}")
171       endif()
172       if(CURL_LIBRARY_DEBUG)
173         set_target_properties(${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} PROPERTIES
174                                                                          IMPORTED_LOCATION_DEBUG "${CURL_LIBRARY_DEBUG}")
175         set_property(TARGET ${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} APPEND PROPERTY
176                                                                               IMPORTED_CONFIGURATIONS DEBUG)
177       endif()
179       # Add link libraries for static lib usage found from pkg-config
180       if(PC_CURL_LINK_LIBRARIES)
181         set_target_properties(${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} PROPERTIES
182                                                                          INTERFACE_LINK_LIBRARIES "${PC_CURL_LINK_LIBRARIES}")
183       endif()
185       if(WIN32 OR WINDOWS_STORE)
186         set_property(TARGET ${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB")
187       endif()
189     endif()
191     if(TARGET curl)
192       add_dependencies(${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME} curl)
193     endif()
195     # Add internal build target when a Multi Config Generator is used
196     # We cant add a dependency based off a generator expression for targeted build types,
197     # https://gitlab.kitware.com/cmake/cmake/-/issues/19467
198     # therefore if the find heuristics only find the library, we add the internal build
199     # target to the project to allow user to manually trigger for any build type they need
200     # in case only a specific build type is actually available (eg Release found, Debug Required)
201     # This is mainly targeted for windows who required different runtime libs for different
202     # types, and they arent compatible
203     if(_multiconfig_generator)
204       if(NOT TARGET curl)
205         buildCurl()
206         set_target_properties(curl PROPERTIES EXCLUDE_FROM_ALL TRUE)
207       endif()
208       add_dependencies(build_internal_depends curl)
209     endif()
210   else()
211     if(Curl_FIND_REQUIRED)
212       message(FATAL_ERROR "Curl libraries were not found.")
213     endif()
214   endif()
215 endif()