What is `relinking` warning? - build

While compiling mpich, I got a few relinking warnings...
libtool: warning: relinking 'lib/libmpicxx.la'
I have not been able to find out what these mean by googling the error message. What is relinking? Why is it caused and how can I get rid of it?

The "relinking" warning is emitted when installing, not when compiling. Libtool warns you that it is running a potentially slow command during the install. There may be different reasons for relinking.
In case of mpich, the reason is completely innocuous. The libmpicxx library depends on libmpi library. Both are built from the same source. Libtool ensures that if you run any executable in the build directory, it would use the libraries from the build directory rather than the installed library.
There is no way to make sure (at least on Linux) that libmpicxx would use the locally built libmpi library without hardcoding the library search path (so called RPATH) into libmpicxx.
For the installed libraries, the requirement is that they never refer to the build tree where they were built. So the RPATH needs to be eliminated from the installed libmpicxx library. That is done by relinking it.
Once again, the warning is not about you or the package doing anything wrong, it's about a potentially slow operation at the install stage (slow operations at the build stage are expected and don't need a warning).

Related

Compile a library in a way that it's shippable

I've a question regarding compilation of a dependency (namely poppler). Poppler is a dependency of my app which is an electron app.
It's working fine on windows (because npm package node-poppler ships the poppler windows build). But on a mac / linux I have to install poppler dependencies by myself (e.g. via homebrew) and then also everything works well.
Now I want to ship the app including poppler and therefore I've started to compile poppler by myself. This is working particularly and all dependencies that it needs I've added via homebrew and finally the build is running and it compiles successfully after long try and error.
But my problem now is, hat if I remove all homebrew dependencies after I've compiled poppler it stops working because there are "links ? (dont know the exact term)" to these dependencies.
e.g.
cmd: './extlib/darwin/poppler/poppler-gitlab/cmake-build-release/utils/pdfinfo -v',
stdout: '',
stderr: 'dyld[93398]: Library not loaded: /usr/local/opt/fontconfig/lib/libfontconfig.1.dylib\n' +
' Referenced from: <0062B574-27F1-35D4-BEF8-81E2F2B5EEDB> /Users/bernhard´/Coding/Sides/backend/extlib/darwin/poppler/poppler-gitlab/cmake-build-release/libpoppler.126.0.0.dylib\n' +
" Reason: tried: '/usr/local/opt/fontconfig/lib/libfontconfig.1.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/opt/fontconfig/lib/libfontconfig.1.dylib' (no such file), '/usr/local/opt/fontconfig/lib/libfontconfig.1.dylib' (no such file), '/usr/local/lib/libfontconfig.1.dylib' (no such file), '/usr/lib/libfontconfig.1.dylib' (no such file, not in dyld cache)\n"
After a lot of reading I've found out that it might be possible to compile it static (even unsure if I'm using the right term here).
I'd like to know what I neet to do, that I can ship the app and what's required, to build poppler in a way that is has no dependencies anymore or has it's dependencies in a place that I have control over and can ship it with my app.
Actually I'm building using following CMAKE options:
-G Ninja -DCMAKE_BUILD_TYPE=Release -DC_MAKE_PROGRAM=/Applications/CLion.app/Contents/bin/ninja/mac/ninja -DCMAKE_FIND_FRAMEWORK=LAST -DCMAKE_VERBOSE_MAKEFILE=ON -DPOPPLER_QT5=OFF -DPOPPLER_ENABLE_CMS=none -DPOPPLER_ENABLE_SPLASH=OFF -DPOPPLER_ENABLE_UTILS=OFF -DPOPPLER_ENABLE_GLIB=OFF -DPOPPLER_ENABLE_CPP=OFF -DPOPPLER_ENABLE_XPDF_HEADERS=OFF -DPOPPLER_ENABLE_ZLIB=OFF -DPOPPLER_ENABLE_LIBCURL=OFF -DPOPPLER_ENABLE_LIBSYSTEMD=OFF -DPOPPLER_ENABLE_OPENJPEG=OFF -DPOPPLER_ENABLE_TIFF=OFF
Thanks for any help and sorry for maybe misusing terms as I'm mostly a frontend dev.
You have to compile your program with an RPATH option for your shipped libraries. The reason why you can't run it without those deleted dependencies is simple. (Regarding RPATH check out the ld man pages.)
Your application seems to be linking against the same version of the dependency as the one in your homebrew directory. Thus this shared object is compatible with your executable.
Your linker is only configured to look for the shared objects within certain directories. Thus when you delete the directory, your linker doesn't know where to find these shared objects anymore (because they do not exist).
On linux distributions you could run your application for example with: LD_LIBRARY_PATH=./path_to_your/library/ && ./your_executable. And it would suddenly work.
RPATH solves this by telling the linker where to look for the linked dependencies.
I would like to give you a general warning here. This is not the way to go when it comes to shipping your executable (and especially libraries) on different distros. It's better to make a package, using the available -dev packages for the given distribution. - Because otherwise you are slowly introducing dependency hell for the developers who wish to use it!
To answer your question regarding static linking: You will increase the size of your executable, so keep that in your mind if you wish to take this path instead

