Установка MS SQL ODBC Driver под Linux и сборка плагина для Qt 5.9

в 8:59, , рубрики: c++, linux, Microsoft SQL Server, odbc, qt, qt5, unixodbc, Разработка под Linux

image

Несколько дней назад встал вопрос о написании консольного приложения, которое будет работать в Linux CentOS 7 и взаимодействовать с MS SQL Server 2012. Мне очень нравится Qt и я решил, что воспользуюсь им для решения этой задачи. И если под Windows я достаточно быстро настроил необходимое окружение, то под Linux я столкнулся с проблемами, которые очень тяжело было решить с помощью гуглинга. Этому вопросу я посвятил полтора дня. Считаю полезным поделиться своим опытом, возможно кому-то это поможет сэкономить драгоценное время.

Инструменты

Я не хочу тянуть на сервер исходники Qt, для того чтобы собрать плагин и само приложение. Поэтому беру образ CentOS 7 LiveGNOME и устанавливаю его на VirtualBox машину. После делаю полный апдейт, и ставлю VirtualBox Guest Additions.

Устанавливаю g++:

sudo yum install gcc-c++

Скачиваю установщик Qt для Linux x64. Устанавливаю Qt 5.9.1, дополнительно при установке выбираю галочку Source, чтобы получить исходники.

Установка Microsoft ODBC Driver for SQL Server

Согласно инструкции устанавливаю драйвер:


sudo su
curl https://packages.microsoft.com/config/rhel/7/prod.repo > /etc/yum.repos.d/mssql-release.repo
exit
sudo yum remove unixODBC-utf16 unixODBC-utf16-devel
sudo ACCEPT_EULA=Y yum install msodbcsql
sudo ACCEPT_EULA=Y yum install mssql-tools
echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bash_profile
echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc
source ~/.bashrc
sudo yum install unixODBC-devel

Драйвер нужно установить как на VirtualBox, так и на машину, где будет работать софт.

Сборка Qt плагина QODBC

Следуя инструкции, скачиваем куда-нибудь unixODBC, распаковываем. Теперь нам нужно собрать unixODBC и установить. В документации Qt, а так же в других источниках в основном я встречал примеры, которые предполагают установку unixODBC в /usr/local/unixODBC. Тут дело вкуса конечно, но я буду использовать именно такое расположение. Так же файлы конфигов драйверов я хочу поместить в /usr/local/etc Для этого нужно сконфигурировать unixODBC со следующими параметрами:

./configure --prefix=/usr/local/unixODBC --sysconfdir=/usr/local/etc

Затем собираем и устанавливаем:

make
make install

Теперь необходимо настроить конфигурацию Microsoft ODBC Driver for SQL Server. Для этого переходим в /usr/local/unixODBC/bin и выполняем:

sudo ./odbcinst -i -d -f /opt/microsoft/msodbcsql/etc/odbcinst.ini

Если вы устанавливали драйвер как было описано выше, то расположение файла odbcinst.ini будет именно таким. Иначе вам нужно определить свой путь. Все эти действия нужно выполнить и на Virtualbox машине и на рабочей.

Теперь нужно собрать Qt плагин для работы с ODBC драйвером. И с этого момента начинаются проблемы, которые частично связаны с багом, который еще не пофиксили. Для того, чтобы собрать плагин придется применить некоторые костыли. Если у кого-то возникнет более элегантный вариант костыля, пожалуйста напишите в комментариях.

Итак, для сборки в штатных условиях нам нужно выполнить простую процедуру. Переходим в QT_DIR/5.9.1/Src/qtbase/src/plugins/sqldrivers/odbc и выполняем:

qmake "INCLUDEPATH+=/usr/local/unixODBC/include" "LIBS+=-L/usr/local/unixODBC/lib -lodbc"
make
make install

Но из-за того, что имеем баг, скорее всего вы получите ошибку:

Cannot read QT_DIR/5.9.1/Src/qtbase/src/plugins/sqldrivers/qtsqldrivers-config.pri: No such file or directory
Project ERROR: Library 'odbc' is not defined.

На отсутствие файла qtsqldrivers-config.pri, можно не обращать внимание, а вот вторая ошибка не даст нам собрать плагин. Чтобы ее избежать нужно закомменитровать в файле odbc.pro строчку:

#QMAKE_USE += odbc

После этого повторим вызов qmake:

qmake "INCLUDEPATH+=/usr/local/unixODBC/include" "LIBS+=-L/usr/local/unixODBC/lib -lodbc"

И получим на выходе Makefile. Еще одна проблема с которой я столкнулся это флаги компилятора -Wdate_time и -std=c++1z, которые вызывали ошибку сборки.

На этот момент я уже потратил много времени, чтобы хоть как-то собрать плагин, поэтому эту проблему я решил жестко, просто открыл сгенерированный Makefile и изменил -std=c++1z на -std=c++11, а флаг -Wdate_time просто удалил. Эти пары флагов встречаются в двух местах. Можно установить более свежий gcc, или может кто-то подскажет есть ли возможность указать для qmake какие-то параметры, чтобы использовать c++11 вместо c++17?

Как бы вы ни поступили, теперь можно выполнить:

make
make install

Плагин собран.

Тестовое приложение

Я создал консольное приложение в Qt и написал следующий код для тестирования соединения:

#include <QCoreApplication>
#include <iostream>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>

int main(int argc, char *argv[])
{
   QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
   QString connectionString = "DRIVER={ODBC Driver 13 for SQL Server};Server=<host>\<instance>,<port>;Uid=<login>;Pwd=<password>";
   db.setDatabaseName(connectionString);
 
   if(db.open()) {
      std::cout << "Connection succes!" << endl;
      return 0;
   }else{
      std::cout << db.lastError().text().toStdString() << endl;
      return 1;
   }
}

Собираем проект на Virtualbox машине. Запускаем, убеждаемся, что все работает. После этого собираем Release версию программы. Я не буду сейчас описывать процесс деплоя Qt приложений. Возможно это тема для еще одной публикации. Я опишу лишь ключевые моменты.

Вместе с исполняемым файлом вам потребуются дополнительные библиотеки, которые можно посмотреть с помощью ldd. Так же вам потребуется сам плагин, который вы собрали. Он лежит в моем случае в QT_DIR/5.9.1/gcc_64/plugins/sqldrivers и называется libsqlodbc.so. Его необходимо так же утащить за собой. Библиотеки вы можете положить например в /usr/lib и система их подхватит, а с плагинами дело обстоит несколько по-другому. Есть множество способов сказать Qt от куда загружать плагины. Самый простой — это перед запуском определить переменную окружения QT_PLUGIN_PATH.

Запускаем программу, все должно работать.

Заключение

Хотелось бы услышать комментарии по поводу альтернативных решений данного вопроса. С удовольствием дополню/исправлю этот пост.

Автор: shude

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js