Поиск по этому блогу

30 мая 2017

QPSQL driver not loaded: развертывание Qt5+PostgreSQL-приложения на Windows

Дано
ОС Windows 7 или 10 x64
Qt5.5.1 (mingw) (x86) или новее
PostgreSQL 10 или новее

Задача
Заставить разработанное на Qt приложение запускаться на машине без установленного Qt и PostgreSQL и подключаться к СУБД PostgreSQL.

Проблема
При вызове QSqlDatabase::addDatabse("QPSQL") программа пишет:
QSqlDatabase: QPSQL driver not loaded
QSqlDatabase: available drivers: QSQLITE QMYSQL QMYSQL3 QODBC QODBC3 QPSQL QPSQL7

либо вовсе:

QSqlDatabase: QPSQL driver not loaded
QSqlDatabase: available drivers:

 

Анализ
Как в общих чертах происходит работа с БД в Qt:
Функция QSqlDatabase::addDatabse живет в Qt5Sql.dll, и при вызове пытается динамически подгрузить qsqlpsql.dll, которая тянет за собой кучу других dll, часть из которых живет в составе PostgreSQL.

Разберемся, как решать эту и подобные проблемы, связанные с dll.

Принципиально существует два способа связывания dll и exe-файлов: явное и неявное. При загрузке SQL-драйверов Qt задействованы оба способа.
Сначала при запуске exe-файла происходит поиск и загрузка требуемых dll-библиотек, в т.ч. Qt5Sql.dll. Если какие-то библиотеки не найдены, то при запуске программы Windows сообщит об этом.

В процессе работы программы при вызове QSqlDatabase::addDatabse делается динамический поиск dll-файлов SQL-драйверов в определенных каталогах. Для драйвера QPSQL должна быть найдена библиотека qsqlpsql.dll, после чего выполняется попытка ее загрузки.

Для этого загружаются другие неявно связанные с ней dll-библиотеки вместе со своими зависимостями. Если всё дерево необходимых dll-библиотек найдено, то qsqlpsql.dll будет успешно загружена и Qt сможет использовать этот драйвер.
Но сложность в том, что при отсутствии какой-либо библиотеки Windows не выдаст красивого сообщения об этом и придется разбираться другими способами.

Разбираемся
Нам надо выяснить, какие dll-библиотеки требуются для работы программы и куда их нужно положить.

Для этого достаточно в общих чертах представлять, как Windows ищет dll, а именно, что сначала производится поиск в каталоге exe-файла, а в конце - по путям, указанным в переменной окружения PATH. PATH удобно использовать на машине разработчика, но этот вариант рассматривать не будем т.к. это не соответствует изначальной задаче. 

Также надо знать, в каких каталогах QSqlDatabase::addDatabse ищет драйверы SQL. Существуют способы указать Qt альтернативные пути, где искать плагины (в т.ч. SQL), но не будем заниматься и этим.

Исследуем
Используем Прекрасную программы DependencyWalker, которая показывает дерево зависимостей dll и exe-файлов.

Сначала открываем с помощью неё исполняемый файл программы и смотрим, какие dll-библиотеки должны быть доступны, ищем их в каталоге установки Qt и компилятора и кладем рядом с исполняемым файлом. Теперь программа должна запускаться и доходить до вызова QSqlDatabase::addDatabse.

Чтобы увидеть, где Qt ищет SQL-драйверы, добавляем переменную окружения QT_PLUGIN_PATH = 1 (например, в настройках параметров запуска приложения в QtCreator), запускаем программу и изучаем ее вывод. Кроме прочего должны быть примерно такие строки:
QFactoryLoader::QFactoryLoader() checking directory path "C:/Qt/Qt5.5.1/5.5/mingw492_32/plugins/sqldrivers"
...
QFactoryLoader::QFactoryLoader() checking directory path "C:/projects/build-foobar-Desktop-Release/release/sqldrivers"


