Skip to content

find_package(ODBC) cause error on mingw-w64 cross compile

FindODBC.cmake does not work properly on mingw cross env.

When build a project depends on odbc on mingw-w64 environment in linux, a project fails with link error.

how to reproduce

CMakeLists.txt

cmake_minimum_required (VERSION 3.12)
project(odbc_example LANGUAGES C)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_MODULE_PATH  ${CMAKE_CURRENT_LIST_DIR})
find_package(ODBC)

set(CMAKE_CXX_STANDARD 11)

add_library(example SHARED example.c)
target_link_libraries(example PRIVATE ODBC::ODBC)

example.c

include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <odbcinst.h>
#include <winver.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>


static BOOL
InUn(int remove, char *drivername, char *dllname, char *dll2name, char *dsname)
{
	char path[301], driver[300], attr[300], inst[400], inst2[400];
	WORD pathmax = sizeof (path) - 1, pathlen;
	DWORD usecnt, mincnt;

	usecnt = 0;
	SQLInstallDriverEx(driver, NULL, path, pathmax, &pathlen,
			   ODBC_INSTALL_INQUIRY, &usecnt);
}

mingw-x86_64.toolchain.cmake

SET(CMAKE_SYSTEM_NAME Windows)

SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
SET(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)

SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32/)

SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

What happens

This cause an error with CMake 3.12.3

