As mentioned in one of the previous articles, libraries should be versioned. Here it becomes a bit confusing. The versioning of a library is shown on the one hand in the file name and on the other hand in the so-called so-name. The filename typically represents the real version of the library. The version is assigned to the file name libXYZ.so.<period1>.<minor>.<period2>.<release>
<period2> and <release> are optional. This nomenclature is established, but is not a technical necessity. As mentioned above, the file name is not everything. A library also has an internal name, the so-name. It typically only changes if the so-called Application Binary Interface (ABI), the binary interface through which an application communicates with the library, does not change backwards compatible. The so-name is set when linking via the parameter -Wl,-soname=<so-name>.
The ABI should not be confused with the API. A change of the API may result in an ABI change. But there are other reasons for ABI changes, especially when working with C++, see here. Another reason to change the version in so-name is if the behaviour of the library changes incompatibly.
Typically the so-name corresponds to the first one or two digits of the real version. If you put the library to /usr/lib or /usr/local/lib and execute ldconfig, ldconfig automatically creates a symlink with the so-name pointing to the real library. For example, if the library file name is libDemo.so.2.3 and the so-name is libDemo.so.2, then ldconfig will create a symlink named libDemo.so.2 pointing to libDemo.so.2.3.
For an existing library you can read the so-name with the following call:
objdump -p <library> | grep SONAME
A new version of libpiControlIf.so
As basis I used the dynamic library piControlIf from the previous article. Netbeans doesn’t seem to offer a special setting for the so-name, so I added the parameter -Wl,-soname=libpiControlIf.so.1 to the Project Properties in Build → Linker → Additional Options. In addition, I added the current version, in our case .1, to the file name Build → Linker → Output.
After rebuilding the library, the library must be moved to /usr/local/lib. Don’t forget to delete the old file first or make sure to overwrite it.
What is still missing is the link name of the library. This is again a symlink, but this time without any version. It typically points to the latest version of the library. The link must be created manually:
ln -s libpiControlIf.so.1 libpiControlIf.so
If you recreate RevPiBlinkDynamicLib from the previous article, the dynamic linker now requires libpiControlIf.so.1. A look with ldd shows
Creating a Debian package
libpiControlIf is now ready for use, at least on one RevPi. If I want to use the library on other RevPis, I have to copy the library + header to the appropriate place, run ldconfig and set the linker name. It is much easier to create a deb package from the library. Then we can install it on every RevPi using the package manager.
If you want to take the rocky road to creating a Debian package, you should read the various tutorials on the Internet, like this one. I tend to make things as complicated as possible, but here the working minimalism got me, because Netbeans can create a package for me without much effort.
In the Project Properties at Build → Packaging → Package Type set Debian Package.
Then two lines below on Packaging Files (Build → Packaging → Packaging Files). Here in the tab enter the data of the library, like version etc. In the line Package the name of the package is entered. Netbeans also uses this name for the file name of the package. By default Netbeans name the file according to the file name of the program, i.e. libpiControlIf.so. Netbeans automatically adds the file extension .deb to the file name. To name a package something .so.deb seems pointless to me, because the package contains also additional file like the header files. Therefore I named the package libpiControlIf (without .so).
It is important to enter the right one in Architecture, because the package manager must after all know whether the package is suitable for the platform.
Which architecture is currently running on a Debian system can be found out here:
When executed on the RevPi, armhf is displayed:
So register armhf in Packaging Files → Info → Architecture
Besides the library the deb package should also contain the header files piControlIf.hpp and piControl.h. We can add these via Packaging Files → Files → Add Files from Directory. As target directory (File or Directory Path in Package) we specify /usr/lib or /usr/include (without local/), because this time everything is done by the package manager.
Last but not least we add the symlink for the linker name via Packaging Files → Files → Add Softlink.
With a right click on the project More Build Commands → Build Package the package is created on the RevPi in PiControlIf/dist/Release/GNU-Linux/package.
The package can now be installed with apt. Important, do not forget ./ before the file name.
apt install ./libpiControlIf.so.deb
The files should then end up in /usr/lib and /usr/include as set. You may have to delete old versions from /usr/local/lib and /usr/local/include, because the files in the /usr/local directories are used first. This can then lead to undesired effects. Probably it is deliberately chosen to overide existing files in /usr/lib and /usr/include with a new version during development.
Please note: The deb package is not an official Kunbus package and is not maintained by the development. Maybe I can persuade my colleagues to offer it officially in the future.