Из них становится ясно, что по умолчанию Qt ищет SQL-драйверы в каталоге установки и в подкаталоге sqldrivers рядом с exe-файлом. Поэтому находим qsqlpsql.dll в каталоге установки Qt (примерно в C:\Qt\5.5.1\mingw491_32\bin\plugins\sqldrivers) и копируем в подкаталог sqldrivers рядом с exe-файлом.
Если все сделано верно, то после вызова QSqlDatabase::addDatabse должно вывестись:

QSqlDatabase: available drivers: QPSQL QPSQL7
Если не удалось, то попробовать положить qsqlpsql.dll в plugins/sqldrivers.

Далее с помощью DependencyWalker исследуем зависимости qsqlpsql.dll.
Кроме зависимостей от библиотек Qt и компилятора, будет зависимость от libpq.dll.

Проще всего взять libpq.dll из каталога установки PostgreSQL (примерно в C:\Program Files (x86)\PostgreSQL\10\bin). Здесь есть две важнейшие особенности:
1) разрядность libpq.dll должна совпадать с разрядностью приложения. Под Windows стандартный SDK Qt5 с официального сайта 32-разрядный. т.е. необходима 32-разрядная версия libpq.dll, которую можно взять из x86-версии PostgreSQL. Это не влияет на разрядность сервера PostgreSQL, к которому будет подключаться приложение;
2) libpq.dll необходимо располагать рядом с exe-файлом, а не рядом с qsqlpsql.dll. Все остальные dll, от которых зависит libpq.dll, необходимо класть также рядом с exe-файлом приложения.

Теперь все тем же DependencyWalker исследуем зависимости libpq.dll в каталоге установки PostgreSQL.
В зависимости от версии PostgreSQL у libpq.dll могут быть разные dll-зависимости. Находим их все в каталоге установки PostgreSQL и копируем рядом с exe-файлом. Не забываем пройтись по всем зависимостям всех добавляемых dll. 

Сравниваем
Из установленного PostgreSQL 9.4 нужно позаимствовать следующие библиотеки:
libpq.dll
ssleay32.dll
libeay32.dll
libintl-8.dll
libiconv-2.dll

Для PostgreSQL 10 набор уже другой:
libpq.dll
libssl-1_1.dll
libcrypto-1_1.dll
libintl-8.dll
libiconv-2.dll

Более новые версии PostgreSQL выпускаются только в редакции x64, поэтому для получения x86-версии libpq.dll и других библиотек, возможно, придется собирать их из исходников самостоятельно (я не пробовал).

Что еще
возможно, Вам, как и мне, потребуется откуда-то добыть msvcr120.dll (или что-то вроде того в новых версиях Windows и PostgreSQL) и тоже бросить рядом с exe-файлом.

Итого
У меня получилась следующая структура каталога простой консольной программы, выполняющей загрузку драйвера БД:
qpsqltest.exe
sqldrivers/qsqlpsql.dll
Qt5Core.dll
Qt5Sql.dll
libpq.dll
libssl-1_1.dll
libcrypto-1_1.dll
libintl-8.dll
libiconv-2.dll
libwinpthread-1.dll
libstdc++-6.dll
libgcc_s_dw2-1.dll
msvcr120.dll

Архив c примером на гуглодиске

10 комментариев:

  1. Анонимный21 марта, 2018 12:15

    Спасибо большое!
    У меня была ошибка QSqlDatabase: QPSQL driver not loaded.
    Всё что требовалось для ее решение это скачать ваш набор dll и положить их рядом с exe файлом. И проблема решена.
    Использую Qt 5.8 к слову.

    ОтветитьУдалить
  2. Анонимный15 мая, 2018 14:45

    Благодарствую!

    ОтветитьУдалить
  3. Анонимный23 мая, 2018 17:28

    Спасибо!
    Помогло!

    ОтветитьУдалить
  4. Анонимный08 марта, 2019 14:21

    установил библиотеки и... вода пошла
    Спасибо

    ОтветитьУдалить
  5. Анонимный29 июня, 2020 11:23

    Спс.Помогло.

    ОтветитьУдалить
  6. Анонимный18 мая, 2021 11:26

    Архив не открывается, можно ли вас попросить заново его на диск залить?

    ОтветитьУдалить