Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Installing PostgreSQL on Qt 5.15/PostgreSQL 12/Windows 10



  • Hi,

    I'm trying to build an application that requires the QPSQL driver.

    I've installed Qt 5.15 and PostgreSQL 12. My understanding is that I now need to:

    1. Build the QPSQL driver.
    2. Build my app.
    3. Use winqtdeploy to have the QPSQL driver bundled with my .exe.

    Please correct me if that is not right.

    I am currently stuck at #1. What I tried:

    cd C:\Qt\5.15.0\Src\qtbase\src\plugins\sqldrivers
    qmake -- PSQL_INCDIR="C:/Program Files/PostgreSQL/12/include" PSQL_LIBDIR="C:/Program Files/PostgreSQL/12/lib" -sql-psql
    
    Running configuration tests...
    Done running configuration tests.
    
    Configure summary:
    
    Qt Sql Drivers:
      DB2 (IBM) .............................. no
      InterBase .............................. no
      MySql .................................. no
      OCI (Oracle) ........................... no
      ODBC ................................... yes
      PostgreSQL ............................. no
      SQLite2 ................................ no
      SQLite ................................. yes
        Using system provided SQLite ......... no
      TDS (Sybase) ........................... no
    
    ERROR: Feature 'sql-psql' was enabled, but the pre-condition 'libs.psql' failed.
    

    Logfile: https://pastebin.com/MxautpQZ

    Any ideas?


  • Lifetime Qt Champion

    Hi,

    What likely happened is that you had the 32bit command line activated.

    Your approach is the correct one: have all dependencies of the right architecture.

    That said, once you have the librairies, the fact that the database itself runs in 32 or 64bit should not be relevant.

    One additional thing that you might want to consider is to use an out of source build so you can build as many variation as you want without filling the sources with build artifacts.

    You're on the right track !


  • Lifetime Qt Champion

    @Laplace said in Installing PostgreSQL on Qt 5.15/PostgreSQL 12/Windows 10:

    Any ideas?

    Read the logfile:

    C:\Users\MYNAME\Downloads\postgresql-12.3-1-windows-x64-binaries\pgsql\lib\libpq.lib : warning LNK4272: library machine type 'x64' conflicts with target machine type 'x86'



  • @Christian-Ehrlicher said in Installing PostgreSQL on Qt 5.15/PostgreSQL 12/Windows 10:

    Read the logfile:

    C:\Users\MYNAME\Downloads\postgresql-12.3-1-windows-x64-binaries\pgsql\lib\libpq.lib : warning LNK4272: library machine type 'x64' conflicts with target machine type 'x86'

    Thank you for pointing that out (and being nice about it)! I read the logfile but didn't catch that, I guess I wasn't looking very hard.

    I was able to fix the issue by:

    1. Re-downloading the Qt source to get a fresh copy instead of using the copy that came with Qt Creator (which is what I think I was doing before).
    2. Running everything from "x64 Native Tools Command Prompt for VS 2019" (I'm guessing this just sets up the PATH and env vars to link nmake and such to x64 version).
    3. Explicitly using the x64 version of qmake.
    4. Using the x64 version of PostgreSQL 12 (I know that's what I was doing above but I did try the x32 version of PostgreSQL 10 so I want to document what did work).

    Concretely, from the "x64 Native Tools Command Prompt for VS 2019" prompt:

    cd C:\Users\MYNAME\Downloads\qt\qt-everywhere-src-5.15.0\qtbase\src\plugins\sqldrivers
    C:\Qt\5.15.0\msvc2019_64\bin\qmake.exe -- PSQL_INCDIR="C:/Program Files/PostgreSQL/12/include" PSQL_LIBDIR="C:/Program Files/PostgreSQL/12/lib" -sql-psql
    nmake sub-psql 
    nmake install
    

    This resulted in:

    ...
    copy /y ..\plugins\sqldrivers\qsqlpsql.pdb C:\Qt\5.15.0\msvc2019_64\plugins\sqldrivers\qsqlpsql.pdb
    ...
    

    And in the folder C:\Qt\5.15.0\msvc2019_64\plugins\sqldrivers I now have:

    qsqlpsql.dll
    qsqlpsql.pdb
    qsqlpsqld.dll
    qsqlpsqld.pdb
    

    Which I think is the drivers and their debug versions (just a guess).

    Now I'll have to try actually building and deploying my application, and hope these drivers get picked up and packaged by windeployqt.

    I know I took the grenade approach of "make sure everything is running on the same architecture", but it would be helpful to understand if that was the correct approach or if there was a specific one of the steps I took that was required. My hunch is that qmake calls nmake and nmake defaults to the x86 version even if using the x64 version of qmake. So the fix was using the Visual Studio x64 prompt. But any clarification of my understanding would be appreciated @Christian-Ehrlicher .

    I also want to make sure I am understanding the following correctly: when I installed Qt Creator it installed both x86 and x64 version of the Qt framework (hence I am able to build my app for both platforms in Qt Creator). What I just did was build the x64 version of the PostgreSQL plugin so that if I build my app for x64 I can package this plugin with the app and run it. If I want to also be able to distribute a 32bit version of my app, I would have to also build the 32bit driver by linking to the 32bit version of PostgreSQL (which means <v10) and essentially reversing my above procedure to make sure everything is 32bit. Is this correct?

    Thanks!


  • Lifetime Qt Champion

    Hi,

    What likely happened is that you had the 32bit command line activated.

    Your approach is the correct one: have all dependencies of the right architecture.

    That said, once you have the librairies, the fact that the database itself runs in 32 or 64bit should not be relevant.

    One additional thing that you might want to consider is to use an out of source build so you can build as many variation as you want without filling the sources with build artifacts.

    You're on the right track !



  • @SGaist said in Installing PostgreSQL on Qt 5.15/PostgreSQL 12/Windows 10:

    That said, once you have the librairies, the fact that the database itself runs in 32 or 64bit should not be relevant.

    What do you mean by this? What kind of mixing and matching can I do? For example, can I use PostreSQL 12 (only comes in 64bit) for a Qt application that I build as 32bit?

    One additional thing that you might want to consider is to use an out of source build so you can build as many variation as you want without filling the sources with build artifacts.

    Does this mean somehow specifying "build the plugin and put it in XYZ folder" (as opposed to putting it in C:\Qt\5.15.0\msvc2019_64\plugins\sqldrivers or something like that)?

    Thanks!


  • Lifetime Qt Champion

    The server itself could be on a remote machine under a different OS. The client being in 64 or 32 does not have a role. As you noted, it's the client library that you need to build the plugin that needs to match the architecture of your application.

    Out of source build means literally that, you trigger the build from a folder outside of the sources. But the steps are the same.



  • @SGaist said in Installing PostgreSQL on Qt 5.15/PostgreSQL 12/Windows 10:

    The server itself could be on a remote machine under a different OS. The client being in 64 or 32 does not have a role. As you noted, it's the client library that you need to build the plugin that needs to match the architecture of your application.

    The server vs. client part makes sense. What is not clear to me is: can I compile 32bit Qt drivers for PostgreSQL 12 (which is 64bit only)? Since the drivers are compiled from the PostgreSQL source and not the binaries, that should be possible, right?

    Thanks!



  • I'm sorry to say I am still having trouble. The compiling the drivers is now fine, but I am having trouble when it comes to actually using them.

    From my applications log:

     QFactoryLoader::QFactoryLoader() looking at "C:/Qt/5.15.0/msvc2019_64/plugins/sqldrivers/qsqlpsqld.dll"
     Found metadata in lib C:/Qt/5.15.0/msvc2019_64/plugins/sqldrivers/qsqlpsqld.dll, metadata=
     {
         "IID": "org.qt-project.Qt.QSqlDriverFactoryInterface",
         "MetaData": {
             "Keys": [
                 "QPSQL7",
                 "QPSQL"
             ]
         },
         "archreq": 1,
         "className": "QPSQLDriverPlugin",
         "debug": true,
         "version": 331520
     }
     
     
     Got keys from plugin meta data ("QPSQL7", "QPSQL")
    

    So this is the actual debug plugin. The metadata looks good.

     Module loaded: C:\Qt\5.15.0\msvc2019_64\plugins\sqldrivers\qsqlpsqld.dll
    

    So it was able to load the DLL for the plugin...

     Cannot load library C:\Qt\5.15.0\msvc2019_64\plugins\sqldrivers\qsqlpsqld.dll: The specified module could not be found.
    

    But then failed to load it!

    It seems that some deps of qsqlpsqld.dll is failing to load. I checked dependency walker (this rewrite specifically) and LIBPQ.dll was missing. This DLL is located in C:\Program Files\PostgreSQL\12\lib which should have been included (or linked?) when building the plugin!

    After copying LIBPQ.dll to the plugin folder, the following were missing:

    libcrypto-1_1-x64.dll
    libssl-1_1-x64.dll
    libintl-8.dll
    WS2_32.dll
    WLDAP32.dll
    

    The first two are from OpenSSL, the last two are from Windows and finally libintl-8.dll seems to be from PostgreSQL itself.

    Here is the nmake log (here).

    I installed OpenSSL (using this installer). Installing this and fixed those two dependencies.

    I'm assuming WS2_32.dll and WLDAP32.dll are not causing the issue.

    So I'm stuck at libintl-8.dll: this is a PostreSQL lib, but in C:\Program Files\PostgreSQL\12\lib all I have is libintl.lib. My understanding of these things is limited, but I believe that libintl.lib is a static library, so wouldn't the compilation process of the plugin need to generate the above referenced DLL (libintl-8.dll)? Or where is the reference to libintl-8.dll coming from?

    Is there a way to avoid this hassle altogether by telling qmake or namke "just build/copy all of the required dependencies to C:\Qt\5.15.0\msvc2019_64\plugins\sqldrivers when you build"?


  • Lifetime Qt Champion

    @Laplace said in Installing PostgreSQL on Qt 5.15/PostgreSQL 12/Windows 10:

    "just build/copy all of the required dependencies to C:\Qt\5.15.0\msvc2019_64\plugins\sqldrivers when you build"?

    No, you have to take care for your deps by yourself with e.g. Dependency Walker.



  • @Christian-Ehrlicher said in [Installing PostgreSQL on Qt 5.15/PostgreSQL

    No, you have to take care for your deps by yourself with e.g. Dependency Walker.

    Good to know at least that I am doing things the right way!

    I was able to find libintl-8.dll in C:\Program Files\PostgreSQL\12\bin.

    Still unable to load the plugin. It seems that WS2_32.dll and WLDAP32.dll are causing issues. These are Windows libraries. Googling reveals pretty generic results. If anyone has any ideas, I'd appreciate the input.


  • Lifetime Qt Champion

    I would check if the correct msvc runtime is installed on the target pc. Afair it needs the ones from msvc2015. But don't remember exactly.



  • I was able to resolve things!

    Here were the required dependencies:

    • libcrypto-1_1-x64.dll: from OpenSSL install.
    • libssl-1_1-x64.dll: from OpenSSL install.
    • libpq.dll: from C:\Program Files\PostgreSQL\12\lib
    • libintl-8.dll: from C:\Program Files\PostgreSQL\12\bin
    • libiconv-2.dll: from C:\Program Files\PostgreSQL\12\bin

    I first copied them manually to the same folder as my .exe, along with the actual plugin DLLs (qsqlpsql.dll). That worked.

    Next I tried using windqtdeploy. It actually was able to detect all of them, but it copied them to a folder called sqldrivers which is a subdirectory of the folder my .exe is in. That did not work. I had to manually copy the following from the sqldrivers subdirectory to the main directory:

    • libpq.dll
    • libintl-8.dll
    • libiconv-2.dll

    Is there any way to tell windqtdeploy to copy these DLLs to the .exe folder instead of the subfolder, hence avoiding one more manual step?


  • Lifetime Qt Champion

    @Laplace said in Installing PostgreSQL on Qt 5.15/PostgreSQL 12/Windows 10:

    Is there any way to tell windqtdeploy to copy these DLLs to the .exe folder instead of the subfolder

    No but they should be in the same dir as the plugin so it's strange - maybe you have some of those libs (with other version) in your PATH?



  • @Christian-Ehrlicher said in [Installing PostgreSQL on Qt 5.15/PostgreSQL

    No but they should be in the same dir as the plugin so it's strange - maybe you have some of those libs (with other version) in your PATH?

    I don't think so because (1) I checked my PATH and didn't see anything and (2) I don't have any other versions of PostgreSQL intalled or anything like that.


  • Lifetime Qt Champion

    @Laplace Ok, then I'll accept it the way it is - no time to look further why it doesn't work like it should :)



  • Alternatively: can I add the sqldrivers folder to the top of the current session (or whatever these are called in Window's)? So something equivalent to:

    set "PATH=%cd%\sqldrivers;%PATH%"
    myapp.exe
    

    But done automatically when double clicking the .exe.



  • This did the trick:

    #ifdef Q_OS_WIN
        // Add the sqldrivers folder to path
        QDir app_dir(QApplication::applicationDirPath());
        QString path;
        path = app_dir.absolutePath();
        path = path + "/sqldrivers";
        path = QStringLiteral("%1;%2").arg(path).arg(QString(qgetenv("PATH")));
        qputenv("PATH", path.toUtf8());
    #endif
    

Log in to reply