Saturday 19 May 2018

Building libpqxx on MSYS2 MinGW 64 bit

This walkthrough explains how to build the shared library (dll) for libpqxx on MSYS2.

1) Install PostgreSQL

Download the latest PostgreSQL installer. Remember to choose the 64-bit version. This walkthrough uses postgresql-10.3-3-windows-x64.exe. The installation is trivial.

2) Get the libpqxx source code

According to the wiki, the recommended method is to get the source from GitHub: git clone https://github.com/jtv/libpqxx. The revision used here is 120ba161b928fcb5c0a6c6a78370cb21f2e3c6d6.

3) Configure

  1. In the MSYS2 shell, set the path to pg_config: export PATH=$PATH:"/c/Progra~1/PostgreSQL/10/bin". Take note of the use of Progra~1, this is because spaces don't play well with the provided configure script.
  2. Run ./configure --enable-shared=yes --enable-static=no. It should complete without errors.

4) Tweak the <thread> C++ header

I didn't bother to find out why, but if you run make now, compilation will fail for util.cxx with something like the following:
In file included from util.cxx:17:0:
C:/msys64/mingw64/include/c++/7.3.0/thread: In function 'bool std::operator==(std::thread::id, std::thread::id)':
C:/msys64/mingw64/include/c++/7.3.0/thread:276:26: error: no match for 'operator==' (operand types are 'std::thread::native_handle_type {aka ptw32_handle_t}' and 'std::thread::native_handle_type {aka ptw32_handle_t}')
     return __x._M_thread == __y._M_thread;
            ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~

<---snip--->

In file included from util.cxx:17:0:
C:/msys64/mingw64/include/c++/7.3.0/thread: In function 'bool std::operator<(std::thread::id, std::thread::id)':
C:/msys64/mingw64/include/c++/7.3.0/thread:288:26: error: no match for 'operator<' (operand types are 'std::thread::native_handle_type {aka ptw32_handle_t}' and 'std::thread::native_handle_type {aka ptw32_handle_t}')
     return __x._M_thread < __y._M_thread;
            ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~

<---snip--->


The workaround is to edit the header file C:/msys64/mingw64/include/c++/7.3.0/thread. Comment out the offending functions:
//   inline bool
//   operator==(thread::id __x, thread::id __y) noexcept
//   {
//     // pthread_equal is undefined if either thread ID is not valid, so we
//     // can't safely use __gthread_equal on default-constructed values (nor
//     // the non-zero value returned by this_thread::get_id() for
//     // single-threaded programs using GNU libc). Assume EqualityComparable.
//     return __x._M_thread == __y._M_thread;
//   }

  inline bool
  operator!=(thread::id __x, thread::id __y) noexcept
  { return !(__x == __y); }

//   inline bool
//   operator<(thread::id __x, thread::id __y) noexcept
//   {
//     // Pthreads doesn't define any way to do this, so we just have to
//     // assume native_handle_type is LessThanComparable.
//     return __x._M_thread < __y._M_thread;
//   }


Save the changes. Remember to revert them later!

5) Add the -no-undefined flag for libtool

If you run make now, another error will occur:
libtool: error: can't build x86_64-w64-mingw32 shared library unless -no-undefined is specified
Manually edit the makefile in src/ (not the top level one!):
LDFLAGS = -LC:/Progra~1/POSTGR~1/10/lib -no-undefined

6) make

Now you can run make. The dll should build without further errors and can be found at src/.libs/libpqxx-6-2.dll. Congratulations! Note that in order to use the library, you still need to link against libpq.dll, which can be found in C:\Program Files\PostgreSQL\10\lib.

UPDATE: Having trouble with the DLL? Segmentation fault? Read this post regarding the use of libpq from the Windows installer.

3 comments:

  1. Gracias, me ayudó con un error al compilar pgmodeler 0.9.2

    ReplyDelete
  2. Thank you so much!
    This post is still valid on postgresql version 13 & libpqxx 7.2.1

    ReplyDelete
  3. To install pqxx do the following steps:

    1) I have installed mingw64 (ucrt-x86_64 version) with all necessary tools.
    If you use another version, please adapt it.
    2) Open a suitable MSYS2 console (bash)
    - pacman -Suy
    - pacman -S --needed base-devel mingw-w64-ucrt-x86_64-toolchain,
    - pacman -S mingw-w64-ucrt-x86_64-cmake,
    - pacman -S mingw-w64-ucrt-x86_64-autotools,
    - pacman -S mingw-w64-ucrt-x86_64-python-pygments,
    - pacman -S git,
    - and if you want vi run command pacman -S vim
    (https://www.freecodecamp.org/news/vimrc-configuration-guide-customize-your-vim-editor)
    3) Now install postgresql package by running command pacman -S mingw-w64-ucrt-x86_64-postgresql
    All you needed for running a PostgreSQL database will be installed - inclusively the C library libpq.
    4) Run command git clone -b 7.8.1 https://github.com/jtv/libpqxx.git in an empty directory which i call "test".
    Now all files will be downloaded. Afterwards you see a subdirectory called libpqxx.
    (Note: 7.8.1 is currently the latest official version of pqxx at the time of writing.
    See https://pqxx.org/development/libpqxx for a newer version.)
    5) Run command cd libpqxx and afterwards run command ./configure --enable-shared=yes --enable-static=no.
    It should complete without errors.
    6) Run command make the first time. It should complete with 1 error.
    The error output here is:
    //libtool: error: can't build x86_64-w64-mingw32 shared library unless -no-undefined is specified
    //make[1]: *** [Makefile:471: libpqxx.la] Error 1 <-- HERE YOU WILL FIND THE LINE TO BE CHANGED!
    //make[1]: Leaving directory '~/test/libpqxx/src'
    7) Open file src/Makefile by your favorite editor and go to line 471 (This line may differ in a later version).
    You must append -no-undefined at the end of this line.
    8) Run command make again. It should complete without errors.
    9) Run command make install. It should complete without errors.

    Now you can use the pqxx library by including it in you C++ file by means of #include
    and adding libraries -lpqxx -lpq to you linkter.

    ReplyDelete