| # Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| # file LICENSE.rst or https://cmake.org/licensing for details. | |
| #[=======================================================================[.rst: | |
| FindODBC | |
| -------- | |
| .. versionadded:: 3.12 | |
| Finds the Open Database Connectivity (ODBC) library, which implements a | |
| standard API for accessing database systems: | |
| .. code-block:: cmake | |
| find_package(ODBC [...]) | |
| ODBC enables applications to communicate with different database management | |
| systems (DBMS) using a common set of functions. Communication with a specific | |
| database is handled through ODBC drivers, which the library loads at runtime. | |
| On Windows, when building with Visual Studio, this module assumes the ODBC | |
| library is provided by the available Windows SDK. | |
| On Unix-like systems, this module searches for ODBC library provided by unixODBC | |
| or iODBC implementations of ODBC API. By default, this module looks for the | |
| ODBC config program to determine the ODBC library and include directory, first | |
| from unixODBC, then from iODBC. If no config program is found, it searches for | |
| ODBC header and library in standard locations. | |
| Imported Targets | |
| ^^^^^^^^^^^^^^^^ | |
| This module provides the following :ref:`Imported Targets`: | |
| ``ODBC::ODBC`` | |
| Target encapsulating the ODBC usage requirements, available if ODBC is found. | |
| Result Variables | |
| ^^^^^^^^^^^^^^^^ | |
| This module defines the following variables: | |
| ``ODBC_FOUND`` | |
| Boolean indicating whether ODBC was found. | |
| ``ODBC_INCLUDE_DIRS`` | |
| Include directories containing headers needed to use ODBC. | |
| ``ODBC_LIBRARIES`` | |
| Libraries needed to link against to use ODBC. | |
| Cache Variables | |
| ^^^^^^^^^^^^^^^ | |
| The following cache variables may also be set: | |
| ``ODBC_INCLUDE_DIR`` | |
| The path to the directory containing ``sql.h`` and other ODBC headers. May be | |
| empty on Windows, where the include directory corresponding to the expected | |
| Windows SDK is already available in the compilation environment. | |
| ``ODBC_LIBRARY`` | |
| The path to the ODBC library or a library name. On Windows, this may be only | |
| a library name, because the library directory corresponding to the expected | |
| Windows SDK is already available in the compilation environment. | |
| ``ODBC_CONFIG`` | |
| The path to the ODBC config program if found or specified. For example, | |
| ``odbc_config`` for unixODBC, or ``iodbc-config`` for iODBC. | |
| Limitations | |
| ^^^^^^^^^^^ | |
| * On Windows, this module does not search for iODBC. | |
| * On Unix-like systems, there is no built-in mechanism to prefer unixODBC over | |
| iODBC, or vice versa. To bypass this limitation, explicitly set the | |
| ``ODBC_CONFIG`` variable to the path of the desired ODBC config program. | |
| * This module does not support searching for or selecting a specific ODBC | |
| driver. | |
| Examples | |
| ^^^^^^^^ | |
| Example: Finding and Using ODBC | |
| """"""""""""""""""""""""""""""" | |
| Finding ODBC and linking it to a project target: | |
| .. code-block:: cmake | |
| :caption: ``CMakeLists.txt`` | |
| find_package(ODBC) | |
| target_link_libraries(project_target PRIVATE ODBC::ODBC) | |
| Example: Finding a Custom ODBC Installation | |
| """"""""""""""""""""""""""""""""""""""""""" | |
| The following examples are for Unix-like systems and demonstrate how to set hint | |
| and cache variables during the CMake configuration phase to help this module | |
| find a custom ODBC implementation (e.g. one not supported by default). | |
| To specify the installation prefix using :variable:`CMAKE_PREFIX_PATH`: | |
| .. code-block:: console | |
| $ cmake -D CMAKE_PREFIX_PATH=/path/to/odbc-installation -B build | |
| Or using the dedicated :variable:`ODBC_ROOT <<PackageName>_ROOT>` variable: | |
| .. code-block:: console | |
| $ cmake -D ODBC_ROOT=/path/to/odbc-installation -B build | |
| To manually specify the ODBC config program, if available, so that the ODBC | |
| installation can be automatically determined based on the config tool: | |
| .. code-block:: console | |
| $ cmake -D ODBC_CONFIG=/path/to/odbc/bin/odbc-config -B build | |
| To manually specify the ODBC library and include directory: | |
| .. code-block:: console | |
| $ cmake \ | |
| -D ODBC_LIBRARY=/path/to/odbc/lib/libodbc.so \ | |
| -D ODBC_INCLUDE_DIR=/path/to/odbc/include \ | |
| -B build | |
| #]=======================================================================] | |
| # Define internal variables | |
| set(_odbc_include_paths) | |
| set(_odbc_lib_paths) | |
| set(_odbc_lib_names) | |
| set(_odbc_required_libs_names) | |
| ### 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;) | |
| # 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 | |
| RESULT_VARIABLE _odbc_config_cflags_result) | |
| execute_process(COMMAND ${ODBC_CONFIG} --libs | |
| OUTPUT_VARIABLE _libs OUTPUT_STRIP_TRAILING_WHITESPACE | |
| RESULT_VARIABLE _odbc_config_libs_result) | |
| # 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}) | |
| if(NOT ODBC_INCLUDE_DIR AND WIN32) | |
| set(ODBC_INCLUDE_DIR "") | |
| endif() | |
| ### 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 | |
| NO_CACHE | |
| NAMES ${_lib} | |
| PATHS ${_odbc_lib_paths} # system paths or collected from ODBC_CONFIG | |
| PATH_SUFFIXES odbc) | |
| if(_lib_path) | |
| list(APPEND _odbc_required_libs_paths ${_lib_path}) | |
| endif() | |
| unset(_lib_path) | |
| endforeach() | |
| endif() | |
| # Unset internal variables 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_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) |