Fixing error: *** No rule to make target '/usr/lib/x86_64-linux-gnu/libdl.so'

I have recently upgraded my OS (to PopOS! 22.04) and now a bunch of builds in my cmake workflow aren't compiling, halting at this particular error at the linking stage:
*** No rule to make target '/usr/lib/x86_64-linux-gnu/libdl.so'
This file now no longer exists. There is however a libdl.so.2.
Running apt-file search /usr/lib/x86_64-linux-gnu/libdl.so gives no output.
How can I get my builds working again?
EDIT:
The solution turned out to be due to manually built dependencies/packages that obviously weren't updated during the upgrade. I had to go and rebuild them, and then the error disappeared. Note, when rebuilding them (also with CMake) it required a full deletion of the build directory, not just running CMake again.
Jammy's GNU C Libarry version is 2.35. The dl library is now part of the C standard library. The release notes, tells that, starting from version 2.34,
all functionality formerly
implemented in the libraries libpthread, libdl, libutil, libanl has
been integrated into libc. New applications do not need to link with
-lpthread, -ldl, -lutil, -lanl anymore. For backwards compatibility,
empty static archives libpthread.a, libdl.a, libutil.a, libanl.a are
provided, so that the linker options keep working. Applications which
have been linked against glibc 2.33 or earlier continue to load the
corresponding shared objects (which are now empty).
This means that you have to remove the explicit libdl.so from the linker dependencies.

Only relink shared libraries when headers change in CMake

Using CMake, is there a way to generate build systems that don't relink everything downstream if a shared library's source code changes without its headers changing?
In Makefiles, I've used rules with an order only prerequisite on the shared library itself and regular prerequisites on the library headers to get this effect.
I know this isn't strictly guaranteed to produce a correct build, e.g. you could delete a function definition from the shared library, but this is for quickly rebuilding a debug build and in my experience it almost always has produced a correct build. I think there was once or twice that I ran into a runtime linker error but on that odd occasion it's not much trouble to run the build as usual.
Still, if there are good reasons that this is actually a terrible idea and shouldn't be done that could be an answer too.
In CMake 2.8.11 and later you can set CMAKE_LINK_DEPENDS_NO_SHARED to get this behavior.
http://thread.gmane.org/gmane.comp.programming.tools.cmake.user/43246/focus=44469
http://www.cmake.org/cmake/help/v3.1/prop_tgt/LINK_DEPENDS_NO_SHARED.html

How can I link to an older version of a shared library

I'm building my program on my computer, on which libtiff.so -> libtiff.so.5.
And then pushing the builds on another machine on which libtiff.so -> libtiff.so.4.
At runtime, my program exists : « error while loading shared libraries: libtiff.so.5: cannot open shared object file: No such file or directory ».
I cannot upgrade the other machine, and I would like to avoid compiling on a virtual machine (with the same linux version than the executing machine). Therefore, I would like to force the compiler to use the libtiff.so.4 instead of libtiff.so.5.
I have libtiff.so.4 installed on my computer (as well as libtiff.so.5). How can I force the linkage with this version instead of the newer version. I thought about moving the libtiff.so -> libtiff.so.4, but I'm afraid of breaking my system if it needs the latest version (apt-get purge libtiff5 gives an error because some other package needs it).
Is it possible to link with an older (installed) version of a library? If yes, how?
And is it harmfull to change the symbolic link of libtiff.so to the older version? If not, will it solve my issue?
You can use this syntax to link to a specific version of a library:
gcc [other options] -l:libtiff.so.4
You do not need to specify a path; the usual directories are searched in order to find the library.
Note: as Michael Wild mentioned, you should have the header files for that version installed instead of the newest ones.
As others have mentioned, you can force the linker by specifying the full versioned name, or even the absolute path.
However, I would strongly advice against doing so. The problem is, that the installed headers correspond to the newer version of the library. If there have been API/ABI-breaking changes between these library versions, the program might work, crash intermittently, or if you're lucky, not work at all.
Instead you should temporarily install the development package that corresponds to the libtiff.so.4 library. If on Debian/Ubuntu or similar, this would be the libtiff4-dev package.
Specify the full path to the .so: instead of -ltiff pass /lib64/libtiff.so.4 to the linker.
You see that error when application is running. So you can either stop your application and then exrract your library tar file. Or, force to link the lib file to the newer version after you extract. In second case, you will use something like:
ln -fs libversionname libfile
Example:
ln -fs libomyapp.1.1.3 libomyapp.lib
This links your libomyapp.lib to the version specified. This can be your older vsersion or your newer version.
But as said, best way to work is to bring down your application to properly match to the expected lib functionality to work without errors or issues.

