From 357db10bd1e154a5f5092b55395a236bb40dc5d6 Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Fri, 11 May 2018 22:31:01 +0200 Subject: FindODBC: Add module to search for ODBC library Add tests for FindODBC module. --- Help/manual/cmake-modules.7.rst | 1 + Help/module/FindODBC.rst | 1 + Help/release/dev/FindODBC-module.rst | 5 + Modules/FindODBC.cmake | 227 +++++++++++++++++++++++++++++++++++ Tests/CMakeLists.txt | 4 + Tests/FindODBC/CMakeLists.txt | 10 ++ Tests/FindODBC/Test/CMakeLists.txt | 14 +++ Tests/FindODBC/Test/main.c | 12 ++ 8 files changed, 274 insertions(+) create mode 100644 Help/module/FindODBC.rst create mode 100644 Help/release/dev/FindODBC-module.rst create mode 100644 Modules/FindODBC.cmake create mode 100644 Tests/FindODBC/CMakeLists.txt create mode 100644 Tests/FindODBC/Test/CMakeLists.txt create mode 100644 Tests/FindODBC/Test/main.c diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index 3bfaa54..8ef4d7d 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -156,6 +156,7 @@ All Modules /module/FindMPEG2 /module/FindMPEG /module/FindMPI + /module/FindODBC /module/FindOpenACC /module/FindOpenAL /module/FindOpenCL diff --git a/Help/module/FindODBC.rst b/Help/module/FindODBC.rst new file mode 100644 index 0000000..8558334 --- /dev/null +++ b/Help/module/FindODBC.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/FindODBC.cmake diff --git a/Help/release/dev/FindODBC-module.rst b/Help/release/dev/FindODBC-module.rst new file mode 100644 index 0000000..f270e8e --- /dev/null +++ b/Help/release/dev/FindODBC-module.rst @@ -0,0 +1,5 @@ +FindODBC-module +--------------- + +* A :module:`FindODBC` module was added to find an Open Database Connectivity + (ODBC) library. diff --git a/Modules/FindODBC.cmake b/Modules/FindODBC.cmake new file mode 100644 index 0000000..c8ca477 --- /dev/null +++ b/Modules/FindODBC.cmake @@ -0,0 +1,227 @@ +# 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) + # List names of ODBC libraries on Windows + set(ODBC_LIBRARY odbc32.lib) + 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}) + +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 + 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_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) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index fe8f2cc..0e94388 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1438,6 +1438,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release add_subdirectory(FindLTTngUST) endif() + if(CMake_TEST_FindODBC) + add_subdirectory(FindODBC) + endif() + if(CMake_TEST_FindOpenCL) add_subdirectory(FindOpenCL) endif() diff --git a/Tests/FindODBC/CMakeLists.txt b/Tests/FindODBC/CMakeLists.txt new file mode 100644 index 0000000..6a81090 --- /dev/null +++ b/Tests/FindODBC/CMakeLists.txt @@ -0,0 +1,10 @@ +add_test(NAME FindODBC.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindODBC/Test" + "${CMake_BINARY_DIR}/Tests/FindODBC/Test" + ${build_generator_args} + --build-project TestFindODBC + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) diff --git a/Tests/FindODBC/Test/CMakeLists.txt b/Tests/FindODBC/Test/CMakeLists.txt new file mode 100644 index 0000000..a20c0f7 --- /dev/null +++ b/Tests/FindODBC/Test/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.1) +project(TestFindODBC C) +include(CTest) + +find_package(ODBC) + +add_executable(test_odbc_tgt main.c) +target_link_libraries(test_odbc_tgt ODBC::ODBC) +add_test(NAME test_odbc_tgt COMMAND test_odbc_tgt) + +add_executable(test_odbc_var main.c) +target_include_directories(test_odbc_var PRIVATE ${ODBC_INCLUDE_DIRS}) +target_link_libraries(test_odbc_var PRIVATE ${ODBC_LIBRARIES}) +add_test(NAME test_odbc_var COMMAND test_odbc_var) diff --git a/Tests/FindODBC/Test/main.c b/Tests/FindODBC/Test/main.c new file mode 100644 index 0000000..917167b --- /dev/null +++ b/Tests/FindODBC/Test/main.c @@ -0,0 +1,12 @@ +#ifdef WIN32 +#include +#endif +#include + +int main() +{ + SQLHENV env; + SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); + SQLFreeHandle(SQL_HANDLE_ENV, env); + return 0; +} -- cgit v0.12