1# Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2# file Copyright.txt or https://cmake.org/licensing for details. 3 4#[=======================================================================[.rst: 5FindODBC 6-------- 7 8.. versionadded:: 3.12 9 10Find an Open Database Connectivity (ODBC) include directory and library. 11 12On Windows, when building with Visual Studio, this module assumes the ODBC 13library is provided by the available Windows SDK. 14 15On Unix, this module allows to search for ODBC library provided by 16unixODBC or iODBC implementations of ODBC API. 17This module reads hint about location of the config program: 18 19.. variable:: ODBC_CONFIG 20 21 Location of odbc_config or iodbc-config program 22 23Otherwise, this module tries to find the config program, 24first from unixODBC, then from iODBC. 25If no config program found, this module searches for ODBC header 26and library in list of known locations. 27 28Imported targets 29^^^^^^^^^^^^^^^^ 30 31This module defines the following :prop_tgt:`IMPORTED` targets: 32 33.. variable:: ODBC::ODBC 34 35 Imported target for using the ODBC library, if found. 36 37Result variables 38^^^^^^^^^^^^^^^^ 39 40.. variable:: ODBC_FOUND 41 42 Set to true if ODBC library found, otherwise false or undefined. 43 44.. variable:: ODBC_INCLUDE_DIRS 45 46 Paths to include directories listed in one variable for use by ODBC client. 47 May be empty on Windows, where the include directory corresponding to the 48 expected Windows SDK is already available in the compilation environment. 49 50.. variable:: ODBC_LIBRARIES 51 52 Paths to libraries to linked against to use ODBC. 53 May just a library name on Windows, where the library directory corresponding 54 to the expected Windows SDK is already available in the compilation environment. 55 56.. variable:: ODBC_CONFIG 57 58 Path to unixODBC or iODBC config program, if found or specified. 59 60Cache variables 61^^^^^^^^^^^^^^^ 62 63For users who wish to edit and control the module behavior, this module 64reads hints about search locations from the following variables: 65 66.. variable:: ODBC_INCLUDE_DIR 67 68 Path to ODBC include directory with ``sql.h`` header. 69 70.. variable:: ODBC_LIBRARY 71 72 Path to ODBC library to be linked. 73 74These variables should not be used directly by project code. 75 76Limitations 77^^^^^^^^^^^ 78 79On Windows, this module does not search for iODBC. 80On Unix, there is no way to prefer unixODBC over iODBC, or vice versa, 81other than providing the config program location using the ``ODBC_CONFIG``. 82This module does not allow to search for a specific ODBC driver. 83 84#]=======================================================================] 85 86# Define lists used internally 87set(_odbc_include_paths) 88set(_odbc_lib_paths) 89set(_odbc_lib_names) 90set(_odbc_required_libs_names) 91 92### Try Windows Kits ########################################################## 93if(WIN32) 94 # List names of ODBC libraries on Windows 95 if(NOT MINGW) 96 set(ODBC_LIBRARY odbc32.lib) 97 else() 98 set(ODBC_LIBRARY libodbc32.a) 99 endif() 100 set(_odbc_lib_names odbc32;) 101 102 # List additional libraries required to use ODBC library 103 if(MSVC OR CMAKE_CXX_COMPILER_ID MATCHES "Intel") 104 set(_odbc_required_libs_names odbccp32;ws2_32) 105 elseif(MINGW) 106 set(_odbc_required_libs_names odbccp32) 107 endif() 108endif() 109 110### Try unixODBC or iODBC config program ###################################### 111if (UNIX) 112 find_program(ODBC_CONFIG 113 NAMES odbc_config iodbc-config 114 DOC "Path to unixODBC or iODBC config program") 115 mark_as_advanced(ODBC_CONFIG) 116endif() 117 118if (UNIX AND ODBC_CONFIG) 119 # unixODBC and iODBC accept unified command line options 120 execute_process(COMMAND ${ODBC_CONFIG} --cflags 121 OUTPUT_VARIABLE _cflags OUTPUT_STRIP_TRAILING_WHITESPACE) 122 execute_process(COMMAND ${ODBC_CONFIG} --libs 123 OUTPUT_VARIABLE _libs OUTPUT_STRIP_TRAILING_WHITESPACE) 124 125 # Collect paths of include directories from CFLAGS 126 separate_arguments(_cflags NATIVE_COMMAND "${_cflags}") 127 foreach(arg IN LISTS _cflags) 128 if("${arg}" MATCHES "^-I(.*)$") 129 list(APPEND _odbc_include_paths "${CMAKE_MATCH_1}") 130 endif() 131 endforeach() 132 unset(_cflags) 133 134 # Collect paths of library names and directories from LIBS 135 separate_arguments(_libs NATIVE_COMMAND "${_libs}") 136 foreach(arg IN LISTS _libs) 137 if("${arg}" MATCHES "^-L(.*)$") 138 list(APPEND _odbc_lib_paths "${CMAKE_MATCH_1}") 139 elseif("${arg}" MATCHES "^-l(.*)$") 140 set(_lib_name ${CMAKE_MATCH_1}) 141 string(REGEX MATCH "odbc" _is_odbc ${_lib_name}) 142 if(_is_odbc) 143 list(APPEND _odbc_lib_names ${_lib_name}) 144 else() 145 list(APPEND _odbc_required_libs_names ${_lib_name}) 146 endif() 147 unset(_lib_name) 148 endif() 149 endforeach() 150 unset(_libs) 151endif() 152 153### Try unixODBC or iODBC in include/lib filesystems ########################## 154if (UNIX AND NOT ODBC_CONFIG) 155 # List names of both ODBC libraries, unixODBC and iODBC 156 set(_odbc_lib_names odbc;iodbc;unixodbc;) 157endif() 158 159### Find include directories ################################################## 160find_path(ODBC_INCLUDE_DIR 161 NAMES sql.h 162 PATHS ${_odbc_include_paths}) 163 164if(NOT ODBC_INCLUDE_DIR AND WIN32) 165 set(ODBC_INCLUDE_DIR "") 166endif() 167 168### Find libraries ############################################################ 169if(NOT ODBC_LIBRARY) 170 find_library(ODBC_LIBRARY 171 NAMES ${_odbc_lib_names} 172 PATHS ${_odbc_lib_paths} 173 PATH_SUFFIXES odbc) 174 175 foreach(_lib IN LISTS _odbc_required_libs_names) 176 find_library(_lib_path 177 NAMES ${_lib} 178 PATHS ${_odbc_lib_paths} # system parths or collected from ODBC_CONFIG 179 PATH_SUFFIXES odbc) 180 if(_lib_path) 181 list(APPEND _odbc_required_libs_paths ${_lib_path}) 182 endif() 183 unset(_lib_path CACHE) 184 endforeach() 185endif() 186 187# Unset internal lists as no longer used 188unset(_odbc_include_paths) 189unset(_odbc_lib_paths) 190unset(_odbc_lib_names) 191unset(_odbc_required_libs_names) 192 193### Set result variables ###################################################### 194set(_odbc_required_vars ODBC_LIBRARY) 195if(NOT WIN32) 196 list(APPEND _odbc_required_vars ODBC_INCLUDE_DIR) 197endif() 198 199include(FindPackageHandleStandardArgs) 200find_package_handle_standard_args(ODBC DEFAULT_MSG ${_odbc_required_vars}) 201 202unset(_odbc_required_vars) 203 204mark_as_advanced(ODBC_LIBRARY ODBC_INCLUDE_DIR) 205 206set(ODBC_INCLUDE_DIRS ${ODBC_INCLUDE_DIR}) 207list(APPEND ODBC_LIBRARIES ${ODBC_LIBRARY}) 208list(APPEND ODBC_LIBRARIES ${_odbc_required_libs_paths}) 209 210### Import targets ############################################################ 211if(ODBC_FOUND) 212 if(NOT TARGET ODBC::ODBC) 213 if(IS_ABSOLUTE "${ODBC_LIBRARY}") 214 add_library(ODBC::ODBC UNKNOWN IMPORTED) 215 set_target_properties(ODBC::ODBC PROPERTIES 216 IMPORTED_LINK_INTERFACE_LANGUAGES "C" 217 IMPORTED_LOCATION "${ODBC_LIBRARY}") 218 else() 219 add_library(ODBC::ODBC INTERFACE IMPORTED) 220 set_target_properties(ODBC::ODBC PROPERTIES 221 IMPORTED_LIBNAME "${ODBC_LIBRARY}") 222 endif() 223 set_target_properties(ODBC::ODBC PROPERTIES 224 INTERFACE_INCLUDE_DIRECTORIES "${ODBC_INCLUDE_DIR}") 225 226 if(_odbc_required_libs_paths) 227 set_property(TARGET ODBC::ODBC APPEND PROPERTY 228 INTERFACE_LINK_LIBRARIES "${_odbc_required_libs_paths}") 229 endif() 230 endif() 231endif() 232 233unset(_odbc_required_libs_paths) 234