-- The C compiler identification is GNU 4.8.2
-- Check for working C compiler: /usr/bin/x86_64-w64-mingw32-gcc
-- Check for working C compiler: /usr/bin/x86_64-w64-mingw32-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Found ODBC: odbc32.lib  
-- Configuring done
-- Generating done
-- Build files have been written to: /vagrant/tmp/odbc/build
$ make
/opt/cmake-3.12.3-Linux-x86_64/bin/cmake -H/vagrant/tmp/odbc -B/vagrant/tmp/odbc/build --check-build-system CMakeFiles/Makefile.cmake 0
/opt/cmake-3.12.3-Linux-x86_64/bin/cmake -E cmake_progress_start /vagrant/tmp/odbc/build/CMakeFiles /vagrant/tmp/odbc/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory `/vagrant/tmp/odbc/build'
make -f CMakeFiles/example.dir/build.make CMakeFiles/example.dir/depend
make[2]: Entering directory `/vagrant/tmp/odbc/build'
cd /vagrant/tmp/odbc/build && /opt/cmake-3.12.3-Linux-x86_64/bin/cmake -E cmake_depends "Unix Makefiles" /vagrant/tmp/odbc /vagrant/tmp/odbc /vagrant/tmp/odbc/build /vagrant/tmp/odbc/build /vagrant/tmp/odbc/build/CMakeFiles/example.dir/DependInfo.cmake --color=
Scanning dependencies of target example
make[2]: Leaving directory `/vagrant/tmp/odbc/build'
make -f CMakeFiles/example.dir/build.make CMakeFiles/example.dir/build
make[2]: Entering directory `/vagrant/tmp/odbc/build'
[ 50%] Building C object CMakeFiles/example.dir/example.c.obj
/usr/bin/x86_64-w64-mingw32-gcc -Dexample_EXPORTS @CMakeFiles/example.dir/includes_C.rsp  -o CMakeFiles/example.dir/example.c.obj   -c /vagrant/tmp/odbc/example.c
[100%] Linking C shared library libexample.dll
/opt/cmake-3.12.3-Linux-x86_64/bin/cmake -E cmake_link_script CMakeFiles/example.dir/link.txt --verbose=1
/opt/cmake-3.12.3-Linux-x86_64/bin/cmake -E remove -f CMakeFiles/example.dir/objects.a
/usr/bin/x86_64-w64-mingw32-ar cr CMakeFiles/example.dir/objects.a @CMakeFiles/example.dir/objects1.rsp
/usr/bin/x86_64-w64-mingw32-gcc    -shared -o libexample.dll -Wl,--out-implib,libexample.dll.a -Wl,--major-image-version,0,--minor-image-version,0 -Wl,--whole-archive CMakeFiles/example.dir/objects.a -Wl,--no-whole-archive @CMakeFiles/example.dir/linklibs.rsp
CMakeFiles/example.dir/objects.a(example.c.obj):example.c:(.text+0x7a): undefined reference to `SQLInstallDriverEx'
collect2: error: ld returned 1 exit status
make[2]: *** [libexample.dll] Error 1
make[2]: Leaving directory `/vagrant/tmp/odbc/build'
make[1]: *** [CMakeFiles/example.dir/all] Error 2
make[1]: Leaving directory `/vagrant/tmp/odbc/build'
make: *** [all] Error 2

ToBe

There is a problem, -- Found ODBC: odbc32.lib is wrong, which should be libodbc32.dll or libodbc32.a and then lead undefined reference to 'SQLInstallDriverEx'.

When comment out line 93 in FindODBC.cmake

  # List names of ODBC libraries on Windows
  # set(ODBC_LIBRARY odbc32.lib)
  set(_odbc_lib_names odbc32;)

then a build is success.

-- The C compiler identification is GNU 4.8.2
-- Check for working C compiler: /usr/bin/x86_64-w64-mingw32-gcc
-- Check for working C compiler: /usr/bin/x86_64-w64-mingw32-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Found ODBC: /usr/x86_64-w64-mingw32/lib/libodbc32.a  
-- Configuring done
-- Generating done
-- Build files have been written to: /vagrant/tmp/odbc/build
vagrant@gdal-vagrant:/vagrant/tmp/odbc$ cd build/
vagrant@gdal-vagrant:/vagrant/tmp/odbc/build$ make
/opt/cmake-3.12.3-Linux-x86_64/bin/cmake -H/vagrant/tmp/odbc -B/vagrant/tmp/odbc/build --check-build-system CMakeFiles/Makefile.cmake 0
/opt/cmake-3.12.3-Linux-x86_64/bin/cmake -E cmake_progress_start /vagrant/tmp/odbc/build/CMakeFiles /vagrant/tmp/odbc/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory `/vagrant/tmp/odbc/build'
make -f CMakeFiles/example.dir/build.make CMakeFiles/example.dir/depend
make[2]: Entering directory `/vagrant/tmp/odbc/build'
cd /vagrant/tmp/odbc/build && /opt/cmake-3.12.3-Linux-x86_64/bin/cmake -E cmake_depends "Unix Makefiles" /vagrant/tmp/odbc /vagrant/tmp/odbc /vagrant/tmp/odbc/build /vagrant/tmp/odbc/build /vagrant/tmp/odbc/build/CMakeFiles/example.dir/DependInfo.cmake --color=
Scanning dependencies of target example
make[2]: Leaving directory `/vagrant/tmp/odbc/build'
make -f CMakeFiles/example.dir/build.make CMakeFiles/example.dir/build
make[2]: Entering directory `/vagrant/tmp/odbc/build'
[ 50%] Building C object CMakeFiles/example.dir/example.c.obj
/usr/bin/x86_64-w64-mingw32-gcc -Dexample_EXPORTS @CMakeFiles/example.dir/includes_C.rsp  -o CMakeFiles/example.dir/example.c.obj   -c /vagrant/tmp/odbc/example.c
[100%] Linking C shared library libexample.dll
/opt/cmake-3.12.3-Linux-x86_64/bin/cmake -E cmake_link_script CMakeFiles/example.dir/link.txt --verbose=1
/opt/cmake-3.12.3-Linux-x86_64/bin/cmake -E remove -f CMakeFiles/example.dir/objects.a
/usr/bin/x86_64-w64-mingw32-ar cr CMakeFiles/example.dir/objects.a @CMakeFiles/example.dir/objects1.rsp
/usr/bin/x86_64-w64-mingw32-gcc    -shared -o libexample.dll -Wl,--out-implib,libexample.dll.a -Wl,--major-image-version,0,--minor-image-version,0 -Wl,--whole-archive CMakeFiles/example.dir/objects.a -Wl,--no-whole-archive @CMakeFiles/example.dir/linklibs.rsp
make[2]: Leaving directory `/vagrant/tmp/odbc/build'
[100%] Built target example
make[1]: Leaving directory `/vagrant/tmp/odbc/build'
/opt/cmake-3.12.3-Linux-x86_64/bin/cmake -E cmake_progress_start /vagrant/tmp/odbc/build/CMakeFiles 0
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information