
A few days ago there was a question about writing a console application that will work in Linux CentOS 7 and interact with MS SQL Server 2012. I really like Qt and I decided that I would use it to solve this problem. And if under Windows I quickly set up the necessary environment, then under Linux I ran into problems that were very hard to solve with the help of googling. I devoted one and a half days to this question. I consider it useful to share my experience; perhaps this will help someone save valuable time.
Instruments
I don’t want to pull Qt sources into the server in order to build the plugin and the application itself. Therefore, I take the
CentOS 7 LiveGNOME image and install it on the VirtualBox machine. After doing a full update, and put
VirtualBox Guest Additions .
Install g ++:
')
sudo yum install gcc-c++
Downloading
Qt Installer for Linux x64. I install Qt 5.9.1, additionally during installation I select the Source checkbox to get the source code.
Installing Microsoft ODBC Driver for SQL Server
According to the
instructions, I install the driver:
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
The driver needs to be installed both on VirtualBox and on the machine where the software will work.
Qt Build QODBC Plugin
Following the
instructions , download somewhere
unixODBC , unpack. Now we need to build unixODBC and install. In the Qt documentation, as well as in other sources, I mainly found examples that suggest installing unixODBC in / usr / local / unixODBC. This is a matter of taste, of course, but I will use just such an arrangement. I also want to put the driver config files in / usr / local / etc. To do this, you need to configure unixODBC with the following parameters:
./configure --prefix=/usr/local/unixODBC --sysconfdir=/usr/local/etc
Then we assemble and install:
make make install
Now you need to configure the Microsoft ODBC Driver for SQL Server configuration. To do this, go to / usr / local / unixODBC / bin and execute:
sudo ./odbcinst -i -d -f /opt/microsoft/msodbcsql/etc/odbcinst.ini
If you installed the driver as described above, then the location of the odbcinst.ini file will be exactly that. Otherwise, you need to determine your path. All these actions need to be executed both on Virtualbox to the machine and on the worker.
Now you need to build a Qt plugin to work with the ODBC driver. And from this point on, the problems begin, which are partially related to a
bug that has not yet been fixed. In order to assemble a plugin you will have to use some crutches If someone has a more elegant version of a crutch, please write in the comments.
So, for assembly in regular conditions, we need to perform a simple procedure. Go to QT_DIR / 5.9.1 / Src / qtbase / src / plugins / sqldrivers / odbc and execute:
qmake "INCLUDEPATH+=/usr/local/unixODBC/include" "LIBS+=-L/usr/local/unixODBC/lib -lodbc" make make install
But due to the fact that we have a bug, most likely you will get an error:
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.
You can ignore the absence of the qtsqldrivers-config.pri file, but the second error will not allow us to build the plugin. To avoid it, you need to replace the line in the odbc.pro file:
After that, repeat the qmake call:
qmake "INCLUDEPATH+=/usr/local/unixODBC/include" "LIBS+=-L/usr/local/unixODBC/lib -lodbc"
And we get the output Makefile. Another problem I encountered is the compiler flags -Wdate_time and -std = c ++ 1z, which caused a build error.
At that moment I already spent a lot of time to somehow assemble the plugin, so I decided this problem hard, just opened the generated Makefile and changed -std = c ++ 1z to -std = c ++ 11, and the -Wdate_time flag just deleted. These pairs of flags are found in two places. Can I install a more recent gcc, or can someone tell me if it is possible to specify some parameters for qmake to use c ++ 11 instead of c ++ 17?
Whatever you do, you can now do:
make make install
Plugin assembled.
Test application
I created a console application in Qt and wrote the following code to test the connection:
#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; } }
We collect the project on Virtualbox to the machine. We start, we are convinced that everything works. After that we collect the Release version of the program. I will not describe the Qt application deployment process now. Perhaps this is a topic for another publication. I will describe only the key points.
Together with the executable file, you will need additional libraries that can be viewed using ldd. You will also need the plugin itself that you collected. It is in my case in QT_DIR / 5.9.1 / gcc_64 / plugins / sqldrivers and is called libsqlodbc.so. It must also be dragged along. You can put the libraries in / usr / lib, for example, and the system will pick them up, but for plugins, the situation is somewhat different. There are many ways to tell Qt from where to load plugins. The easiest is to define the QT_PLUGIN_PATH environment variable before launch.
Run the program, everything should work.
Conclusion
I would like to hear comments on alternative solutions to this issue. I am pleased to add / correct this post.