Distribution via Folder Copy

In my last post, I described how I went about identifying all of the files necessary to distribute my new High Altitude Balloon Tracking program to linux machines other than the one it had been developed on.

At the end of that post, I was left with a folder which contained an executable file, several library files and a subfolder containing another library file.

In this post, I will go over the structure of these folders and how I tested the distribution on alternate linux operating systems and machines.

Basically, I started with the second distribution method mentioned in the Qt Wiki article. The first method was to statically build the application, which results in a huge executable, and looked to be more work than I was interested in doing at this point.

The second distribution method is to collect the executable and supporting files all under a single directory tree, add a shell script to set the library path and distribute that collection of files together.

At the end of my last post, I had the following directory structure accumulated:

  • ANSRTrack folder
    • ANSRTrack – Executable file
    • libQt5Core.so.5 – shared library
    • libQt5Gui.so.5 – shared library
    • libQt5Widgets.so.5 – shared library
    • libQt5Positioning.so.5 – shared library
    • libQt5SerialPort.so.5 – shared library
    • libQt5Dbus.so.5 – shared library
    • libQt5XcbQpa.so.5 – shared library
    • libicui18n.so.56 – shared library
    • libicuuc.so.56 – shared library
    • libicudata.so.56 – shared library
    • platforms directory
      • libqxcb.so – shared platform library

To this structure, we now have to add just a shell script that will add the correct path to this directory so that these libraries can be found and loaded when the program is loaded.

The Qt Wiki provides the following shell script to set the LD_LIBRARY_PATH correctly when it is run, regardless of where the folder is moved to. As long as the script is contained within the folder described above, it should work.

#!/bin/sh 
appname=`basename $0 | sed s,\.sh$,,`
dirname=`dirname $0`
tmp="${dirname#?}"
if [ "${dirname%$tmp}" != "/" ]; then
dirname=$PWD/$dirname
fi
LD_LIBRARY_PATH=$dirname
export LD_LIBRARY_PATH
$dirname/$appname "$@"

I just copied that code to a text file named ANSRTrack.sh, saved it in the directory structure with the executable and library files and made it executable. So now we have this:

  • ANSRTrack folder
    • ANSRTrack – Executable file
    • ANSRTrack.sh – shell script
    • libQt5Core.so.5 – shared library
    • libQt5Gui.so.5 – shared library
    • libQt5Widgets.so.5 – shared library
    • libQt5Positioning.so.5 – shared library
    • libQt5SerialPort.so.5 – shared library
    • libQt5Dbus.so.5 – shared library
    • libQt5XcbQpa.so.5 – shared library
    • libicui18n.so.56 – shared library
    • libicuuc.so.56 – shared library
    • libicudata.so.56 – shared library
    • platforms directory
      • libqxcb.so – shared platform library

As a first test, I should be able to double click on the ANSRTrack.sh file and run my program. I can, so it works locally. Next, I copy the ANSRTrack folder to a second linux machine, either by network or by memory stick.

Next, I made sure that the executable file and the shell script were set to be executable. Sometimes when copying across a network or shared drive or flash drive, the executable bits gets unset, as a security measure. Note that the platforms directory itself must have its executable bits set, too (as does the ANSRTrack directory).

Running the ANSRTrack.sh script from this state was a success on the second linux machine with no Qt5 development system installed.

For a second test, I copied the ANSRTrack Directory to a flash drive. Then I booted that laptop to a Linux Mint LiveUSB image on a flash drive. After copying my program folder to the new linux desktop and modifying the permissions of the executable and script files as before, I started up the ANSRTrack.sh file. This loaded my ANSRTrack program, but the serial ports did not seem to be working. A little research taught me that when booting a liveCD or liveUSB image, you have to go in and change the permissions on the serial port files in linux. My program identifed the two serial ports I was interested in were the ttyACM0 and ttyUSB0 ports.

Using a terminal session, I changed the permissions on two files to allow read/write and execute on the two files of interest:

sudo chmod 777 ttyACM0

sudo chmod 777 ttyUSB0

After making this change, the program operated as expected. This is great. It means that even if the user doesn’t have a linux machine, he will be able to boot to a liveUSB image of linux and run the program from there. All with no software changes other than copying the folder and changing the permissions on the files.