gcc: error while loading shared libraries -> looks up wrong library version - c++

I upgraded my system (to ubuntu 13.04) and somewhere in the process gcc broke :-( I'm getting this exception when trying to compile something:
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../x86_64-linux-gnu/bin/as:
error while loading shared libraries:
libopcodes-2.22-system.so: cannot open shared object file: No such file or directory
Actually libopcodes-2.22-system.so does not exist, BUT libopcodes-2.23.2-system.so does.
If i symlink from 2.22 to 2.23 gcc fails with just another library.
So for some reason it is looking for the wrong version. I wildly tried to solve it by reinstalling gcc, binutils, libc6 etc., but the problem still exists.
How can i tell gcc to use the correct shared library version? / Where does gcc gets the information which shared libraries to use?
Thx

Thanks guys, your comments made me look at the right place.
This path made me suspicious:
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../x86_64-linux-gnu/bin/as
I thought it must be a symlink to /usr/bin/as, but it exposed that /usr/x86_64-linux-gnu/bin was a complete copy of /usr/bin - not up to date and therefore with incorrectly linked binaries. I have no idea why a copy of the whole bin directory was there and was used by gcc in favor of /usr/bin.
The compiler is running fine after /usr/x86_64-linux-gnu was removed.
Edit: Better check comments before doing the same.

Related

Cross Compiling from Linux-Windows, stdio has undefined references (to __imp___acrt_iob_func)

As the title says, I've been trying to cross compile a fairly large project with quite a few dependencies (both static and dynamic libraries). I've cross compiled every dependency successfully using MinGW-w64, set the include & library search paths to their MinGW counterparts (/usr/x86_64-w64-mingw32/lib & include), and yet on the linking step MinGW throws out an error for each call of printf (with stdio.h included, of course). The errors are as follows:
/usr/bin/x86_64-w64-mingw32-ld: ./obj/XXXX.o:/usr/share/mingw-w64/include/stdio.h:352: undefined reference to `__imp___acrt_iob_func'
(Where "XXXX" is a file name from my project)
This error is repeated the exact same (with the exception of the object file name). The command for linking looks like this:
/usr/bin/x86_64-w64-mingw32-g++ -o bin/ReleaseWin/Project #[file with object file names] -L. -L/usr/x86_64-w64-mingw32/lib/ [linking some dependencies (boost, openGL, SDL2, etc.)...] -m64 -flto
I've searched for a solution (or even someone with the same problem) to no avail. I've never been well-versed in linking any more than regular libraries, so if you need more information just ask.
Thanks in advance :)
Extra info:
This project has been cross compiled (from Linux to Windows) successfully before, and I haven't added/removed any dependencies since.
My MinGW-w64 version is 7.0.0
So, I apt-get purge'd mingw-w64 and mingw-w64-common, reinstalled just mingw-w64, and now it's working...
This might have something to do with the fact that I followed the issue that Richard Critten commented with (thanks!), which led me to try downloading and manually copy/pasting headers and CRT (mingw-w64-x86_64-headers-git-... & mingw-w64-x86_64-crt-git) from the MSYS2 repository. That didn't work right away (probably because I screwed up and used the 5.0.0 versions instead of my version), but it seems to have done something.
Therefore, for those who stumble upon this issue,
Try a re-install of MinGW (of course),
Try manually adding the CRT and headers from the link I supplied, and if that still doesn't work,
Try re-installing MinGW again. I'm not super familiar with apt, so I don't know if adding the CRT and headers actually changed how it installed MinGW, but it's worth a shot I guess.
Update: I had this exact same problem on another system. Simply reinstalling MinGW fixed it, so it seems like maybe there was some sort of issue with the files? It's possible that updating from an earlier version messed with things. Moral of the story: even if you think your files are good, a reinstall can't hurt.

Built GCC 5.4 from source; executables thus built try to link incompatible libstdc++ and fail to run

I have followed instructions to build GCC from source. The only modifications I made for the configure were:
using a binary suffix of -5.4 so that I can use the compiler as g++-5.4 for instance.
setting --configure-multilib because it wouldn't run otherwise.
I'm doing this for testing some of my code by compiling it with various different compilers. On this Centos 7 system I've got the system gcc (4.8.2) as well as clang (also compiled from source) running, and now I'd like to see 5.4 working.
Based on these instructions, inside the source code I've put these statements to make the linker happy.
#define _GLIBCXX_USE_CXX11_ABI 0
Now that the executables compile and link, I'm getting this when I run them...
/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by <program name>)
I can't quite tell here but I do know enough to see that the actual symlink /usr/lib64/libstdc++.so.6 links to the older one (/usr/lib64/libstdc++.so.6.0.19), and the one built as part of GCC 5.4 lives somewhere else (/usr/local/lib64/libstdc++.so.6.0.21). This would indicate that this program I built using 5.4 is looking at the right (old) stdlib shared lib, so something else is amiss.
The new compiler is generating code which expects to be linked to the newer libstdc++, rather than the system one. The linker finds that this expectation is not met, so it throws an error.
To fix this you will have to ensure that the correct path is being used to find and link libstdc++. There are a few options:
Use the -rpath linker option. This option adds a path to the directories to be used during dynamic linking. As it is a linker option, you pass it through using -Wl,<option> when invoking the compiler, for example:
g++ ... -Wl,-rpath=/usr/local/lib64 .... You may also need to add the path using the -L option.
Set environment variable LD_LIBRARY_PATH at runtime
See also: compiler-libstdc-version-vs-system-version
Since you are using Centos, you may also want to check out the devtoolset collection, which allows a parallel installation of newer GCC toolsets.
This would indicate that this program I built using 5.4 is looking at the right (old) stdlib shared lib
... as far as I can see, that is the wrong library, isn't it? Because it the program is built with the new g++ version, it should be using the new libstdc++, i.e. the one in /usr/local/lib64/libstdc++.so.6.0.21.
So then you might need to prepend that path to LD_LIBRARY_PATH to be able to load the program.

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.

fixing boost shared library missing in linux

I am building a unix c++ program that calls boost, but when i try to run it i get
error while loading shared libraries: libboost_filesystem.so.1.42.0: cannot open shared object file: No such file or directory.
I didn't use to get this error before ( even though i was already calling boost ) , though i don't know what triggered the change. Anyway - doing ldd on the binary, it indeed shows that the library is missing.
I guess the solution would be to add in the LD_LIBRARY_PATH a link to the library containing the .so file - but i can't find it. Where should it be? Is this the right solution?
Note that i don't have sudo privelages on my computer, so i can only change user settings - And also that i'm a linux newb so please try to explain simply...
I think the problem is that you have linked to a very specific version of Boost (1.42.0 in this case). This worked as long as Boost existed in that exact version on your system, but as soon as an update to a more recent version of Boost happened, the linked library could no longer be found.
You might want to adjust your Makefile to link to a more generic version of libboost_filesystem.so.