How to use Qt app on tiny210 device?

I want to use a Qt app on a tiny210 device.
I installed Qt ( qt-everywhere-opensource-src.4.8.5 ) downloaded from here. I managed to compile a simple application for use on tiny210. The problem is that now when I try to run the app on the device, I get the following errors:
libc.so.6: version 'GLIBC_2.15' not found (required by libQtCore.so.4)
libc.so.6: version 'GLIBC_2.15' not found (required by libQtNetwork.so.4)
There is a libc.so.6 in /lib/ on the target device, but it is version 2.11.
I should mention that before getting those errors I also got errors for not having libQtCore.so.4, libQtNetwork.so.4 and libQtGui.so.4. I fixed those errors just by copying the compiled libraries from my host PC to the device.
First question is: Would there have been a better way to provide the needed libraries, or copying them is fine?
Second question is: How can I get over the errors mentioned above?
EDIT : I've read something about building it static, but I am not sure how, and what are the downsides of this.
EDIT2 : I managed to get over the above errors thanks to artless noise's answer, but now I get: error loading shared libraries: libQtGui.so.4: cannot open shared object file: No such file or directory.
The issue is the cross-compiler (apt-get install gcc-arm-linux-gnueabi) is ARM based and this cross compiler has a newer glibc than on the ARM device. You can copy the libc from the cross compiler directory to your ARM device. I suggest testing with LD_LIBRARY_PATH, before updating the main libraries. Use ls /var/lib/dpkg/info/*arm-linux*.list to see most packages related to the ARM compiler. You can use grep to figure out where the libraries are (or fancier things like apt-file, etc).
Crosstool-ng has a populate script, but I dont see it in the Ubuntu packages; it is perfect for your issue. If it is present on your Debian version, I would use it.
The glibc 2.15 is backwards compatible with the glibc 2.11 which is currently on your system. Issues may arise if the compiler was configured with different options (different ABI); however if this is the case, you will have many issues with your built Qt besides the library. In this case, you need to find a better compiler which fits your root filesystem.
So to be clear, on the target
mkdir /lib/staging
cp libc.so-2.15 /lib/staging
cd /lib/staging
ln -s libc.so-2.15 libc.so
LD_LIBRARY_PATH=/lib/staging ls # test the library
You may have to copy additional libraries, such as pthread, resolv, rt, crypt, etc. The files are probably in a directory like sysroot/lib. You can copy the whole directory to the /lib/staging to test it. If the above ls functions, then the compilers should be ABI compatible. If you have a crash or not an executable, then the compiler and rootfs may not be compatible.
Would there have been a better way to provide the needed libraries, or copying them is fine?
Copying may be fine as per above. If it is not fine, then either the compiler or the root filesystem must be updated.
How can I get over the errors mentioned above?
Try the above method. As well, you maybe able to leave your root filesystem alone. Set-up a shadow directory and use chroot to run the Qt application with the copied files as another solution. To test this, make a very simple program and put it along the compiler libraries in a test directory, say /lib/staging as above. Then the test code can be run like,
$ LD_LIBRARY_PATH=/lib/staging ./hello_world
If this doesn't work, your compiler and the ARM file system/OS are not compatible. No library magic will help.
I've read something about building it static, but I am not sure how, and what are the downsides of this.
See Linux static linking is dead. I understand this seems like a solution. However, if the compiler is wrong, this won't help. The calling convention between OS, libraries and what registers are saved by the OS will be implicit in the compiled code. You may have to rebuild Qt with -softfp, etc.