diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5878d2919..21e7d626a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -80,7 +80,6 @@ jobs: libfreetype-dev \ libldap2-dev \ unixodbc-dev \ - libodbc2 \ freetds-dev \ libsnmp-dev \ snmp \ diff --git a/cmake/cmake/modules/FindACL.cmake b/cmake/cmake/modules/FindACL.cmake index 142612132..121ba47b7 100644 --- a/cmake/cmake/modules/FindACL.cmake +++ b/cmake/cmake/modules/FindACL.cmake @@ -143,7 +143,9 @@ else() # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) - pkg_check_modules(PC_ACL QUIET libacl) + if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_ACL QUIET libacl) + endif() find_path( ACL_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindApache.cmake b/cmake/cmake/modules/FindApache.cmake index 37db8ed85..33de1e874 100644 --- a/cmake/cmake/modules/FindApache.cmake +++ b/cmake/cmake/modules/FindApache.cmake @@ -193,7 +193,9 @@ endif() # Find the apr library (Apache portable runtime). # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_Apache_APR QUIET apr-1) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Apache_APR QUIET apr-1) +endif() find_path( Apache_APR_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindAppArmor.cmake b/cmake/cmake/modules/FindAppArmor.cmake index f1c5d8a90..dd931ac57 100644 --- a/cmake/cmake/modules/FindAppArmor.cmake +++ b/cmake/cmake/modules/FindAppArmor.cmake @@ -37,7 +37,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_AppArmor QUIET libapparmor) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_AppArmor QUIET libapparmor) +endif() find_path( AppArmor_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindArgon2.cmake b/cmake/cmake/modules/FindArgon2.cmake index 9b644fa57..7500df096 100644 --- a/cmake/cmake/modules/FindArgon2.cmake +++ b/cmake/cmake/modules/FindArgon2.cmake @@ -36,7 +36,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_Argon2 QUIET libargon2) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Argon2 QUIET libargon2) +endif() find_path( Argon2_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindCapstone.cmake b/cmake/cmake/modules/FindCapstone.cmake index f17a710f7..347378eb0 100644 --- a/cmake/cmake/modules/FindCapstone.cmake +++ b/cmake/cmake/modules/FindCapstone.cmake @@ -36,7 +36,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_Capstone QUIET capstone) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Capstone QUIET capstone) +endif() find_path( Capstone_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindCdb.cmake b/cmake/cmake/modules/FindCdb.cmake index 99900e2cb..be6457dde 100644 --- a/cmake/cmake/modules/FindCdb.cmake +++ b/cmake/cmake/modules/FindCdb.cmake @@ -37,7 +37,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_Cdb QUIET libcdb) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Cdb QUIET libcdb) +endif() find_path( Cdb_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindCrypt.cmake b/cmake/cmake/modules/FindCrypt.cmake index d7644ee9f..82bb0b8e1 100644 --- a/cmake/cmake/modules/FindCrypt.cmake +++ b/cmake/cmake/modules/FindCrypt.cmake @@ -85,7 +85,9 @@ else() # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) - pkg_search_module(PC_Crypt QUIET libcrypt libxcrypt) + if(PKG_CONFIG_FOUND) + pkg_search_module(PC_Crypt QUIET libcrypt libxcrypt) + endif() find_path( Crypt_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindEditline.cmake b/cmake/cmake/modules/FindEditline.cmake index 84417dbce..ca2bf1e67 100644 --- a/cmake/cmake/modules/FindEditline.cmake +++ b/cmake/cmake/modules/FindEditline.cmake @@ -37,7 +37,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_Editline QUIET libedit) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Editline QUIET libedit) +endif() find_path( Editline_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindEnchant.cmake b/cmake/cmake/modules/FindEnchant.cmake index 7cfe794b7..6ccf008fb 100644 --- a/cmake/cmake/modules/FindEnchant.cmake +++ b/cmake/cmake/modules/FindEnchant.cmake @@ -43,7 +43,9 @@ endif() # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_Enchant QUIET ${_enchant_name}) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Enchant QUIET ${_enchant_name}) +endif() find_path( Enchant_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindFFI.cmake b/cmake/cmake/modules/FindFFI.cmake index 4428396fd..8ac16dcb5 100644 --- a/cmake/cmake/modules/FindFFI.cmake +++ b/cmake/cmake/modules/FindFFI.cmake @@ -36,7 +36,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_FFI QUIET libffi) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_FFI QUIET libffi) +endif() find_path( FFI_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindGD.cmake b/cmake/cmake/modules/FindGD.cmake index 161b222d3..0850633af 100644 --- a/cmake/cmake/modules/FindGD.cmake +++ b/cmake/cmake/modules/FindGD.cmake @@ -36,7 +36,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_GD QUIET gdlib) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_GD QUIET gdlib) +endif() find_path( GD_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindGMP.cmake b/cmake/cmake/modules/FindGMP.cmake index f75da22df..6bdb04794 100644 --- a/cmake/cmake/modules/FindGMP.cmake +++ b/cmake/cmake/modules/FindGMP.cmake @@ -36,7 +36,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_GMP QUIET gmp) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_GMP QUIET gmp) +endif() find_path( GMP_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindICU.cmake b/cmake/cmake/modules/FindICU.cmake index d0245d058..475d3a5dc 100644 --- a/cmake/cmake/modules/FindICU.cmake +++ b/cmake/cmake/modules/FindICU.cmake @@ -20,17 +20,19 @@ set_package_properties( ) # If available, use pkgconf and append paths to the internal icu_roots variable. -foreach(component ${ICU_FIND_COMPONENTS}) - find_package(PkgConfig QUIET) - string(TOUPPER ${component} component_upper) - pkg_check_modules(PC_ICU_${component_upper} QUIET icu-${component}) - - list(APPEND icu_roots ${PC_ICU_${component_upper}_INCLUDE_DIRS}) - list(APPEND icu_roots ${PC_ICU_${component_upper}_LIBRARY_DIRS}) -endforeach() - -if(icu_roots) - list(REMOVE_DUPLICATES icu_roots) +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + foreach(component ${ICU_FIND_COMPONENTS}) + string(TOUPPER ${component} component_upper) + pkg_check_modules(PC_ICU_${component_upper} QUIET icu-${component}) + + list(APPEND icu_roots ${PC_ICU_${component_upper}_INCLUDE_DIRS}) + list(APPEND icu_roots ${PC_ICU_${component_upper}_LIBRARY_DIRS}) + endforeach() + + if(icu_roots) + list(REMOVE_DUPLICATES icu_roots) + endif() endif() # Find package with upstream CMake module; override CMAKE_MODULE_PATH to prevent diff --git a/cmake/cmake/modules/FindKerberos.cmake b/cmake/cmake/modules/FindKerberos.cmake index d631b50d1..7cf7dd402 100644 --- a/cmake/cmake/modules/FindKerberos.cmake +++ b/cmake/cmake/modules/FindKerberos.cmake @@ -46,7 +46,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_Kerberos QUIET krb5) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Kerberos QUIET krb5) +endif() find_path( Kerberos_INCLUDE_DIR @@ -115,7 +117,9 @@ block(PROPAGATE Kerberos_VERSION) endblock() # Find Kerberos GSSAPI component. -pkg_check_modules(PC_Kerberos_GSSAPI QUIET krb5-gssapi) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Kerberos_GSSAPI QUIET krb5-gssapi) +endif() find_path( Kerberos_GSSAPI_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindLDAP.cmake b/cmake/cmake/modules/FindLDAP.cmake index 26182b140..7c5b32866 100644 --- a/cmake/cmake/modules/FindLDAP.cmake +++ b/cmake/cmake/modules/FindLDAP.cmake @@ -44,7 +44,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_LDAP QUIET ldap) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_LDAP QUIET ldap) +endif() find_path( LDAP_INCLUDE_DIR @@ -65,7 +67,9 @@ find_library( ) if(LDAP_LIBRARY) - pkg_check_modules(PC_LDAP_LBER QUIET lber) + if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_LDAP_LBER QUIET lber) + endif() find_library( LDAP_LBER_LIBRARY diff --git a/cmake/cmake/modules/FindLMDB.cmake b/cmake/cmake/modules/FindLMDB.cmake index fe80ca39e..4bc2e8057 100644 --- a/cmake/cmake/modules/FindLMDB.cmake +++ b/cmake/cmake/modules/FindLMDB.cmake @@ -37,7 +37,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_LMDB QUIET lmdb) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_LMDB QUIET lmdb) +endif() find_path( LMDB_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindMySQL.cmake b/cmake/cmake/modules/FindMySQL.cmake index d57f06269..57885a943 100644 --- a/cmake/cmake/modules/FindMySQL.cmake +++ b/cmake/cmake/modules/FindMySQL.cmake @@ -55,6 +55,7 @@ find_program( NAMES mysql_config DOC "The mysql_config command-line tool for getting MySQL installation info" ) +mark_as_advanced(MySQL_CONFIG_EXECUTABLE) # Find the Socket component. if("Socket" IN_LIST MySQL_FIND_COMPONENTS) @@ -114,7 +115,9 @@ if("Lib" IN_LIST MySQL_FIND_COMPONENTS) else() # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) - pkg_check_modules(PC_MySQL QUIET mysqlclient) + if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_MySQL QUIET mysqlclient) + endif() endif() find_path( diff --git a/cmake/cmake/modules/FindNetSnmp.cmake b/cmake/cmake/modules/FindNetSnmp.cmake index b76b8ccdc..4a4616029 100644 --- a/cmake/cmake/modules/FindNetSnmp.cmake +++ b/cmake/cmake/modules/FindNetSnmp.cmake @@ -38,7 +38,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_NetSnmp QUIET netsnmp) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_NetSnmp QUIET netsnmp) +endif() find_program( NetSnmp_EXECUTABLE diff --git a/cmake/cmake/modules/FindODBC.cmake b/cmake/cmake/modules/FindODBC.cmake index 20dabe23e..f5b99d496 100644 --- a/cmake/cmake/modules/FindODBC.cmake +++ b/cmake/cmake/modules/FindODBC.cmake @@ -1,73 +1,199 @@ #[=============================================================================[ Find the ODBC library. -Module defines the following `IMPORTED` target(s): +This module is based on the upstream +[FindODBC](https://cmake.org/cmake/help/latest/module/FindODBC.html) with some +enhancements and adjustments for the PHP build workflow. -* `ODBC::ODBC` - The package library, if found. +Modifications from upstream: -Result variables: +* Additional result variables: -* `ODBC_FOUND` - Whether the package has been found. -* `ODBC_INCLUDE_DIRS` - Include directories needed to use this package. -* `ODBC_LIBRARIES` - Libraries needed to link to the package library. -* `ODBC_VERSION` - Package version, if found. + * `ODBC_DRIVER` -Cache variables: + Name of the found driver, if any. For example, `unixODBC`, `iODBC`. -* `ODBC_INCLUDE_DIR` - Directory containing package library headers. -* `ODBC_LIBRARY` - The path to the package library. + * `ODBC_VERSION` -Hints: + Version of the found ODBC library if it was retrieved from config utilities. -* The `ODBC_ROOT` variable adds custom search path. -* The `ODBC_TYPE` variable adds ODBC library name to look for. +* Additional cache variables: + + * `ODBC_COMPILE_DEFINITIONS` - a `;`-list of compile definitions. + * `ODBC_COMPILE_OPTIONS` - a `;`-list of compile options. + * `ODBC_LINK_OPTIONS` - a `;`-list of linker options. + +* Additional hints: + + * `ODBC_USE_DRIVER` + + Set to `unixODBC` or `iODBC` to limit searching for specific ODBC driver + instead of any driver. + +* Added pkg-config integration. + +* Fixed limitation where the upstream module can't (yet) select which specific + ODBC driver to use. Except on Windows, where the driver searching is the same + as upstream. + +* Added package meta-data for FeatureSummary. #]=============================================================================] include(FeatureSummary) -include(FindPackageHandleStandardArgs) -set_package_properties( - ODBC - PROPERTIES - URL "https://en.wikipedia.org/wiki/Open_Database_Connectivity" - DESCRIPTION "Open Database Connectivity library" +# Define internal variables +set(_odbc_include_paths) +set(_odbc_lib_paths) +set(_odbc_lib_names) +set(_odbc_required_libs_names) +set(_odbc_config_names) +set(_reason) + +### To manually override build options of the ODBC library #################### +set(ODBC_COMPILE_DEFINITIONS "" CACHE STRING "ODBC library compile definitions") +set(ODBC_COMPILE_OPTIONS "" CACHE STRING "ODBC library compile options") +set(ODBC_LINK_OPTIONS "" CACHE STRING "ODBC library linker flags") +mark_as_advanced( + ODBC_COMPILE_DEFINITIONS + ODBC_COMPILE_OPTIONS + ODBC_LINK_OPTIONS ) -set(_reason "") +### Try Windows Kits ########################################################## +if(WIN32) + # List names of ODBC libraries on Windows + if(NOT MINGW) + set(ODBC_LIBRARY odbc32.lib) + else() + set(ODBC_LIBRARY libodbc32.a) + endif() + set(_odbc_lib_names odbc32;) -# Use pkgconf, if available on the system. -find_package(PkgConfig QUIET) -pkg_check_modules(PC_ODBC QUIET odbc) + # List additional libraries required to use ODBC library + if(MSVC OR CMAKE_CXX_COMPILER_ID MATCHES "Intel") + set(_odbc_required_libs_names odbccp32;ws2_32) + elseif(MINGW) + set(_odbc_required_libs_names odbccp32) + endif() +endif() -find_path( - ODBC_INCLUDE_DIR - NAMES sql.h - PATHS ${PC_ODBC_INCLUDE_DIRS} - DOC "Directory containing ODBC library headers" -) +### Try unixODBC or iODBC config program ###################################### +if(UNIX) + if(ODBC_USE_DRIVER MATCHES "^(unixODBC|unixodbc|UNIXODBC)$") + set(_odbc_config_names odbc_config) + elseif(ODBC_USE_DRIVER MATCHES "^(iODBC|iodbc|IODBC)$") + set(_odbc_config_names iodbc-config) + else() + set(_odbc_config_names odbc_config iodbc-config) + endif() -if(NOT ODBC_INCLUDE_DIR) - string(APPEND _reason "ODBC sql.h not found. ") + find_program(ODBC_CONFIG + NAMES ${_odbc_config_names} + DOC "Path to unixODBC or iODBC config program") + mark_as_advanced(ODBC_CONFIG) endif() -if(NOT ODBC_TYPE) - set(ODBC_TYPE "") +if(UNIX AND ODBC_CONFIG) + # unixODBC and iODBC accept unified command line options + execute_process(COMMAND ${ODBC_CONFIG} --cflags + OUTPUT_VARIABLE _cflags OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${ODBC_CONFIG} --libs + OUTPUT_VARIABLE _libs OUTPUT_STRIP_TRAILING_WHITESPACE) + + # Collect paths of include directories from CFLAGS + separate_arguments(_cflags NATIVE_COMMAND "${_cflags}") + foreach(arg IN LISTS _cflags) + if("${arg}" MATCHES "^-I(.*)$") + list(APPEND _odbc_include_paths "${CMAKE_MATCH_1}") + endif() + endforeach() + unset(_cflags) + + # Collect paths of library names and directories from LIBS + separate_arguments(_libs NATIVE_COMMAND "${_libs}") + foreach(arg IN LISTS _libs) + if("${arg}" MATCHES "^-L(.*)$") + list(APPEND _odbc_lib_paths "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^-l(.*)$") + set(_lib_name ${CMAKE_MATCH_1}) + string(REGEX MATCH "odbc" _is_odbc ${_lib_name}) + if(_is_odbc) + list(APPEND _odbc_lib_names ${_lib_name}) + else() + list(APPEND _odbc_required_libs_names ${_lib_name}) + endif() + unset(_lib_name) + endif() + endforeach() + unset(_libs) endif() -find_library( - ODBC_LIBRARY - NAMES ${ODBC_TYPE} odbc - PATHS ${PC_ODBC_LIBRARY_DIRS} - DOC "The path to the ODBC library" -) +### Try pkg-config ############################################################ +if(NOT ODBC_CONFIG) + find_package(PkgConfig QUIET) + if(PKG_CONFIG_FOUND) + if(ODBC_USE_DRIVER MATCHES "^(unixODBC|unixodbc|UNIXODBC)$") + pkg_check_modules(PC_ODBC QUIET odbc) + elseif(ODBC_USE_DRIVER MATCHES "^(iODBC|iodbc|IODBC)$") + pkg_check_modules(PC_ODBC QUIET libiodbc) + else() + pkg_search_module(PC_ODBC QUIET odbc libiodbc) + endif() + endif() +endif() + +### Try unixODBC or iODBC in include/lib filesystems ########################## +if(UNIX AND NOT ODBC_CONFIG) + if(ODBC_USE_DRIVER MATCHES "^(unixODBC|unixodbc|UNIXODBC)$") + set(_odbc_lib_names odbc;unixodbc;) + elseif(ODBC_USE_DRIVER MATCHES "^(iODBC|iodbc|IODBC)$") + set(_odbc_lib_names iodbc;) + else() + # List names of both ODBC libraries, unixODBC and iODBC + set(_odbc_lib_names odbc;iodbc;unixodbc;) + endif() +endif() + +### Find include directories ################################################## +find_path(ODBC_INCLUDE_DIR + NAMES sql.h + PATHS ${_odbc_include_paths} + HINTS ${PC_ODBC_INCLUDE_DIRS}) + +if(NOT ODBC_INCLUDE_DIR AND WIN32) + set(ODBC_INCLUDE_DIR "") +endif() +### Find libraries ############################################################ if(NOT ODBC_LIBRARY) - string(APPEND _reason "ODBC library not found. ") + find_library(ODBC_LIBRARY + NAMES ${_odbc_lib_names} + PATHS ${_odbc_lib_paths} + PATH_SUFFIXES odbc + HINTS ${PC_ODBC_LIBRARY_DIRS}) + + foreach(_lib IN LISTS _odbc_required_libs_names) + find_library(_lib_path + NAMES ${_lib} + PATHS ${_odbc_lib_paths} # system parths or collected from ODBC_CONFIG + PATH_SUFFIXES odbc) + if(_lib_path) + list(APPEND _odbc_required_libs_paths ${_lib_path}) + endif() + unset(_lib_path CACHE) + endforeach() endif() -# Get version. +# Unset internal lists as no longer used +unset(_odbc_include_paths) +unset(_odbc_lib_paths) +unset(_odbc_lib_names) +unset(_odbc_required_libs_names) +unset(_odbc_config_names) + +### Get version ############################################################### block(PROPAGATE ODBC_VERSION) - # ODBC headers don't provide version. Try pkgconf version, if found. + # ODBC headers don't provide version. Try pkg-confing version, if found. if(PC_ODBC_VERSION) cmake_path( COMPARE @@ -79,36 +205,138 @@ block(PROPAGATE ODBC_VERSION) set(ODBC_VERSION ${PC_ODBC_VERSION}) endif() endif() + + if(NOT ODBC_VERSION AND ODBC_CONFIG) + execute_process( + COMMAND ${ODBC_CONFIG} --version + OUTPUT_VARIABLE _odbc_version + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + if(_odbc_version MATCHES "[0-9]+\.[0-9.]*") + set(ODBC_VERSION ${_odbc_version}) + endif() + endif() endblock() -mark_as_advanced(ODBC_LIBRARY ODBC_INCLUDE_DIR) +### Set result variables ###################################################### +set(_odbc_required_vars ODBC_LIBRARY) +if(NOT WIN32) + list(APPEND _odbc_required_vars ODBC_INCLUDE_DIR) +endif() + +if(NOT ODBC_INCLUDE_DIR) + string(APPEND _reason "ODBC sql.h not found. ") +endif() + +if(NOT ODBC_LIBRARY) + string(APPEND _reason "ODBC library not found. ") +endif() +include(FindPackageHandleStandardArgs) find_package_handle_standard_args( ODBC - REQUIRED_VARS - ODBC_LIBRARY - ODBC_INCLUDE_DIR + REQUIRED_VARS ${_odbc_required_vars} VERSION_VAR ODBC_VERSION REASON_FAILURE_MESSAGE "${_reason}" ) +unset(_odbc_required_vars) unset(_reason) -if(NOT ODBC_FOUND) - return() -endif() +mark_as_advanced(ODBC_LIBRARY ODBC_INCLUDE_DIR) set(ODBC_INCLUDE_DIRS ${ODBC_INCLUDE_DIR}) -set(ODBC_LIBRARIES ${ODBC_LIBRARY}) - -if(NOT TARGET ODBC::ODBC) - add_library(ODBC::ODBC UNKNOWN IMPORTED) - - set_target_properties( - ODBC::ODBC - PROPERTIES - IMPORTED_LOCATION "${ODBC_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${ODBC_INCLUDE_DIR}" - INTERFACE_COMPILE_OPTIONS "${PC_ODBC_CFLAGS_OTHER}" - ) +list(APPEND ODBC_LIBRARIES ${ODBC_LIBRARY}) +list(APPEND ODBC_LIBRARIES ${_odbc_required_libs_paths}) + +### Import targets ############################################################ +if(ODBC_FOUND) + if(NOT TARGET ODBC::ODBC) + if(IS_ABSOLUTE "${ODBC_LIBRARY}") + add_library(ODBC::ODBC UNKNOWN IMPORTED) + set_target_properties(ODBC::ODBC PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${ODBC_LIBRARY}") + else() + add_library(ODBC::ODBC INTERFACE IMPORTED) + set_target_properties(ODBC::ODBC PROPERTIES + IMPORTED_LIBNAME "${ODBC_LIBRARY}") + endif() + set_target_properties(ODBC::ODBC PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${ODBC_INCLUDE_DIR}") + + if(_odbc_required_libs_paths) + set_property(TARGET ODBC::ODBC APPEND PROPERTY + INTERFACE_LINK_LIBRARIES "${_odbc_required_libs_paths}") + endif() + + if(ODBC_COMPILE_DEFINITIONS) + target_compile_definitions(ODBC::ODBC INTERFACE ${ODBC_COMPILE_DEFINITIONS}) + endif() + + if(ODBC_COMPILE_OPTIONS) + target_compile_options(ODBC::ODBC INTERFACE ${ODBC_COMPILE_OPTIONS}) + endif() + + if(ODBC_LINK_OPTIONS) + target_link_options(ODBC::ODBC INTERFACE ${ODBC_LINK_OPTIONS}) + endif() + endif() + + if(NOT ODBC_DRIVER) + if(ODBC_CONFIG) + execute_process( + COMMAND ${ODBC_CONFIG} + OUTPUT_VARIABLE _output + ERROR_VARIABLE _output + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + if(_output MATCHES "^iODBC") + set(ODBC_DRIVER "iODBC") + elseif(_output MATCHES "^Usage: odbc_config") + set(ODBC_DRIVER "unixODBC") + endif() + unset(_output) + elseif(PC_ODBC_FOUND) + if(PC_ODBC_MODULE_NAME STREQUAL "libiodbc") + set(ODBC_DRIVER "iODBC") + elseif(PC_ODBC_MODULE_NAME STREQUAL "odbc") + set(ODBC_DRIVER "unixODBC") + endif() + elseif(WIN32) + set(ODBC_DRIVER "Windows") + endif() + + if(NOT ODBC_DRIVER) + if(ODBC_LIBRARY MATCHES "libiodbc") + set(ODBC_DRIVER "iODBC") + elseif(ODBC_LIBRARY MATCHES "odbc") + set(ODBC_DRIVER "unixODBC") + endif() + endif() + endif() +endif() + +unset(_odbc_required_libs_paths) + +### Set package metadata ###################################################### +if(ODBC_DRIVER STREQUAL "unixODBC" OR ODBC_USE_DRIVER STREQUAL "unixODBC") + set(_odbc_url "https://www.unixodbc.org/") + set(_odbc_description "Open Database Connectivity library for *nix systems") +elseif(ODBC_DRIVER STREQUAL "iODBC" OR ODBC_USE_DRIVER STREQUAL "iODBC") + set(_odbc_url "https://www.iodbc.org") + set(_odbc_description "Independent Open Database Connectivity library") +else() + set(_odbc_url "https://en.wikipedia.org/wiki/Open_Database_Connectivity") + set(_odbc_description "Open Database Connectivity library") endif() +set_package_properties( + ODBC + PROPERTIES + URL "${_odbc_url}" + DESCRIPTION "${_odbc_description}" +) +unset(_odbc_url) +unset(_odbc_description) diff --git a/cmake/cmake/modules/FindOniguruma.cmake b/cmake/cmake/modules/FindOniguruma.cmake index dd9ac8097..f7116ee42 100644 --- a/cmake/cmake/modules/FindOniguruma.cmake +++ b/cmake/cmake/modules/FindOniguruma.cmake @@ -36,7 +36,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_Oniguruma QUIET oniguruma) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Oniguruma QUIET oniguruma) +endif() find_path( Oniguruma_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindPCRE.cmake b/cmake/cmake/modules/FindPCRE.cmake index 0f01a8c65..62b2c0030 100644 --- a/cmake/cmake/modules/FindPCRE.cmake +++ b/cmake/cmake/modules/FindPCRE.cmake @@ -36,7 +36,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_PCRE QUIET libpcre2-8) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_PCRE QUIET libpcre2-8) +endif() find_path( PCRE_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindQDBM.cmake b/cmake/cmake/modules/FindQDBM.cmake index ff68f1700..219a0e914 100644 --- a/cmake/cmake/modules/FindQDBM.cmake +++ b/cmake/cmake/modules/FindQDBM.cmake @@ -37,7 +37,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_QDBM QUIET qdbm) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_QDBM QUIET qdbm) +endif() find_path( QDBM_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindReadline.cmake b/cmake/cmake/modules/FindReadline.cmake index 9b65d1c61..c91bdcf8c 100644 --- a/cmake/cmake/modules/FindReadline.cmake +++ b/cmake/cmake/modules/FindReadline.cmake @@ -37,7 +37,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_Readline QUIET readline) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Readline QUIET readline) +endif() find_path( Readline_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindSASL.cmake b/cmake/cmake/modules/FindSASL.cmake index 19dd52908..c4e008cda 100644 --- a/cmake/cmake/modules/FindSASL.cmake +++ b/cmake/cmake/modules/FindSASL.cmake @@ -36,7 +36,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_SASL QUIET libsasl2) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_SASL QUIET libsasl2) +endif() find_path( SASL_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindSELinux.cmake b/cmake/cmake/modules/FindSELinux.cmake index 7ae15605d..d61bfdc58 100644 --- a/cmake/cmake/modules/FindSELinux.cmake +++ b/cmake/cmake/modules/FindSELinux.cmake @@ -37,7 +37,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_Selinux QUIET libselinux) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Selinux QUIET libselinux) +endif() find_path( SELinux_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindSodium.cmake b/cmake/cmake/modules/FindSodium.cmake index aee73b2de..a3759e474 100644 --- a/cmake/cmake/modules/FindSodium.cmake +++ b/cmake/cmake/modules/FindSodium.cmake @@ -36,7 +36,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_Sodium QUIET libsodium) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Sodium QUIET libsodium) +endif() find_path( Sodium_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindSystemd.cmake b/cmake/cmake/modules/FindSystemd.cmake index 57bfd82c5..09e0d4316 100644 --- a/cmake/cmake/modules/FindSystemd.cmake +++ b/cmake/cmake/modules/FindSystemd.cmake @@ -37,7 +37,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_Systemd QUIET libsystemd) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Systemd QUIET libsystemd) +endif() find_path( Systemd_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindTidy.cmake b/cmake/cmake/modules/FindTidy.cmake index 2a8395192..931028ea2 100644 --- a/cmake/cmake/modules/FindTidy.cmake +++ b/cmake/cmake/modules/FindTidy.cmake @@ -43,7 +43,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_Tidy QUIET tidy) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Tidy QUIET tidy) +endif() find_path( Tidy_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindTokyoCabinet.cmake b/cmake/cmake/modules/FindTokyoCabinet.cmake index 5c73ecd94..134a69d97 100644 --- a/cmake/cmake/modules/FindTokyoCabinet.cmake +++ b/cmake/cmake/modules/FindTokyoCabinet.cmake @@ -37,7 +37,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_TokyoCabinet QUIET tokyocabinet) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_TokyoCabinet QUIET tokyocabinet) +endif() find_path( TokyoCabinet_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindValgrind.cmake b/cmake/cmake/modules/FindValgrind.cmake index f3c5b66d6..1b6a7a548 100644 --- a/cmake/cmake/modules/FindValgrind.cmake +++ b/cmake/cmake/modules/FindValgrind.cmake @@ -35,7 +35,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_Valgrind QUIET valgrind) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_Valgrind QUIET valgrind) +endif() find_path( Valgrind_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindWebP.cmake b/cmake/cmake/modules/FindWebP.cmake index 127caa187..b7487c6ae 100644 --- a/cmake/cmake/modules/FindWebP.cmake +++ b/cmake/cmake/modules/FindWebP.cmake @@ -36,7 +36,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_WebP QUIET libwebp) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_WebP QUIET libwebp) +endif() find_path( WebP_INCLUDE_DIR diff --git a/cmake/cmake/modules/FindXPM.cmake b/cmake/cmake/modules/FindXPM.cmake index cf6342e99..421364fc4 100644 --- a/cmake/cmake/modules/FindXPM.cmake +++ b/cmake/cmake/modules/FindXPM.cmake @@ -36,7 +36,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_XPM QUIET xpm) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_XPM QUIET xpm) +endif() find_path( XPM_INCLUDE_DIR diff --git a/cmake/cmake/modules/Findlibavif.cmake b/cmake/cmake/modules/Findlibavif.cmake index 2dcdd1132..98705a3b3 100644 --- a/cmake/cmake/modules/Findlibavif.cmake +++ b/cmake/cmake/modules/Findlibavif.cmake @@ -38,7 +38,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_libavif QUIET libavif) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_libavif QUIET libavif) +endif() find_path( libavif_INCLUDE_DIR diff --git a/cmake/cmake/modules/Findlibzip.cmake b/cmake/cmake/modules/Findlibzip.cmake index d4095b36f..2693d4b98 100644 --- a/cmake/cmake/modules/Findlibzip.cmake +++ b/cmake/cmake/modules/Findlibzip.cmake @@ -45,7 +45,9 @@ set(_reason "") # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_libzip QUIET libzip) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_libzip QUIET libzip) +endif() find_path( libzip_INCLUDE_DIR diff --git a/cmake/cmake/modules/PHP/Set.cmake b/cmake/cmake/modules/PHP/Set.cmake index 2913e7633..793cea5b6 100644 --- a/cmake/cmake/modules/PHP/Set.cmake +++ b/cmake/cmake/modules/PHP/Set.cmake @@ -1,57 +1,45 @@ #[=============================================================================[ Set a CACHE variable that depends on a set of conditions. -> [!WARNING] -> TODO: This module is still under review to determine its usefulness. -> Dependent variables may seem convenient for the application but may create -> difficulties for anyone troubleshooting why a configuration isn't applied, -> even though a configuration value has been set. In the end, build system -> configuration isn't aiming to provide a HTML-form-alike functionality. - -At the time of writing, there are 3 main ways in CMake to create non-internal -cache variables that can be also customized from the outside using the `-D` -command-line option, through CMake presets, or similar: +At the time of writing, there are three main ways in CMake to create +non-internal cache variables that can also be customized externally via the `-D` +command-line option, CMake presets, or similar: + * `option()` * `set( CACHE )` * `cmake_dependent_option()` -Ideally, these are the recommended ways to set configuration variables. However, -there are many cases where a `CACHE` variable of a type other than `BOOL` -depends on certain conditions. Additionally, an edge-case issue with +Ideally, these are the recommended methods to set configuration variables. +However, there are cases where a `CACHE` variable of a type other than `BOOL` +depends on specific conditions. Additionally, an edge-case issue with `cmake_dependent_option()` is that it sets a local variable if the conditions -are not met. Local variables in such edge cases can be difficult to work with -when using `add_subdirectory()`. In the parent scope, instead of the local +are not met. Local variables in such cases can be difficult to work with +when using `add_subdirectory()`. In the parent scope, instead of a local variable with a forced value, the cached variable is still defined as `INTERNAL`, which can lead to bugs in the build process. -This module exposes the following function: +## The `php_set()` function ```cmake php_set( TYPE - [CHOICES ...] [IF VALUE [ELSE_VALUE ]] | [VALUE ] DOC ... - [WARNING ] ) ``` -It sets a CACHE `` of `` to a ``. +This function sets a cache `` of `` to a ``. * `TYPE` can be `BOOL`, `FILEPATH`, `PATH`, or `STRING`. -* `CHOICES` is an optional list of items when `STRING` type is used to create - a list of supported options to pick in the GUI. Under the hood, it sets the - `STRINGS` CACHE variable property. - -* `VALUE` is the default variable value. There are two ways to set default +* `VALUE` is the default variable value. There are two ways to set the default value. * When using the `IF ` argument, it sets the variable to `` if `` is met. Otherwise it sets the `` to `ELSE_VALUE` - `` and hides it in the GUI, if `ELSE_VALUE` is given. Under the - hood `ELSE_VALUE` will set `INTERNAL` cache variable if `` is not + `` and hides it in the GUI if `ELSE_VALUE` is provided. Internally, + `ELSE_VALUE` will set an `INTERNAL` cache variable if `` is not met. If `ELSE_VALUE` is not provided, the `INTERNAL` cache variable is not set (it is undefined). @@ -59,19 +47,135 @@ It sets a CACHE `` of `` to a ``. `cmake_dependent_option()`. This supports both full condition syntax and semicolon-separated list of conditions. - * When using only `VALUE` signature, it sets the cache variable to ``. - It is the same as writing: + * When using only `VALUE` signature, it sets the cache variable to ``, + which is equivalent to writing: ```cmake set( CACHE ) ``` -* `DOC` is a short variable help text visible in the GUIs. Multiple strings are - joined together. +* `DOC` is a short help text for the variable, visible in GUIs. Multiple strings + are joined together. + + For example: + + ```cmake + php_set( + VAR + TYPE STRING + IF [[CMAKE_SYSTEM_NAME STREQUAL "Linux"]] + VALUE "some value" + DOC + "This help text " + "is joined " + "together." + ) + ``` + +## The `CHOICES` signature + +The `CHOICES` signature provides a list of options to choose from: + +```cmake +php_set( + + [TYPE STRING] + CHOICES ... + [CHOICES_OPTIONAL] + [CHOICES_CASE_SENSITIVE] + [IF [VALUE ] [ELSE_VALUE ]] | [VALUE ] + DOC ... +) +``` + +* `CHOICES` is a list of items to choose from in the GUI. Internally, it sets + the `STRINGS` cache variable property. The default `TYPE` is `STRING`, which + is optional. + + When using `CHOICES`, the `VALUE` keyword is optional. The default variable + value is set to the first item in the `CHOICES` list. + + For example: + + ```cmake + include(PHP/Set) + php_set( + VAR + CHOICES auto on off + DOC "Variable with default value set to the first list item" + ) + message(STATUS "VAR=${VAR}") + ``` + + Output: + + ``` + VAR=auto + ``` + +* When `CHOICES_OPTIONAL` is given, the variable value will not be required to + match one of the list items. By default, when using `CHOICES`, the variable + value must match one of the list items; otherwise, a fatal error is thrown. + + For example: + + ```cmake + php_set( + VAR + CHOICES auto on off + CHOICES_OPTIONAL + DOC + "Variable with optional predefined choices where its value can be also " + "changed to anything else." + ) + message(STATUS "VAR=${VAR}") + ``` + + ```sh + cmake -S -B -D VAR=overridden + ``` + + Output: + + ``` + VAR=overridden + ``` + +* When `CHOICES_CASE_SENSITIVE` is given, the variable value will need to match + the case of item defined in the `CHOICES` list. By default, choices are + case-insensitive. + + For example: + + ```cmake + php_set( + VAR + CHOICES auto unixODBC iODBC + DOC "Variable with a case-insensitive list of choices" + ) + message(STATUS "VAR=${VAR}") + ``` + + ```sh + cmake -S -B -D VAR=unixodbc + ``` + + Will output `VAR=unixODBC` and not `VAR=unixodbc`. + + With `CHOICES_CASE_SENSITIVE`: -* `WARNING` is optional text that is emitted when setting a variable from the - command line or CMake presets but its condition is not met. Otherwise, a - default warning is emitted. + ```cmake + php_set( + VAR + CHOICES auto unixODBC iODBC + CHOICES_CASE_SENSITIVE + DOC "Variable with a case-sensitive list of choices" + ) + message(STATUS "VAR=${VAR}") + ``` + + A fatal error will be thrown, if `VAR` is set to a case-sensitive value + (`unixodbc`) that does not match any item in the `CHOICES` list. #]=============================================================================] include_guard(GLOBAL) @@ -80,10 +184,10 @@ function(php_set) cmake_parse_arguments( PARSE_ARGV 1 - parsed # prefix - "" # options + parsed # prefix + "CHOICES_OPTIONAL;CHOICES_CASE_SENSITIVE" # options "TYPE;IF;VALUE;ELSE_VALUE" # one-value keywords - "CHOICES;DOC;WARNING" # multi-value keywords + "CHOICES;DOC" # multi-value keywords ) # The cmake_parse_arguments() before 3.31 didn't define one-value keywords @@ -106,6 +210,11 @@ function(php_set) endforeach() endif() + # Set default TYPE if not set when using CHOICES argument. + if(DEFINED parsed_CHOICES AND NOT DEFINED parsed_TYPE) + set(parsed_TYPE "STRING") + endif() + _php_set_validate_arguments("${ARGN}") set(doc "") @@ -114,7 +223,7 @@ function(php_set) endforeach() set(condition TRUE) - if(parsed_IF) + if(DEFINED parsed_IF) # Make condition look nice in the possible output strings. string(STRIP "${parsed_IF}" parsed_IF) string(REGEX REPLACE "[ \t]*[\r\n]+[ \t\r\n]*" "\n" parsed_IF "${parsed_IF}") @@ -133,10 +242,22 @@ function(php_set) set(bufferDoc "Internal storage for ${varName} variable") if(NOT DEFINED ${bufferVarName} AND DEFINED ${varName}) - # Initial configuration phase with variable set by the user. + # Initial configuration phase with variable set externally. set(${bufferVarName} "${${varName}}" CACHE INTERNAL "${bufferDoc}") elseif(NOT DEFINED ${bufferVarName}) - # Initial configuration phase without variable set by the user. + # Initial configuration phase without variable set externally. + + # When using CHOICES and VALUE is not set, set the variable value to the + # first item of the CHOICES list. + if( + parsed_TYPE STREQUAL "STRING" + AND DEFINED parsed_CHOICES + AND NOT DEFINED parsed_VALUE + ) + list(GET parsed_CHOICES 0 value) + set(parsed_VALUE "${value}") + unset(value) + endif() set(${bufferVarName} "${parsed_VALUE}" CACHE INTERNAL "${bufferDoc}") elseif( DEFINED ${bufferVarName} @@ -153,13 +274,21 @@ function(php_set) if(condition) set(${varName} "${${bufferVarName}}" CACHE ${parsed_TYPE} "${doc}" FORCE) + if(parsed_TYPE STREQUAL "STRING" AND parsed_CHOICES) - set_property(CACHE ${varName} PROPERTY STRINGS ${parsed_CHOICES}) + set_property(CACHE ${varName} PROPERTY STRINGS "${parsed_CHOICES}") + if(NOT parsed_CHOICES_CASE_SENSITIVE) + _php_set_adjust_case_sensitivity_value(${varName}) + endif() + if(NOT parsed_CHOICES_OPTIONAL) + _php_set_validate_choices(${varName} ${parsed_CHOICES_CASE_SENSITIVE}) + endif() endif() + unset(${bufferVarName} CACHE) unset(${bufferVarName}_OVERRIDDEN CACHE) else() - _php_set_validate_input() + _php_set_validate_input(${varName}) if(DEFINED parsed_ELSE_VALUE) set(${varName} "${parsed_ELSE_VALUE}" CACHE INTERNAL "${doc}" FORCE) @@ -181,7 +310,10 @@ function(_php_set_validate_arguments arguments) message(FATAL_ERROR "Bad arguments: ${parsed_UNPARSED_ARGUMENTS}") endif() - if(NOT DEFINED parsed_VALUE) + if( + NOT DEFINED parsed_VALUE + AND (NOT DEFINED parsed_CHOICES OR NOT parsed_TYPE STREQUAL "STRING") + ) message(FATAL_ERROR "Missing VALUE argument") endif() @@ -191,6 +323,10 @@ function(_php_set_validate_arguments arguments) message(FATAL_ERROR "Unknown TYPE argument: ${parsed_TYPE}") endif() + if(DEFINED parsed_CHOICES AND NOT parsed_TYPE STREQUAL "STRING") + message(FATAL_ERROR "CHOICES argument can be only used with TYPE STRING") + endif() + list(FIND arguments ELSE_VALUE elseValueIndex) if(NOT DEFINED parsed_IF AND NOT elseValueIndex EQUAL -1) message(FATAL_ERROR "Redundant ELSE_VALUE argument without IF condition") @@ -207,41 +343,76 @@ function(_php_set_validate_arguments arguments) endif() endfunction() -# Output warning when setting conditional variable and condition is not met. -function(_php_set_validate_input) - get_property(helpString CACHE ${varName} PROPERTY HELPSTRING) +# Validate variable and output warning when a conditional variable is set +# externally and the condition is not met. This is for diagnostic purpose for +# user to be aware that some configuration value was not taken into account. +function(_php_set_validate_input var) + get_property(helpString CACHE ${var} PROPERTY HELPSTRING) if(NOT helpString STREQUAL "No help, variable specified on the command line.") return() endif() - if(NOT parsed_WARNING) - set(parsed_WARNING "Variable ${varName}") - if(DEFINED parsed_ELSE_VALUE) - string( - APPEND - parsed_WARNING - " has been overridden (${varName}=${parsed_ELSE_VALUE})" - ) - else() - string( - APPEND - parsed_WARNING - " has been overridden to an undefined state" - ) - endif() - string( - APPEND - parsed_WARNING - " as it depends on the condition:\n" - "${parsed_IF}\n" - ) + if(${var} STREQUAL "${parsed_ELSE_VALUE}") + return() + endif() + + set(warning "Variable ${var}") + if(DEFINED parsed_ELSE_VALUE) + string(APPEND warning " has been overridden (${var}=${parsed_ELSE_VALUE})") + else() + string(APPEND warning " has been undefined") endif() - set(warning "") - foreach(string ${parsed_WARNING}) - string(APPEND warning "${string}") + string( + APPEND + warning + " as it depends on the condition:\n" + "${parsed_IF}\n" + "The ${var} configuration value can be then probably removed from the " + "current build command as it won't be utilized." + ) + + message(WARNING "${warning}") +endfunction() + +# Adjust the variable value according to the case sensitivity as defined in the +# CHOICES list item. +function(_php_set_adjust_case_sensitivity_value var) + get_property(value CACHE ${var} PROPERTY VALUE) + get_property(choices CACHE ${var} PROPERTY STRINGS) + + string(TOLOWER "${value}" valueLower) + list(TRANSFORM choices TOLOWER OUTPUT_VARIABLE choicesLower) + + set(index 0) + foreach(item IN LISTS choicesLower) + if(valueLower STREQUAL "${item}") + list(GET choices ${index} itemOriginal) + if(NOT value STREQUAL "${itemOriginal}") + set_property(CACHE ${var} PROPERTY VALUE ${itemOriginal}) + break() + endif() + endif() + math(EXPR index "${index}+1") endforeach() +endfunction() + +# Validate variable value to match with one of the items from the CHOICES list. +function(_php_set_validate_choices var caseSensitive) + get_property(value CACHE ${var} PROPERTY VALUE) + get_property(choices CACHE ${var} PROPERTY STRINGS) - if(NOT ${varName} STREQUAL "${parsed_ELSE_VALUE}") - message(WARNING "${warning}") + if(NOT caseSensitive) + string(TOLOWER "${value}" value) + list(TRANSFORM choices TOLOWER) + endif() + + if(NOT value IN_LIST choices) + list(JOIN choices ", " choices) + + message( + FATAL_ERROR + "Unknown value: ${var}=${value}\n" + "Please select one of: ${choices}." + ) endif() endfunction() diff --git a/cmake/ext/odbc/CMakeLists.txt b/cmake/ext/odbc/CMakeLists.txt index c7cd460d6..93b6beb72 100644 --- a/cmake/ext/odbc/CMakeLists.txt +++ b/cmake/ext/odbc/CMakeLists.txt @@ -1,5 +1,3 @@ -# TODO: Add support for the rest of the ODBC types. - project( PhpExtensionOdbc LANGUAGES C @@ -10,24 +8,24 @@ include(FeatureSummary) include(PHP/Set) option(EXT_ODBC "Enable the odbc extension" OFF) - add_feature_info( "ext/odbc" EXT_ODBC - "Unified ODBC databases support (Open Database Connectivity)" + "Unified Open Database Connectivity (ODBC) databases support" ) cmake_dependent_option( EXT_ODBC_SHARED "Build the odbc extension as a shared library" OFF - "EXT_ODBC;NOT BUILD_SHARED_LIBS" + [[EXT_ODBC AND NOT BUILD_SHARED_LIBS]] OFF ) -set( - odbcTypes - # TODO: "Adabas D" vs "Adabas". +php_set( + EXT_ODBC_TYPE + CHOICES + "auto" "adabas" "dbmaker" "empress-bcs" @@ -38,41 +36,65 @@ set( "sapdb" "solid" "unixODBC" - "generic" -) - -php_set( - EXT_ODBC_TYPE - TYPE STRING - CHOICES ${odbcTypes} + "custom" IF EXT_ODBC - VALUE unixODBC - DOC "The ODBC implementation type" + DOC "The ODBC implementation type (library driving the ODBC)" ) +mark_as_advanced(EXT_ODBC_TYPE) -block() - if(EXT_ODBC_TYPE AND NOT EXT_ODBC_TYPE IN_LIST odbcTypes) - list(JOIN odbcTypes ", " odbcTypesString) +# Validate ODBC type for odbc and pdo_odbc extensions. Ideally, the same ODBC +# driver library should be used for both extensions. +if(EXT_ODBC AND EXT_PDO_ODBC AND NOT EXT_ODBC_TYPE STREQUAL EXT_PDO_ODBC_TYPE) + message( + FATAL_ERROR + "Different ODBC types detected for 'odbc' and 'pdo_odbc' PHP " + "extensions:\n" + "EXT_ODBC_TYPE=${EXT_ODBC_TYPE}\n" + "EXT_PDO_ODBC_TYPE=${EXT_PDO_ODBC_TYPE}\n" + "To prevent library symbol collisions when building both 'odbc' and " + "'pdo_odbc' please link with the same ODBC library. Or disable one of " + "the extensions by setting EXT_ODBC or EXT_PDO_ODBC to 'OFF'." + ) +endif() - message( - FATAL_ERROR - "Unknown ODBC type EXT_ODBC_TYPE=${EXT_ODBC_TYPE}. Please select one of " - "these: ${odbcTypesString}." - ) - endif() -endblock() +# Some ODBC drivers require setting ODBC_LIBRARY manually to find package. +if( + EXT_ODBC + AND NOT EXT_ODBC_TYPE MATCHES "auto|unixODBC|iODBC" + AND NOT ODBC_LIBRARY +) + message( + FATAL_ERROR + "When using EXT_ODBC_TYPE=${EXT_ODBC_TYPE}, please set also " + "ODBC_LIBRARY and optionally ODBC_INCLUDE_DIR to locate the ODBC " + "installation." + ) +endif() -set( +php_set( EXT_ODBC_VERSION - "0x0350" - CACHE STRING - "Force support for the passed ODBC version. A hex number is \ -expected, default 0x0350. Set it to empty value to prevent an explicit ODBCVER \ -to be defined." + TYPE STRING + IF EXT_ODBC + VALUE "0x0350" + DOC + "Hex number to force support for the ODBC specification version. Default: " + "0x0350. Set to special value 0 (zero) or empty to not define explicit " + "ODBCVER in the configuration header." ) mark_as_advanced(EXT_ODBC_VERSION) +# Validate hexadecimal version. +if(EXT_ODBC_VERSION AND NOT EXT_ODBC_VERSION MATCHES "^0x[0-9A-Fa-f]+$") + message( + FATAL_ERROR + "The value 'EXT_ODBC_VERSION=${EXT_ODBC_VERSION}' is NOT valid hexadecimal " + "number." + ) +endif() -set(ODBCVER "${EXT_ODBC_VERSION}") +unset(PHP_ODBC_CFLAGS CACHE) +unset(PHP_ODBC_LFLAGS CACHE) +unset(PHP_ODBC_LIBS CACHE) +unset(PHP_ODBC_TYPE CACHE) if(NOT EXT_ODBC) return() @@ -94,6 +116,15 @@ target_sources( target_compile_definitions(php_odbc PRIVATE ZEND_ENABLE_STATIC_TSRMLS_CACHE=1) +# TODO: Can this be fixed better? +get_target_property(extension_type php_odbc TYPE) +if(NOT extension_type MATCHES "^(MODULE|SHARED)_LIBRARY$") + target_link_libraries(php_odbc PRIVATE PHP::main) +endif() + +if(NOT EXT_ODBC_TYPE STREQUAL "auto") + set(ODBC_USE_DRIVER "${EXT_ODBC_TYPE}") +endif() find_package(ODBC) set_package_properties( ODBC @@ -102,6 +133,10 @@ set_package_properties( PURPOSE "Necessary to enable the odbc extension." ) +if(ODBC_DRIVER AND EXT_ODBC_TYPE STREQUAL "auto") + set(EXT_ODBC_TYPE "${ODBC_DRIVER}") +endif() + target_link_libraries(php_odbc PRIVATE ODBC::ODBC) if(EXT_ODBC_TYPE STREQUAL "adabas") @@ -119,10 +154,14 @@ elseif(EXT_ODBC_TYPE STREQUAL "iODBC") elseif(EXT_ODBC_TYPE STREQUAL "sapdb") set(HAVE_SAPDB 1) elseif(EXT_ODBC_TYPE STREQUAL "solid") - # TODO: Set based on the Solid version: - #set(HAVE_SOLID_35 1) - #set(HAVE_SOLID_30 1) - set(HAVE_SOLID 1) + # Set based on the Solid version: + if(ODBC_LIBRARY MATCHES "23\.(a|so)$") + set(HAVE_SOLID 1) + elseif(ODBC_LIBRARY MATCHES "30\.(a|so)$") + set(HAVE_SOLID_30 1) + else() + set(HAVE_SOLID_35 1) + endif() # Additional configuration for using obsolete header on obsolete # systems. @@ -133,21 +172,34 @@ elseif(EXT_ODBC_TYPE STREQUAL "solid") endif() elseif(EXT_ODBC_TYPE STREQUAL "unixODBC") set(HAVE_UNIXODBC 1) -elseif(EXT_ODBC_TYPE STREQUAL "generic") +elseif(EXT_ODBC_TYPE STREQUAL "custom") + set(EXT_ODBC_TYPE custom-odbc) set(HAVE_CODBC 1) endif() +if(NOT EXT_ODBC_TYPE MATCHES "^(dbmaker|solid)$") + set(HAVE_SQLDATASOURCES 1) +endif() + ################################################################################ # Set ODBC_* variables for main/build-defs.h file. ################################################################################ if(TARGET ODBC::ODBC) - block() - get_target_property(cflags ODBC::ODBC INTERFACE_COMPILE_OPTIONS) - list(JOIN cflags " " cflags) - set(ODBC_CFLAGS "${cflags}" CACHE INTERNAL "ODBC CFLAGS") + block(PROPAGATE PHP_ODBC_BUILD_DEFINITIONS_CODE) + get_target_property(definitions ODBC::ODBC INTERFACE_COMPILE_DEFINITIONS) + get_target_property(options ODBC::ODBC INTERFACE_COMPILE_OPTIONS) + set(cflags "") + if(definitions) + list(APPEND cflags ${definitions}) + endif() + if(options) + list(APPEND cflags ${options}) + endif() + if(cflags) + list(JOIN cflags " " cflags) + endif() get_target_property(libraries ODBC::ODBC IMPORTED_LOCATION) - foreach(library ${libraries}) cmake_path(GET library PARENT_PATH path) list(APPEND ldflags "-L${path}") @@ -157,20 +209,54 @@ if(TARGET ODBC::ODBC) list(APPEND libs "-l${name}") endforeach() + get_target_property(options ODBC::ODBC INTERFACE_LINK_OPTIONS) + if(options) + list(APPEND ldflags ${options}) + endif() + list(REMOVE_DUPLICATES ldflags) list(REMOVE_DUPLICATES libs) list(JOIN ldflags " " ldflags) list(JOIN libs " " libs) - set(ODBC_LFLAGS "${ldflags}" CACHE INTERNAL "ODBC linker flags") - set(ODBC_LIBS "${libs}" CACHE INTERNAL "ODBC libraries") - set(ODBC_TYPE "${EXT_ODBC_TYPE}" CACHE INTERNAL "ODBC type") + set(PHP_ODBC_CFLAGS "${cflags}" CACHE INTERNAL "ODBC CFLAGS") + set(PHP_ODBC_LFLAGS "${ldflags}" CACHE INTERNAL "ODBC linker flags") + set(PHP_ODBC_LIBS "${libs}" CACHE INTERNAL "ODBC libraries") + set(PHP_ODBC_TYPE "${EXT_ODBC_TYPE}" CACHE INTERNAL "ODBC type") + + if( + NOT CMAKE_SYSTEM_NAME STREQUAL "Windows" + AND NOT PHP_SOURCE_DIR + AND NOT EXISTS ${PHP_SOURCE_DIR}/main/build-defs.h.in + ) + set( + PHP_ODBC_BUILD_DEFINITIONS_CODE + [[ +/* The compile options that PHP odbc extension was built with. */ +#define PHP_ODBC_CFLAGS "@PHP_ODBC_CFLAGS@" + +/* The linker flags that PHP odbc extension was built with. */ +#define PHP_ODBC_LFLAGS "@PHP_ODBC_LFLAGS@" + +/* The libraries linker flags that PHP odbc extension was built with. */ +#define PHP_ODBC_LIBS "@PHP_ODBC_LIBS@" + +/* The ODBC library used in the PHP odbc extension. */ +#define PHP_ODBC_TYPE "@PHP_ODBC_TYPE@"]] + ) + + string( + CONFIGURE + "${PHP_ODBC_BUILD_DEFINITIONS_CODE}" + PHP_ODBC_BUILD_DEFINITIONS_CODE + ) + endif() endblock() endif() -if(NOT EXT_ODBC_TYPE MATCHES "^(dbmaker|solid)$") - set(HAVE_SQLDATASOURCES 1) +if(EXT_ODBC_VERSION) + set(ODBCVER "${EXT_ODBC_VERSION}") endif() set(HAVE_UODBC 1) diff --git a/cmake/ext/odbc/config.cmake.h.in b/cmake/ext/odbc/config.cmake.h.in index d8041e0cf..8e2702ddd 100644 --- a/cmake/ext/odbc/config.cmake.h.in +++ b/cmake/ext/odbc/config.cmake.h.in @@ -51,3 +51,5 @@ /* Define to 1 to be able to use the obsolete header file on some Linux systems. */ #cmakedefine SS_LINUX 1 + +@PHP_ODBC_BUILD_DEFINITIONS_CODE@ diff --git a/cmake/ext/pdo_mysql/CMakeLists.txt b/cmake/ext/pdo_mysql/CMakeLists.txt index 2fb8c340d..275861f62 100644 --- a/cmake/ext/pdo_mysql/CMakeLists.txt +++ b/cmake/ext/pdo_mysql/CMakeLists.txt @@ -30,10 +30,8 @@ cmake_dependent_option( # Driver selection option. php_set( EXT_PDO_MYSQL_DRIVER - TYPE STRING CHOICES "mysqlnd" "mysql" IF EXT_PDO_MYSQL - VALUE "mysqlnd" DOC "Select MySQL driver: mysqlnd (MySQL Native Driver, recommended) or mysql " "(system MySQL)" diff --git a/cmake/ext/pdo_odbc/CMakeLists.txt b/cmake/ext/pdo_odbc/CMakeLists.txt index b4c5efabb..c2e2e0944 100644 --- a/cmake/ext/pdo_odbc/CMakeLists.txt +++ b/cmake/ext/pdo_odbc/CMakeLists.txt @@ -3,107 +3,51 @@ project( LANGUAGES C ) -include(CheckIncludeFile) include(CheckLibraryExists) include(CMakeDependentOption) -include(CMakePushCheckState) include(FeatureSummary) +include(PHP/Set) option(EXT_PDO_ODBC "Enable the pdo_odbc extension" OFF) - add_feature_info( "ext/pdo_odbc" EXT_PDO_ODBC - "Unified ODBC support in PDO (Open Database Connectivity)" + "Unified Open Database Connectivity (ODBC) databases support in PDO" ) cmake_dependent_option( EXT_PDO_ODBC_SHARED "Build the pdo_odbc extension as a shared library" OFF - "EXT_PDO_ODBC;NOT BUILD_SHARED_LIBS" + [[EXT_PDO_ODBC AND NOT BUILD_SHARED_LIBS]] OFF ) -block() - if(EXT_PDO_ODBC) - set(odbc_types - "ibm-db2" - "iODBC" - "unixODBC" - "generic" - ) - - set(EXT_PDO_ODBC_TYPE "unixODBC" CACHE STRING "The ODBC implementation type") - - set_property( - CACHE EXT_PDO_ODBC_TYPE - PROPERTY STRINGS ${odbc_types} - ) - - # Change from INTERNAL type to show variable on consecutive configuration run. - set_property(CACHE EXT_PDO_ODBC_TYPE PROPERTY TYPE STRING) - - if(NOT EXT_PDO_ODBC_TYPE IN_LIST odbc_types) - list(JOIN odbc_types ", " odbc_types_string) - - message( - FATAL_ERROR - "Unknown PDO ODBC type EXT_PDO_ODBC_TYPE=${EXT_PDO_ODBC_TYPE}. Please " - "select one of these: ${odbc_types_string}." - ) - endif() - elseif(DEFINED EXT_PDO_ODBC_TYPE) - # Hide variable. - set_property(CACHE EXT_PDO_ODBC_TYPE PROPERTY TYPE INTERNAL) - endif() -endblock() +php_set( + EXT_PDO_ODBC_TYPE + CHOICES + "auto" + "ibm-db2" + "iODBC" + "unixODBC" + "custom" + IF EXT_PDO_ODBC + DOC "The ODBC implementation type (library driving the ODBC)" +) +mark_as_advanced(EXT_PDO_ODBC_TYPE) -# ODBC library directory. -if(EXT_PDO_ODBC) - set( - EXT_PDO_ODBC_ROOT "" - CACHE PATH "Set the path to ODBC library root directory" +# Some ODBC drivers require setting ODBC_LIBRARY manually to find package. +if( + EXT_PDO_ODBC + AND NOT EXT_PDO_ODBC_TYPE MATCHES "auto|unixODBC|iODBC" + AND NOT ODBC_LIBRARY +) + message( + FATAL_ERROR + "When using EXT_PDO_ODBC_TYPE=${EXT_PDO_ODBC_TYPE}, please set also " + "ODBC_LIBRARY and optionally ODBC_INCLUDE_DIR to find the ODBC " + "installation." ) - mark_as_advanced(EXT_PDO_ODBC_ROOT) - # Change from INTERNAL type to show variable on consecutive configuration run. - set_property(CACHE EXT_PDO_ODBC_ROOT PROPERTY TYPE PATH) -elseif(DEFINED EXT_PDO_ODBC_ROOT) - # Hide variable. - set_property(CACHE EXT_PDO_ODBC_ROOT PROPERTY TYPE INTERNAL) -endif() - -# ODBC library name. -if(EXT_PDO_ODBC) - set(EXT_PDO_ODBC_LIBRARY "" CACHE STRING "Set the ODBC library name") - mark_as_advanced(EXT_PDO_ODBC_LIBRARY) - # Change from INTERNAL type to show variable on consecutive configuration run. - set_property(CACHE EXT_PDO_ODBC_LIBRARY PROPERTY TYPE STRING) -elseif(DEFINED EXT_PDO_ODBC_LIBRARY) - # Hide variable. - set_property(CACHE EXT_PDO_ODBC_LIBRARY PROPERTY TYPE INTERNAL) -endif() - -# ODBC library linker flags. -if(EXT_PDO_ODBC) - set(EXT_PDO_ODBC_LDFLAGS "" CACHE STRING "Set the ODBC library linker flags") - mark_as_advanced(EXT_PDO_ODBC_LDFLAGS) - # Change from INTERNAL type to show variable on consecutive configuration run. - set_property(CACHE EXT_PDO_ODBC_LDFLAGS PROPERTY TYPE STRING) -elseif(DEFINED EXT_PDO_ODBC_LDFLAGS) - # Hide variable. - set_property(CACHE EXT_PDO_ODBC_LDFLAGS PROPERTY TYPE INTERNAL) -endif() - -# ODBC library C flags. -if(EXT_PDO_ODBC) - set(EXT_PDO_ODBC_CFLAGS "" CACHE STRING "Set the ODBC library C flags") - mark_as_advanced(EXT_PDO_ODBC_CFLAGS) - # Change from INTERNAL type to show variable on consecutive configuration run. - set_property(CACHE EXT_PDO_ODBC_CFLAGS PROPERTY TYPE STRING) -elseif(DEFINED EXT_PDO_ODBC_CFLAGS) - # Hide variable. - set_property(CACHE EXT_PDO_ODBC_CFLAGS PROPERTY TYPE INTERNAL) endif() if(NOT EXT_PDO_ODBC) @@ -139,32 +83,9 @@ if(NOT extension_type MATCHES "^(MODULE|SHARED)_LIBRARY$") target_link_libraries(php_pdo_odbc PRIVATE PHP::main) endif() -if(EXT_PDO_ODBC_TYPE STREQUAL "ibm-db2") - # Set some sensible default root directory. - if(NOT EXT_PDO_ODBC_ROOT) - set(ODBC_ROOT "/home/db2inst1/sqllib") - endif() - set(ODBC_TYPE "db2") -elseif(EXT_PDO_ODBC_TYPE STREQUAL "iODBC") - set(ODBC_TYPE "iodbc") -elseif(EXT_PDO_ODBC_TYPE STREQUAL "unixODBC") - set(ODBC_TYPE "odbc") +if(NOT EXT_PDO_ODBC_TYPE STREQUAL "auto") + set(ODBC_USE_DRIVER "${EXT_PDO_ODBC_TYPE}") endif() - -if(EXT_PDO_ODBC_TYPE STREQUAL "generic" AND EXT_PDO_ODBC_LIBRARY) - set(PDO_ODBC_TYPE "${EXT_PDO_ODBC_TYPE}-${EXT_PDO_ODBC_LIBRARY}") -else() - set(PDO_ODBC_TYPE "${EXT_PDO_ODBC_TYPE}") -endif() - -if(EXT_PDO_ODBC_ROOT AND NOT ODBC_ROOT) - set(ODBC_ROOT ${EXT_PDO_ODBC_ROOT}) -endif() - -if(EXT_PDO_ODBC_LIBRARY AND NOT ODBC_TYPE) - set(ODBC_TYPE ${EXT_PDO_ODBC_LIBRARY}) -endif() - find_package(ODBC) set_package_properties( ODBC @@ -172,17 +93,17 @@ set_package_properties( TYPE REQUIRED PURPOSE "Necessary to enable the pdo_odbc extension." ) +if(ODBC_DRIVER AND EXT_PDO_ODBC_TYPE STREQUAL "auto") + set(EXT_PDO_ODBC_TYPE "${ODBC_DRIVER}") +endif() -if(TARGET ODBC::ODBC) - if(EXT_PDO_ODBC_CFLAGS) - target_compile_options(ODBC::ODBC INTERFACE ${EXT_PDO_ODBC_CFLAGS}) - endif() - - if(EXT_PDO_ODBC_LDFLAGS) - target_link_options(ODBC::ODBC INTERFACE ${EXT_PDO_ODBC_LDFLAGS}) - endif() +if(EXT_PDO_ODBC_TYPE STREQUAL "custom") + set(PDO_ODBC_TYPE "generic-${ODBC_LIBRARY}") +else() + set(PDO_ODBC_TYPE "${EXT_PDO_ODBC_TYPE}") +endif() - # Sanity checks. +if(TARGET ODBC::ODBC) block() foreach( header @@ -208,23 +129,27 @@ if(TARGET ODBC::ODBC) string(MAKE_C_IDENTIFIER "HAVE_${header}" const) string(TOUPPER "${const}" const) - cmake_push_check_state(RESET) - set(CMAKE_REQUIRED_LIBRARIES ODBC::ODBC) - check_include_file(${header} ${const}) - cmake_pop_check_state() + message(CHECK_START "Looking for ${header}") + if(EXISTS ${ODBC_INCLUDE_DIR}/${header}) + message(CHECK_PASS "found") + set(${const} 1) + set(${const} 1 PARENT_SCOPE) + else() + message(CHECK_FAIL "not found") + endif() if(${const}) - set(have_headers TRUE) + set(haveSomeHeaders TRUE) endif() endforeach() - if(NOT have_headers) + if(NOT haveSomeHeaders) message(FATAL_ERROR "Cannot find header file(s) for pdo_odbc") endif() endblock() # Check for an ODBC 1.0 function to assert that the libraries work. - check_library_exists("${ODBC_LIBRARY}" SQLBindCol "" _HAVE_SQLBINDCOL) + check_library_exists(ODBC::ODBC SQLBindCol "" _HAVE_SQLBINDCOL) if(NOT _HAVE_SQLBINDCOL) message( @@ -233,17 +158,16 @@ if(TARGET ODBC::ODBC) ) endif() - # Check for an ODBC 3.0 function to assert that they're *good* libraries. - check_library_exists("${ODBC_LIBRARIES}" SQLAllocHandle "" _HAVE_SQLALLOCHANDLE) + # Check for an ODBC 3.0 function to assert that the libraries work. + check_library_exists(ODBC::ODBC SQLAllocHandle "" _HAVE_SQLALLOCHANDLE) if(NOT _HAVE_SQLALLOCHANDLE) message( FATAL_ERROR - "Could not find the ODBC 3.0 function SQLAllocHandle in the ODBC " - "library. Your ODBC library does not appear to be ODBC 3 compatible. You " - "should consider using iODBC or unixODBC instead, and loading your " - "libraries as a driver in that environment. It will emulate the " - "functions required for PDO support." + "The ODBC library does not appear to be ODBC 3 compatible (the ODBC 3.0 " + "function SQLAllocHandle not found. Consider using iODBC or unixODBC " + "instead, and load libraries as a driver in that environment. It will " + "emulate the functions required for PDO support." ) endif() endif() diff --git a/cmake/ext/skeleton/cmake/modules/FindPHP.cmake b/cmake/ext/skeleton/cmake/modules/FindPHP.cmake index 0c6aab33b..69b7dd434 100644 --- a/cmake/ext/skeleton/cmake/modules/FindPHP.cmake +++ b/cmake/ext/skeleton/cmake/modules/FindPHP.cmake @@ -90,7 +90,9 @@ find_program( # Use pkgconf, if available on the system. find_package(PkgConfig QUIET) -pkg_check_modules(PC_PHP QUIET php) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_PHP QUIET php) +endif() # Get PHP include directories. if(PHP_CONFIG_EXECUTABLE) @@ -158,7 +160,7 @@ if(PHP_CONFIG_EXECUTABLE) ERROR_QUIET ) endif() -if(NOT PHP_EXTENSION_DIR) +if(NOT PHP_EXTENSION_DIR AND PKG_CONFIG_FOUND) pkg_get_variable(PHP_EXTENSION_DIR php extensiondir) endif() @@ -166,7 +168,9 @@ endif() # PHP Embed component. ################################################################################ -pkg_check_modules(PC_PHP_EMBED QUIET php-embed) +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_PHP_EMBED QUIET php-embed) +endif() find_library( PHP_EMBED_LIBRARY diff --git a/cmake/main/CMakeLists.txt b/cmake/main/CMakeLists.txt index 8697e85a5..af4baefe7 100644 --- a/cmake/main/CMakeLists.txt +++ b/cmake/main/CMakeLists.txt @@ -392,6 +392,10 @@ function(_php_main_create_files) set(PHP_CONFIG_H_WINDOWS 1) set(file config.w32.h) else() + set(ODBC_CFLAGS "${PHP_ODBC_CFLAGS}") + set(ODBC_LFLAGS "${PHP_ODBC_LFLAGS}") + set(ODBC_LIBS "${PHP_ODBC_LIBS}") + set(ODBC_TYPE "${PHP_ODBC_TYPE}") message(STATUS "Creating main/build-defs.h") file(READ main/build-defs.h.in content) string(CONFIGURE "${content}" content @ONLY) @@ -415,10 +419,10 @@ function(_php_main_create_files) OUTPUT ${PHP_BINARY_DIR}/main/build-defs.h VARIABLES CONFIGURE_COMMAND "cmake" - ODBC_CFLAGS "${ODBC_CFLAGS}" - ODBC_LFLAGS "${ODBC_LFLAGS}" - ODBC_LIBS "${ODBC_LIBS}" - ODBC_TYPE "${ODBC_TYPE}" + ODBC_CFLAGS "${PHP_ODBC_CFLAGS}" + ODBC_LFLAGS "${PHP_ODBC_LFLAGS}" + ODBC_LIBS "${PHP_ODBC_LIBS}" + ODBC_TYPE "${PHP_ODBC_TYPE}" PROG_SENDMAIL "${PROG_SENDMAIL}" EXPANDED_PEAR_INSTALLDIR "${EXPANDED_PEAR_INSTALLDIR}" INCLUDE_PATH "${INCLUDE_PATH}"