ANSRTrack – Deploy to Linux: Part 1
ANSRTrack – Deploy to Linux: Part 1
Identifying Critical Libraries
As mentioned in our previous post, I have been developing a new version of our High Altitude Balloon Tracking System. This is being written on the Qt platform, a GUI-based development environment using C++ and its associated libraries.
I will not be discussing the use of the Qt platform up to the point of compiling and running the code in the development mode. Once the code compiles without errors and is reasonably debugged, it is time to deploy the program to be used on computers other than that which it was developed on.
In order to deploy the program, we need an executable file (from our compile effort), and a group of library binary files that the program uses, but which are not likely to be already installed on base linux operating systems. This post outlines my method of identifying those files. I am nowhere near an expert on this, but I will try to explain how I personally arrived at this method.
We start by compiling the program inside the Qt environment. This is while we are still in Debug Mode in the compiler. Prior to this step, we have a folder with our various source files, header files and gui files. It is named ANSRTrack in this case:
To run the compile, make sure that you have “Debug” selected, and press the right facing triangle symbol.
This will result in a new directory containing the object files, compile-related files and an executable file. This is the build-ANSRTRACK…-Debug directory.
The contents look something like this for my project:
Next, we want to build the program in release form. This will result in a smaller, faster executable. The Debug version has a lot of extra stuff in it to support the debugging process. The Release version assumes you don’t need that extra stuff, so does not include it. To get the release version, click on the computer icon that says “Debug” under it, and select “Release” from the pop-out menu. Then click outside of the menu to pop it back in. Your compiler version should now say “Release” under it, instead of “Debug”.
Now, when we run the compile using the green triangle, it will create another directory with the same name as before, but ending with -Release.
Notice that the executable file is roughly 1/10 the size of the debug version file of the same name.
Now that we have an executable, we need to find what libraries that executable depends on to run. These are called dependencies. Open a terminal session and navigate to the Release directory that contains the executable. If you list the files, you will see all of the files in that directory.
To get a list of libraries to start with, we can use the ldd tool in linux to list out the dependencies. It is likely to show some errors about files it cannot find, because we haven’t set an environment variable to tell it where to look at this point, but that doesn’t matter for this step. We are interested in the executable named ANSRTrack, so the command is:
ldd ANSRTrack > ANSRTrack.ldd
This will run the ldd program against the ANSRTrack executable, and send the results to a file named “ANSRTrack.ldd”.
Now if we go back to the gui directory listing, we can see the file of interest – ANSRTrack.ldd
We can open this file up in the linux Text Editor, and use the text search function to search for the sequence Qt. We know that Qt files are not typically installed on linux systems by default, so they are a good place to start looking for files to include in our collection to be deployed with the executable.
The files of interest at this point are:
Oftentimes, the files we are looking for are named something slightly different than what is listed by the ldd command. This depends on what versions we have installed. So now we can look in the Qt5 lib directory and see where what those filenames listed above actually point to.
Note how all of the Qt libraries are located in the: /opt/Qt/5.12.0/gcc_64/lib directory. If we navigate to that directory in our terminal session, we can list the first file of interest – libQtWidgets.so.5
I use the command: ls -la libQt5Widgets.* to list out all files that start with the correct name. Notice that the .so file has a -> symbol pointing to libQt5Widgets.so.5.12.0
That is a symbolic link, meaning it just points to the second file. You can see that the first file has on 23 bytes, while the file we are really interested in has nearly 8Mb of data. So our ANSRTrack program is looking for a file named libQt5Widgets.so.5, which it finds and sees that it really needs libQt5Widgets.so.5.12.0 . So it loads that 5.12.0 file instead. So that is the file we want to copy and save in a separate folder.
Then we can just rename it in its new folder back to libQt5Widgets.so
We continue to do this with the other 4 Qt library files:
libQt5Gui.so, libQt5SerialPort.so, libQt5Positioning.so, libQt5Core.co
When we get to the libicui18n.so.56 file, we see that it is linked to the libicui18n.so.56.1 file. So we similarly copy the 56.1 file to our collection directory, and rename it as we did those above. We do the same process with the other two files: libicuuc.so.56.1 and libicudata.so.56.1
So at this point, we have 9 files in our new directory. One executable and 8 library files. When we try to run the executable on a machine without Qt installed, we will see that double clicking on it seems to do nothing. So we can navigate over to the new collection directory and try to run the program from the command line to see if it will spit out any errors for a clue.
We can see that we do indeed get an error, stating that the “qt.qpa.plugin Could not find the Qt platform plugin “xcb” in “”.
This is kind of cryptic, but I suspect it has to do with the x11 desktop environment. So we have to find something to do with plugins with a name containing “xcb”, it seems.
Well, since it is a Qt plugin error, a good place to start looking is the same directory structure we found all of our other files in: /opt/Qt/5.12.0/gcc_64
We can see that there is a “plugins” directory here… We can also see in the error message that it references a “platform” plugin. Well, there just so happens to be a platforms directory within the plugins directory. If we navigate to this directory, we can search for any file that has the letters “xcb” in it.
Since we are interested in the release version, rather than the debug, we copy the libqxcb.so file to our new collection directory.
So at this point, I tried running the program again from the command line. It took a while and a bit of searching to find out that I needed to put this plugin platform file in its own folder named platforms.
So now, when I ran the program again, I got a different error: It couldn’t run “xcb” even though it was found! Aagh!
So I ran ldd on the libqxcb.so file, and found two more files that IT depended on that had not been listed earlier.
So, using the same process as above, I tracked down the files corresponding to the libQt5XcbQpa.so.5 and libQt5DBus.so.5 entries listed above. I added them to the new collection directory.
So, finally, I ran the program from the command line again (on the remote machine), and it ran! So we have all the files we need. 1 executable and 10 library files in the main directory, and one “plugin platform” library file in the platforms subdirectory.
All of that is kind of ugly, but that is why not everyone wants to be a programmer. But now that we know what files to distribute, we can work on our first deployment method. Distribution of a directory with all of the necessary files in it to run. That will be the topic of my next post on this subject.