curl/CMake/FindGSS.cmake
Viktor Szakats 146759716c
cmake: fix pkg-config-based detection in FindGSS.cmake
Before this patch `pkg-config`-based detection was ignored, and used
solely as a path hint for native detection.

- fix `pkg_search_module()` result prefix to match what code expects:
  `_GSS` (was: `_GSS_PKG`). Update variable that were in sync with old
  prefix.

- update the pkg-config codepath to use `_GSS_MODULE_NAME` to detect
  GSS flavour. This requires CMake 3.16.
  Otherwise fall back to the old method. (The old method doesn't seem to
  work anymore (?) as of CMake 3.30.1. Documented
  `<prefix>_<modulename>_VERSION` variable is defined, but empty.)

- update the pkg-config codepath to use `_GSS_VERSION` set by CMake.
  Resort to the old code when this variable is empty. (The old code
  doesn't seem to work anymore (?) as of CMake 3.30.1)

- fix pkg-config codepath to set the documented result variables.

- align native detection variable names with those generated by
  `pkg_search_module()` in the pkg-config codepath.

- GHA/macos: enable GSS Heimdal in a cmake job.
  Uses the native detection.

- GHA/linux: enable GSS Heimdal in cmake and autotools jobs.
  CMake uses `pkg-config`-based detection.

- suppress test 2077 and 2078 results on Linux + Heimdal.
  ```
  FAIL-IGNORED 2077: 'curl --fail --negotiate to unauthenticated service fails' HTTP, HTTP GET, GSS-API
  FAIL-IGNORED 2078: 'curl --negotiate should not send empty POST request only' HTTP, HTTP GET, GSS-API
  ```
  Failing with valgrind errors in both autotools and cmake builds:
  https://github.com/curl/curl/actions/runs/10282222581/job/28453472068?pr=14430#step:38:3638
  https://github.com/curl/curl/actions/runs/10282222581/job/28453473398?pr=14430#step:38:7831

Closes #14430
2024-08-07 15:13:07 +02:00

316 lines
10 KiB
CMake

#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
# - Try to find the GSS Kerberos library
# Once done this defines
#
# GSS_ROOT_DIR - Set this variable to the root installation of GSS
#
# Read-Only variables:
# GSS_FOUND - system has the Heimdal library
# GSS_FLAVOUR - "MIT" or "Heimdal" if anything found.
# GSS_INCLUDE_DIR - the Heimdal include directory
# GSS_LIBRARIES - The libraries needed to use GSS
# GSS_LINK_DIRECTORIES - Directories to add to linker search path
# GSS_LINKER_FLAGS - Additional linker flags
# GSS_COMPILER_FLAGS - Additional compiler flags
# GSS_VERSION - This is set to version advertised by pkg-config or read from manifest.
# In case the library is found but no version info available it is set to "unknown"
set(_MIT_MODNAME mit-krb5-gssapi)
set(_HEIMDAL_MODNAME heimdal-gssapi)
include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckTypeSize)
set(_GSS_ROOT_HINTS
"${GSS_ROOT_DIR}"
"$ENV{GSS_ROOT_DIR}"
)
# Try to find library using system pkg-config if user did not specify root dir
if(NOT GSS_ROOT_DIR AND NOT "$ENV{GSS_ROOT_DIR}")
if(UNIX)
find_package(PkgConfig QUIET)
pkg_search_module(_GSS ${_MIT_MODNAME} ${_HEIMDAL_MODNAME})
list(APPEND _GSS_ROOT_HINTS "${_GSS_PREFIX}")
elseif(WIN32)
list(APPEND _GSS_ROOT_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]")
endif()
endif()
if(NOT _GSS_FOUND) # Not found by pkg-config. Let us take more traditional approach.
find_file(_GSS_CONFIGURE_SCRIPT
NAMES
"krb5-config"
HINTS
${_GSS_ROOT_HINTS}
PATH_SUFFIXES
bin
NO_CMAKE_PATH
NO_CMAKE_ENVIRONMENT_PATH
)
# If not found in user-supplied directories, maybe system knows better
find_file(_GSS_CONFIGURE_SCRIPT
NAMES
"krb5-config"
PATH_SUFFIXES
bin
)
if(_GSS_CONFIGURE_SCRIPT)
execute_process(
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi"
OUTPUT_VARIABLE _GSS_CFLAGS
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
OUTPUT_STRIP_TRAILING_WHITESPACE
)
message(STATUS "CFLAGS: ${_GSS_CFLAGS}")
if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
# Should also work in an odd case when multiple directories are given
string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1" _GSS_CFLAGS "${_GSS_CFLAGS}")
foreach(_flag ${_GSS_CFLAGS})
if(_flag MATCHES "^-I.*")
string(REGEX REPLACE "^-I" "" _val "${_flag}")
list(APPEND _GSS_INCLUDE_DIRS "${_val}")
else()
list(APPEND _GSS_CFLAGS "${_flag}")
endif()
endforeach()
endif()
execute_process(
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi"
OUTPUT_VARIABLE _GSS_LIB_FLAGS
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
OUTPUT_STRIP_TRAILING_WHITESPACE
)
message(STATUS "LDFLAGS: ${_GSS_LIB_FLAGS}")
if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
# This script gives us libraries and link directories. Blah. We have to deal with it.
string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS)
string(REGEX REPLACE " +-(L|l)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
foreach(_flag ${_GSS_LIB_FLAGS})
if(_flag MATCHES "^-l.*")
string(REGEX REPLACE "^-l" "" _val "${_flag}")
list(APPEND _GSS_LIBRARIES "${_val}")
elseif(_flag MATCHES "^-L.*")
string(REGEX REPLACE "^-L" "" _val "${_flag}")
list(APPEND _GSS_LIBRARY_DIRS "${_val}")
else()
list(APPEND _GSS_LDFLAGS "${_flag}")
endif()
endforeach()
endif()
execute_process(
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version"
OUTPUT_VARIABLE _GSS_VERSION
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Older versions may not have the "--version" parameter. In this case we just do not care.
if(_GSS_CONFIGURE_FAILED)
set(_GSS_VERSION 0)
endif()
execute_process(
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor"
OUTPUT_VARIABLE _GSS_VENDOR
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Older versions may not have the "--vendor" parameter. In this case we just do not care.
if(_GSS_CONFIGURE_FAILED)
set(GSS_FLAVOUR "Heimdal") # most probably, should not really matter
else()
if(_GSS_VENDOR MATCHES ".*H|heimdal.*")
set(GSS_FLAVOUR "Heimdal")
else()
set(GSS_FLAVOUR "MIT")
endif()
endif()
else() # Either there is no config script or we are on a platform that does not provide one (Windows?)
find_path(_GSS_INCLUDE_DIRS
NAMES
"gssapi/gssapi.h"
HINTS
${_GSS_ROOT_HINTS}
PATH_SUFFIXES
include
inc
)
if(_GSS_INCLUDE_DIRS) # jay, we have found something
set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIRS}")
check_include_files( "gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _GSS_HAVE_MIT_HEADERS)
if(_GSS_HAVE_MIT_HEADERS)
set(GSS_FLAVOUR "MIT")
else()
# Prevent compiling the header - just check if we can include it
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D__ROKEN_H__)
check_include_file( "roken.h" _GSS_HAVE_ROKEN_H)
check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H)
if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H)
set(GSS_FLAVOUR "Heimdal")
endif()
list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D__ROKEN_H__)
endif()
else()
# I am not convinced if this is the right way but this is what autotools do at the moment
find_path(_GSS_INCLUDE_DIRS
NAMES
"gssapi.h"
HINTS
${_GSS_ROOT_HINTS}
PATH_SUFFIXES
include
inc
)
if(_GSS_INCLUDE_DIRS)
set(GSS_FLAVOUR "Heimdal")
endif()
endif()
# If we have headers, check if we can link libraries
if(GSS_FLAVOUR)
set(_GSS_LIBDIR_SUFFIXES "")
set(_GSS_LIBDIR_HINTS ${_GSS_ROOT_HINTS})
get_filename_component(_GSS_CALCULATED_POTENTIAL_ROOT "${_GSS_INCLUDE_DIRS}" PATH)
list(APPEND _GSS_LIBDIR_HINTS ${_GSS_CALCULATED_POTENTIAL_ROOT})
if(WIN32)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
list(APPEND _GSS_LIBDIR_SUFFIXES "lib/AMD64")
if(GSS_FLAVOUR STREQUAL "MIT")
set(_GSS_LIBNAME "gssapi64")
else()
set(_GSS_LIBNAME "libgssapi")
endif()
else()
list(APPEND _GSS_LIBDIR_SUFFIXES "lib/i386")
if(GSS_FLAVOUR STREQUAL "MIT")
set(_GSS_LIBNAME "gssapi32")
else()
set(_GSS_LIBNAME "libgssapi")
endif()
endif()
else()
list(APPEND _GSS_LIBDIR_SUFFIXES "lib;lib64") # those suffixes are not checked for HINTS
if(GSS_FLAVOUR STREQUAL "MIT")
set(_GSS_LIBNAME "gssapi_krb5")
else()
set(_GSS_LIBNAME "gssapi")
endif()
endif()
find_library(_GSS_LIBRARIES
NAMES
${_GSS_LIBNAME}
HINTS
${_GSS_LIBDIR_HINTS}
PATH_SUFFIXES
${_GSS_LIBDIR_SUFFIXES}
)
endif()
endif()
else()
if(_GSS_MODULE_NAME STREQUAL _MIT_MODNAME OR _GSS_${_MIT_MODNAME}_VERSION) # _GSS_MODULE_NAME set since CMake 3.16
set(GSS_FLAVOUR "MIT")
if(NOT _GSS_VERSION) # for old CMake versions?
set(_GSS_VERSION _GSS_${_MIT_MODNAME}_VERSION)
endif()
else()
set(GSS_FLAVOUR "Heimdal")
if(NOT _GSS_VERSION) # for old CMake versions?
set(_GSS_VERSION _GSS_${_HEIMDAL_MODNAME}_VERSION)
endif()
endif()
endif()
set(GSS_INCLUDE_DIR ${_GSS_INCLUDE_DIRS})
set(GSS_LIBRARIES ${_GSS_LIBRARIES})
set(GSS_LINK_DIRECTORIES ${_GSS_LIBRARY_DIRS})
set(GSS_LINKER_FLAGS ${_GSS_LDFLAGS})
set(GSS_COMPILER_FLAGS ${_GSS_CFLAGS})
set(GSS_VERSION ${_GSS_VERSION})
if(GSS_FLAVOUR)
if(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "Heimdal")
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.amd64.manifest")
else()
set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.x86.manifest")
endif()
if(EXISTS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}")
file(STRINGS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}" _heimdal_version_str
REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$")
string(REGEX MATCH "[0-9]\\.[^\"]+"
GSS_VERSION "${_heimdal_version_str}")
endif()
if(NOT GSS_VERSION)
set(GSS_VERSION "Heimdal Unknown")
endif()
elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT")
get_filename_component(_MIT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME CACHE)
if(WIN32 AND _MIT_VERSION)
set(GSS_VERSION "${_MIT_VERSION}")
else()
set(GSS_VERSION "MIT Unknown")
endif()
endif()
endif()
include(FindPackageHandleStandardArgs)
set(_GSS_REQUIRED_VARS GSS_LIBRARIES GSS_FLAVOUR)
find_package_handle_standard_args(GSS
REQUIRED_VARS
${_GSS_REQUIRED_VARS}
VERSION_VAR
GSS_VERSION
FAIL_MESSAGE
"Could NOT find GSS, try to set the path to GSS root folder in the system variable GSS_ROOT_DIR"
)
mark_as_advanced(GSS_INCLUDE_DIR GSS_LIBRARIES)