From 39f85b34dcdd4de0899b5c9b8e1de47cf8ed63f5 Mon Sep 17 00:00:00 2001
From: Guilherme Amadio <amadio@cern.ch>
Date: Thu, 7 Feb 2019 14:49:16 +0100
Subject: [PATCH] cmake/modules: sync FindODBC.cmake with version from CMake
 itself

This module was introduced with CMake 3.12, so we cannot remove it yet.
---
 cmake/modules/FindODBC.cmake | 254 ++++++++++++++++++++++++++++++-----
 1 file changed, 219 insertions(+), 35 deletions(-)

diff --git a/cmake/modules/FindODBC.cmake b/cmake/modules/FindODBC.cmake
index dd176d8f856..c8ca477cca8 100644
--- a/cmake/modules/FindODBC.cmake
+++ b/cmake/modules/FindODBC.cmake
@@ -1,43 +1,227 @@
-# Find the ODBC driver manager includes and library.
-#
-# ODBC is an open standard for connecting to different databases in a
-# semi-vendor-independent fashion.  First you install the ODBC driver
-# manager.  Then you need a driver for each separate database you want
-# to connect to (unless a generic one works).  VTK includes neither
-# the driver manager nor the vendor-specific drivers: you have to find
-# those yourself.
-#
-# This module defines
-# ODBC_INCLUDE_DIR where to find sql.h
-# ODBC_LIBRARIES, the libraries to link against to use ODBC
-# ODBC_FOUND.  If false, you cannot build anything that requires MySQL.
-# also defined, but not for general use is
-# ODBC_LIBRARY, where to find the ODBC driver manager library.
-
-#---For the windows platform ODBC is located automatically
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindODBC
+--------
+
+Find an Open Database Connectivity (ODBC) include directory and library.
+
+On Windows, when building with Visual Studio, this module assumes the ODBC
+library is provided by the available Windows SDK.
+
+On Unix, this module allows to search for ODBC library provided by
+unixODBC or iODBC implementations of ODBC API.
+This module reads hint about location of the config program:
+
+.. variable:: ODBC_CONFIG
+
+  Location of odbc_config or iodbc-config program
+
+Otherwise, this module tries to find the config program,
+first from unixODBC, then from iODBC.
+If no config program found, this module searches for ODBC header
+and library in list of known locations.
+
+Imported targets
+^^^^^^^^^^^^^^^^
+
+This module defines the following :prop_tgt:`IMPORTED` targets:
+
+.. variable:: ODBC::ODBC
+
+  Imported target for using the ODBC library, if found.
+
+Result variables
+^^^^^^^^^^^^^^^^
+
+.. variable:: ODBC_FOUND
+
+  Set to true if ODBC library found, otherwise false or undefined.
+
+.. variable:: ODBC_INCLUDE_DIRS
+
+  Paths to include directories listed in one variable for use by ODBC client.
+  May be empty on Windows, where the include directory corresponding to the
+  expected Windows SDK is already available in the compilation environment.
+
+.. variable:: ODBC_LIBRARIES
+
+  Paths to libraries to linked against to use ODBC.
+  May just a library name on Windows, where the library directory corresponding
+  to the expected Windows SDK is already available in the compilation environment.
+
+.. variable:: ODBC_CONFIG
+
+  Path to unixODBC or iODBC config program, if found or specified.
+
+Cache variables
+^^^^^^^^^^^^^^^
+
+For users who wish to edit and control the module behavior, this module
+reads hints about search locations from the following variables:
+
+.. variable:: ODBC_INCLUDE_DIR
+
+  Path to ODBC include directory with ``sql.h`` header.
+
+.. variable:: ODBC_LIBRARY
+
+  Path to ODBC library to be linked.
+
+These variables should not be used directly by project code.
+
+Limitations
+^^^^^^^^^^^
+
+On Windows, this module does not search for iODBC.
+On Unix, there is no way to prefer unixODBC over iODBC, or vice versa,
+other than providing the config program location using the ``ODBC_CONFIG``.
+This module does not allow to search for a specific ODBC driver.
+
+#]=======================================================================]
+
+# Define lists used internally
+set(_odbc_include_paths)
+set(_odbc_lib_paths)
+set(_odbc_lib_names)
+set(_odbc_required_libs_names)
+
+### Try Windows Kits ##########################################################
 if(WIN32)
-  find_path(ODBC_INCLUDE_DIR NAMES sql.h sqlext.h)
-  if(NOT ODBC_INCLUDE_DIR)
-    set(ODBC_INCLUDE_DIR "")
-  endif()
+  # List names of ODBC libraries on Windows
   set(ODBC_LIBRARY odbc32.lib)
-else()
-  find_path(ODBC_INCLUDE_DIR sqlext.h
-    PATH_SUFFIXES odbc iodbc 
-    HINTS $ENV{ODBC_DIR}/include ${ODBC_DIR}/include 
-    DOC "Specify the directory containing sql.h."
-  )
+  set(_odbc_lib_names odbc32;)
+
+  # 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()
+
+### Try unixODBC or iODBC config program ######################################
+if (UNIX)
+  find_program(ODBC_CONFIG
+    NAMES odbc_config iodbc-config
+    DOC "Path to unixODBC or iODBC config program")
+  mark_as_advanced(ODBC_CONFIG)
+endif()
+
+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()
+
+### Try unixODBC or iODBC in include/lib filesystems ##########################
+if (UNIX AND NOT ODBC_CONFIG)
+  # List names of both ODBC libraries, unixODBC and iODBC
+  set(_odbc_lib_names odbc;iodbc;unixodbc;)
+endif()
+
+### Find include directories ##################################################
+find_path(ODBC_INCLUDE_DIR
+  NAMES sql.h
+  PATHS ${_odbc_include_paths})
 
-  find_library( ODBC_LIBRARY NAMES iodbc odbc odbc32
-    PATHS_SUFFIXES odbc
-    HINTS  $ENV{ODBC_DIR}/lib ${ODBC_DIR}/lib 
-    DOC "Specify the ODBC driver manager library here."
-  )
+if(NOT ODBC_INCLUDE_DIR AND WIN32)
+  set(ODBC_INCLUDE_DIR "")
 endif()
 
-set(ODBC_LIBRARIES ${ODBC_LIBRARY})
+### Find libraries ############################################################
+if(NOT ODBC_LIBRARY)
+  find_library(ODBC_LIBRARY
+    NAMES ${_odbc_lib_names}
+    PATHS ${_odbc_lib_paths}
+    PATH_SUFFIXES odbc)
+
+  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()
+
+# Unset internal lists as no longer used
+unset(_odbc_include_paths)
+unset(_odbc_lib_paths)
+unset(_odbc_lib_names)
+unset(_odbc_required_libs_names)
+
+### Set result variables ######################################################
+set(_odbc_required_vars ODBC_LIBRARY)
+if(NOT WIN32)
+  list(APPEND _odbc_required_vars ODBC_INCLUDE_DIR)
+endif()
 
 include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(ODBC DEFAULT_MSG ODBC_INCLUDE_DIR ODBC_LIBRARY)
-mark_as_advanced(ODBC_INCLUDE_DIR ODBC_LIBRARY)
+find_package_handle_standard_args(ODBC DEFAULT_MSG ${_odbc_required_vars})
+
+unset(_odbc_required_vars)
+
+mark_as_advanced(ODBC_LIBRARY ODBC_INCLUDE_DIR)
+
+set(ODBC_INCLUDE_DIRS ${ODBC_INCLUDE_DIR})
+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()
+  endif()
+endif()
 
+unset(_odbc_required_libs_paths)
-- 
GitLab