FindGSS.cmake 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. #***************************************************************************
  2. # _ _ ____ _
  3. # Project ___| | | | _ \| |
  4. # / __| | | | |_) | |
  5. # | (__| |_| | _ <| |___
  6. # \___|\___/|_| \_\_____|
  7. #
  8. # Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
  9. #
  10. # This software is licensed as described in the file COPYING, which
  11. # you should have received as part of this distribution. The terms
  12. # are also available at https://curl.se/docs/copyright.html.
  13. #
  14. # You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. # copies of the Software, and permit persons to whom the Software is
  16. # furnished to do so, under the terms of the COPYING file.
  17. #
  18. # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. # KIND, either express or implied.
  20. #
  21. # SPDX-License-Identifier: curl
  22. #
  23. ###########################################################################
  24. # Find the GSS Kerberos library
  25. #
  26. # Input variables:
  27. #
  28. # - `GSS_ROOT_DIR`: Set this variable to the root installation of GSS. (also supported as environment)
  29. #
  30. # Result variables:
  31. #
  32. # - `GSS_FOUND`: System has the Heimdal library.
  33. # - `GSS_FLAVOUR`: "GNU", "MIT" or "Heimdal" if anything found.
  34. # - `GSS_INCLUDE_DIRS`: The GSS include directories.
  35. # - `GSS_LIBRARIES`: The GSS library names.
  36. # - `GSS_LIBRARY_DIRS`: The GSS library directories.
  37. # - `GSS_LDFLAGS`: Required linker flags.
  38. # - `GSS_CFLAGS`: Required compiler flags.
  39. # - `GSS_VERSION`: This is set to version advertised by pkg-config or read from manifest.
  40. # In case the library is found but no version info available it is set to "unknown"
  41. set(_gnu_modname "gss")
  42. set(_mit_modname "mit-krb5-gssapi")
  43. set(_heimdal_modname "heimdal-gssapi")
  44. include(CheckIncludeFile)
  45. include(CheckIncludeFiles)
  46. include(CheckTypeSize)
  47. set(_gss_root_hints
  48. "${GSS_ROOT_DIR}"
  49. "$ENV{GSS_ROOT_DIR}"
  50. )
  51. # Try to find library using system pkg-config if user did not specify root dir
  52. if(NOT GSS_ROOT_DIR AND NOT "$ENV{GSS_ROOT_DIR}")
  53. if(CURL_USE_PKGCONFIG)
  54. find_package(PkgConfig QUIET)
  55. pkg_search_module(_GSS ${_gnu_modname} ${_mit_modname} ${_heimdal_modname})
  56. list(APPEND _gss_root_hints "${_GSS_PREFIX}")
  57. endif()
  58. if(WIN32)
  59. list(APPEND _gss_root_hints "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]")
  60. endif()
  61. endif()
  62. if(NOT _GSS_FOUND) # Not found by pkg-config. Let us take more traditional approach.
  63. find_file(_gss_configure_script
  64. NAMES
  65. "krb5-config"
  66. HINTS
  67. ${_gss_root_hints}
  68. PATH_SUFFIXES
  69. "bin"
  70. NO_CMAKE_PATH
  71. NO_CMAKE_ENVIRONMENT_PATH
  72. )
  73. # If not found in user-supplied directories, maybe system knows better
  74. find_file(_gss_configure_script
  75. NAMES
  76. "krb5-config"
  77. PATH_SUFFIXES
  78. "bin"
  79. )
  80. if(_gss_configure_script)
  81. execute_process(
  82. COMMAND ${_gss_configure_script} "--cflags" "gssapi"
  83. OUTPUT_VARIABLE _GSS_CFLAGS
  84. RESULT_VARIABLE _gss_configure_failed
  85. OUTPUT_STRIP_TRAILING_WHITESPACE
  86. )
  87. message(STATUS "FindGSS CFLAGS: ${_GSS_CFLAGS}")
  88. if(NOT _gss_configure_failed) # 0 means success
  89. # Should also work in an odd case when multiple directories are given
  90. string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
  91. string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
  92. string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1" _GSS_CFLAGS "${_GSS_CFLAGS}")
  93. foreach(_flag IN LISTS _GSS_CFLAGS)
  94. if(_flag MATCHES "^-I.*")
  95. string(REGEX REPLACE "^-I" "" _val "${_flag}")
  96. list(APPEND _GSS_INCLUDE_DIRS "${_val}")
  97. else()
  98. list(APPEND _GSS_CFLAGS "${_flag}")
  99. endif()
  100. endforeach()
  101. endif()
  102. execute_process(
  103. COMMAND ${_gss_configure_script} "--libs" "gssapi"
  104. OUTPUT_VARIABLE _gss_lib_flags
  105. RESULT_VARIABLE _gss_configure_failed
  106. OUTPUT_STRIP_TRAILING_WHITESPACE
  107. )
  108. message(STATUS "FindGSS LDFLAGS: ${_gss_lib_flags}")
  109. if(NOT _gss_configure_failed) # 0 means success
  110. # This script gives us libraries and link directories. Blah. We have to deal with it.
  111. string(STRIP "${_gss_lib_flags}" _gss_lib_flags)
  112. string(REGEX REPLACE " +-(L|l)" ";-\\1" _gss_lib_flags "${_gss_lib_flags}")
  113. string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1" _gss_lib_flags "${_gss_lib_flags}")
  114. foreach(_flag IN LISTS _gss_lib_flags)
  115. if(_flag MATCHES "^-l.*")
  116. string(REGEX REPLACE "^-l" "" _val "${_flag}")
  117. list(APPEND _GSS_LIBRARIES "${_val}")
  118. elseif(_flag MATCHES "^-L.*")
  119. string(REGEX REPLACE "^-L" "" _val "${_flag}")
  120. list(APPEND _GSS_LIBRARY_DIRS "${_val}")
  121. else()
  122. list(APPEND _GSS_LDFLAGS "${_flag}")
  123. endif()
  124. endforeach()
  125. endif()
  126. execute_process(
  127. COMMAND ${_gss_configure_script} "--version"
  128. OUTPUT_VARIABLE _GSS_VERSION
  129. RESULT_VARIABLE _gss_configure_failed
  130. OUTPUT_STRIP_TRAILING_WHITESPACE
  131. )
  132. # Older versions may not have the "--version" parameter. In this case we just do not care.
  133. if(_gss_configure_failed)
  134. set(_GSS_VERSION 0)
  135. endif()
  136. execute_process(
  137. COMMAND ${_gss_configure_script} "--vendor"
  138. OUTPUT_VARIABLE _gss_vendor
  139. RESULT_VARIABLE _gss_configure_failed
  140. OUTPUT_STRIP_TRAILING_WHITESPACE
  141. )
  142. # Older versions may not have the "--vendor" parameter. In this case we just do not care.
  143. if(_gss_configure_failed)
  144. set(GSS_FLAVOUR "Heimdal") # most probably, should not really matter
  145. else()
  146. if(_gss_vendor MATCHES ".*H|heimdal.*")
  147. set(GSS_FLAVOUR "Heimdal")
  148. else()
  149. set(GSS_FLAVOUR "MIT")
  150. endif()
  151. endif()
  152. else() # Either there is no config script or we are on a platform that does not provide one (Windows?)
  153. find_path(_GSS_INCLUDE_DIRS NAMES "gssapi/gssapi.h"
  154. HINTS
  155. ${_gss_root_hints}
  156. PATH_SUFFIXES
  157. "include"
  158. "inc"
  159. )
  160. if(_GSS_INCLUDE_DIRS) # jay, we have found something
  161. cmake_push_check_state()
  162. set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIRS}")
  163. check_include_files("gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _gss_have_mit_headers)
  164. if(_gss_have_mit_headers)
  165. set(GSS_FLAVOUR "MIT")
  166. else()
  167. # Prevent compiling the header - just check if we can include it
  168. list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D__ROKEN_H__")
  169. check_include_file("roken.h" _gss_have_roken_h)
  170. check_include_file("heimdal/roken.h" _gss_have_heimdal_roken_h)
  171. if(_gss_have_roken_h OR _gss_have_heimdal_roken_h)
  172. set(GSS_FLAVOUR "Heimdal")
  173. endif()
  174. endif()
  175. cmake_pop_check_state()
  176. else()
  177. # I am not convinced if this is the right way but this is what autotools do at the moment
  178. find_path(_GSS_INCLUDE_DIRS NAMES "gssapi.h"
  179. HINTS
  180. ${_gss_root_hints}
  181. PATH_SUFFIXES
  182. "include"
  183. "inc"
  184. )
  185. if(_GSS_INCLUDE_DIRS)
  186. set(GSS_FLAVOUR "Heimdal")
  187. else()
  188. find_path(_GSS_INCLUDE_DIRS NAMES "gss.h"
  189. HINTS
  190. ${_gss_root_hints}
  191. PATH_SUFFIXES
  192. "include"
  193. )
  194. if(_GSS_INCLUDE_DIRS)
  195. set(GSS_FLAVOUR "GNU")
  196. endif()
  197. endif()
  198. endif()
  199. # If we have headers, check if we can link libraries
  200. if(GSS_FLAVOUR)
  201. set(_gss_libdir_suffixes "")
  202. set(_gss_libdir_hints ${_gss_root_hints})
  203. get_filename_component(_gss_calculated_potential_root "${_GSS_INCLUDE_DIRS}" DIRECTORY)
  204. list(APPEND _gss_libdir_hints ${_gss_calculated_potential_root})
  205. if(WIN32)
  206. if(CMAKE_SIZEOF_VOID_P EQUAL 8)
  207. list(APPEND _gss_libdir_suffixes "lib/AMD64")
  208. if(GSS_FLAVOUR STREQUAL "GNU")
  209. set(_gss_libname "gss")
  210. elseif(GSS_FLAVOUR STREQUAL "MIT")
  211. set(_gss_libname "gssapi64")
  212. else()
  213. set(_gss_libname "libgssapi")
  214. endif()
  215. else()
  216. list(APPEND _gss_libdir_suffixes "lib/i386")
  217. if(GSS_FLAVOUR STREQUAL "GNU")
  218. set(_gss_libname "gss")
  219. elseif(GSS_FLAVOUR STREQUAL "MIT")
  220. set(_gss_libname "gssapi32")
  221. else()
  222. set(_gss_libname "libgssapi")
  223. endif()
  224. endif()
  225. else()
  226. list(APPEND _gss_libdir_suffixes "lib;lib64") # those suffixes are not checked for HINTS
  227. if(GSS_FLAVOUR STREQUAL "GNU")
  228. set(_gss_libname "gss")
  229. elseif(GSS_FLAVOUR STREQUAL "MIT")
  230. set(_gss_libname "gssapi_krb5")
  231. else()
  232. set(_gss_libname "gssapi")
  233. endif()
  234. endif()
  235. find_library(_GSS_LIBRARIES NAMES ${_gss_libname}
  236. HINTS
  237. ${_gss_libdir_hints}
  238. PATH_SUFFIXES
  239. ${_gss_libdir_suffixes}
  240. )
  241. endif()
  242. endif()
  243. else()
  244. # _GSS_MODULE_NAME set since CMake 3.16
  245. if(_GSS_MODULE_NAME STREQUAL _gnu_modname OR _GSS_${_gnu_modname}_VERSION)
  246. set(GSS_FLAVOUR "GNU")
  247. if(NOT _GSS_VERSION) # for old CMake versions?
  248. set(_GSS_VERSION ${_GSS_${_gnu_modname}_VERSION})
  249. endif()
  250. elseif(_GSS_MODULE_NAME STREQUAL _mit_modname OR _GSS_${_mit_modname}_VERSION)
  251. set(GSS_FLAVOUR "MIT")
  252. if(NOT _GSS_VERSION) # for old CMake versions?
  253. set(_GSS_VERSION ${_GSS_${_mit_modname}_VERSION})
  254. endif()
  255. else()
  256. set(GSS_FLAVOUR "Heimdal")
  257. if(NOT _GSS_VERSION) # for old CMake versions?
  258. set(_GSS_VERSION ${_GSS_${_heimdal_modname}_VERSION})
  259. endif()
  260. endif()
  261. message(STATUS "Found GSS/${GSS_FLAVOUR} (via pkg-config): ${_GSS_INCLUDE_DIRS} (found version \"${_GSS_VERSION}\")")
  262. endif()
  263. set(GSS_INCLUDE_DIRS ${_GSS_INCLUDE_DIRS})
  264. set(GSS_LIBRARIES ${_GSS_LIBRARIES})
  265. set(GSS_LIBRARY_DIRS ${_GSS_LIBRARY_DIRS})
  266. set(GSS_LDFLAGS ${_GSS_LDFLAGS})
  267. set(GSS_CFLAGS ${_GSS_CFLAGS})
  268. set(GSS_VERSION ${_GSS_VERSION})
  269. if(GSS_FLAVOUR)
  270. if(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "Heimdal")
  271. if(CMAKE_SIZEOF_VOID_P EQUAL 8)
  272. set(_heimdal_manifest_file "Heimdal.Application.amd64.manifest")
  273. else()
  274. set(_heimdal_manifest_file "Heimdal.Application.x86.manifest")
  275. endif()
  276. if(EXISTS "${GSS_INCLUDE_DIRS}/${_heimdal_manifest_file}")
  277. file(STRINGS "${GSS_INCLUDE_DIRS}/${_heimdal_manifest_file}" _heimdal_version_str
  278. REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$")
  279. string(REGEX MATCH "[0-9]\\.[^\"]+" GSS_VERSION "${_heimdal_version_str}")
  280. endif()
  281. if(NOT GSS_VERSION)
  282. set(GSS_VERSION "Heimdal Unknown")
  283. endif()
  284. elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT")
  285. get_filename_component(_mit_version "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME
  286. CACHE)
  287. if(WIN32 AND _mit_version)
  288. set(GSS_VERSION "${_mit_version}")
  289. else()
  290. set(GSS_VERSION "MIT Unknown")
  291. endif()
  292. elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "GNU")
  293. if(GSS_INCLUDE_DIRS AND EXISTS "${GSS_INCLUDE_DIRS}/gss.h")
  294. set(_version_regex "#[\t ]*define[\t ]+GSS_VERSION[\t ]+\"([^\"]*)\"")
  295. file(STRINGS "${GSS_INCLUDE_DIRS}/gss.h" _version_str REGEX "${_version_regex}")
  296. string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
  297. set(GSS_VERSION "${_version_str}")
  298. unset(_version_regex)
  299. unset(_version_str)
  300. endif()
  301. endif()
  302. endif()
  303. include(FindPackageHandleStandardArgs)
  304. find_package_handle_standard_args(GSS
  305. REQUIRED_VARS
  306. GSS_FLAVOUR
  307. GSS_LIBRARIES
  308. VERSION_VAR
  309. GSS_VERSION
  310. FAIL_MESSAGE
  311. "Could NOT find GSS, try to set the path to GSS root folder in the system variable GSS_ROOT_DIR"
  312. )
  313. mark_as_advanced(
  314. _GSS_CFLAGS
  315. _GSS_FOUND
  316. _GSS_INCLUDE_DIRS
  317. _GSS_LDFLAGS
  318. _GSS_LIBRARIES
  319. _GSS_LIBRARY_DIRS
  320. _GSS_MODULE_NAME
  321. _GSS_PREFIX
  322. _GSS_VERSION
  323. )