A while back, I decided to upgrade to GCC 4.8 in order to get an early start on some c++11 features. I got a bit sidetracked, though, and didn't really put any of the new features to use until a project a few days ago (the new compiler seemed to have been working fine, but it may just be because I wasn't utilizing any new functionality.)
In this new project, when I compiled with the =std=c++11 flag, I had no problems. However, at runtime, I get the error:
./main: /usr/lib/i386-linux-gnu/libstdc++.so.6: versionGLIBCXX_3.4.18' not found (required by ./main)`
I assume that there is a problem linking to a more modern libstdc++ library associated with GCC 4.8, but I can't for the life of me figure out how to fix this or where the appropriate library should be. I remember symbolically linking the g++ and gcc binaries to gcc-4.8, which appears to be working, since g++ -v returns:
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/app/gcc/4.8.0/libexec/gcc/i686-pc-linux-gnu/4.8.0/lto-wrapper
Target: i686-pc-linux-gnu
Configured with: ./gcc-4.8.0/configure --prefix=/app/gcc/4.8.0
Thread model: posix
gcc version 4.8.0 (GCC)
Another thread online led me to look at the ldd output for the program, which did show me that the directory structure for the libstdc++ libraries being linked to was different than the directory structure for the binaries. I couldn't, however, find the appropriate libstdc++ libraries in the latter, so I'm not sure where to look. The output for ldd main is:
./main: /usr/lib/i386-linux-gnu/libstdc++.so.6: versionGLIBCXX_3.4.18' not found (required by ./main)
linux-gate.so.1 => (0xb7791000)
libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xb768e000)
libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb7662000)
libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xb7644000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb749b000)
/lib/ld-linux.so.2 (0xb7792000)`
I'm not sure exactly where this is going wrong, and I'll continue Googling and looking around for answers, but any help you guys could offer would be greatly appreciated. If anything is unclear about the issue or I forgot some information, just let me know and I'll try to add that in. Thanks so much!
You need to tell your dynamic linker (it's executed when you run your program) where to find the library. Set LD_LIBRARY_PATH to the path of the library (probably somewhere under /app/gcc/4.8.0/lib or something).
Use find /app/gcc/4.8.0 -name "libstdc++.so.6". Add the directory to your LD_LIBRARY_PATH. e.g with the path I mentioned:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/app/gcc/4.8.0/lib (if you're using a bourne-like shell which the default on Linux).
Then try to run your program.
If it works, you'll probably want to configure your dynamic linker to look in the directory without using LD_LIBRARY_PATH. See man ld.so for details about how to configure the path.
Related
Recently I struggled porting an existing C++ application onto a new production environment (updated kernel, updated glibc, etc). Even though the output of ldd showed that all my .so were found, including the ELF interpreter, the execution always resulted on a "No such file or directory".
$ ldd my_app
libpthread.so.0 => /lib/libpthread.so.0 (0x00007fd41afd6000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007fd41ae52000)
libm.so.6 => /lib/libm.so.6 (0x00007fd41ad11000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007fd41acf7000)
libc.so.6 => /lib/libc.so.6 (0x00007fd41ab3a000)
/lib64/ld-linux-x86-64.so.2 => /lib/ld-linux-x86-64.so.2 (0x00007fd4258b5000) <= ELF Interpreter
libconfig.so.9 => /usr/lib/libconfig.so.9 (0x00007fd41ab2c000)
libsensors.so.4 => /usr/lib/libsensors.so.4 (0x00007fd41ab1b000)
$ file my_app
ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=c8c7eeb2f6bdb96dab7b0cc9ad41aa6e3d610ec7, stripped
$ readelf -a my_app | grep "interpreter"
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
I didn't think my problem had anything to do with the interpreter because of this output of ldd. So I tried all other possible workarounds with no success. After much digging online I encountered a related problem that the solution suggested the creation of a symlink from the application's hard-coded path for the interpreter to the real path one. In my case:
ln -s /lib/ld-2.29.so /lib64/ld-linux-x86-64.so.2
This finally resolved the problem. At the end I was frustrated since I wasn't looking for the real problem and it took me too long to realize it because of the misleading output of ldd.
Why does ldd say that the interpreter is there even though it will not be loaded when you run the binary? Is my interpretation of the use/output of ldd mistaken?
onto a new production environment
Your new production environment installed ld-linux-x86-64.so.2 into /lib instead of /lib64. This is highly unusual and non-standard. Many binaries will fail to run on such a system. Whoever "made" this system, probably made a grave mistake.
Why does ldd say that the interpreter is there
The way ldd works is: it sets an environment variable LD_TRACE_OBJECTS=1 and invokes the real interpreter it was compiled with.
Since your system (erroneously) installed ld-linux into /lib, ldd dutifully invoked /lib/ld-linux-x86-64.so.2, which does exist, and actually told you so.
In general, ldd is not trustworthy, especially when several versions of GLIBC are installed on a single system.
In glibc, the dynamic loader ld.so. is both used as the program interpreter and as a loaded shared object. ldd only displays the latter. It can find ld.so because it is either on the search path or in the ld.so cache. In contrast, when the kernel tries to load the program interpreter, it only uses the exact path specified in the program, so search paths and the like do not apply.
The correct path according to the ABI manual is /lib64/ld-linux-x86-64.so.2. If your system does not have that, it does not follow the GNU/Linux x86-64 ABI, which is rather odd.
I have an issue which sounds annoyingly simple, but I feel I've tried everything to resolve it and I'm out of ideas.
I have a program I wrote which uses boost/program_options.hpp using the include statement
#include <boost/program_options.hpp>
This program works on my laptop and now I am trying to put it onto a server where I don't have sudo privileges. On my laptop, where the whole thing works I have boost versions 1.56 and 1.58 and on the server I found 1.53.0. I didn't install or build this though.
The shared library file that exists on the server is:
/usr/lib64/libboost_program_options.so.1.53.0
Running ldd on that gives me the output:
ldd /usr/lib64/libboost_program_options.so.1.53.0
linux-vdso.so.1 => (0x00007ffc54a63000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fc0dcad8000)
libm.so.6 => /lib64/libm.so.6 (0x00007fc0dc7d5000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fc0dc5bf000)
libc.so.6 => /lib64/libc.so.6 (0x00007fc0dc1fe000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc0dd071000)
Which I assume means it's found all its dependencies.
I have made a symbolic link to my home directory to create a libboost_program_options.so link, which I guess means the -lboost_program_options linker flag should work.
The way I compile is by:
g++ -L/home/homeDir code.cpp -o code.o -std=c++11 -Wall -lboost_program_options
And all I get is:
fatal error: boost/program_options.hpp: No such file or directory
#include "boost/program_options.hpp"
^
compilation terminated.
I've tried this with quotes and <>, and without "boost/" etc, but I always get the same complaint. I assume this means that it finds the library as there is no complaint about the -lboost_program_options flag?
While it works on my machine, I may not be using the shared program options library at all. On my laptop I have both a static version of libboost_program_options in my library path which it may be using, and the program_options.hpp header outside of a library which may be in my include path. I feel like I should be able to use the shared library that's on the server and not annoy the server admin for the 5th time (things work really slowly with these things here).
I'm sorry if this is my oversight. I'm fairly new to boost, but I feel like I've tried everything to resolve this myself at the moment.
I'd be happy with any suggestions as to how I could change this... or if I'm just being a bit stupid with using shared libraries.
Thanks in advance.
EDIT:
After more research I feel like I'm just getting confused between static and shared libraries. I'm trying to link a shared library at compile time, which I guess doesn't make sense. Also including the header file of something which should not be linked at compile time makes little sense. My code is clearly designed for the static library.
The error message is produced by the pre-compiler which does not find the Boost header file (as it says in the error message). You need to set the correct include path (-I...) where the Boost library header files are found, obviously they are not under /usr/include.
Path to the Boost libraries (-L...) must be specified accordingly.
Finally: If you are linking against the Boost shared libraries on your system, then you should use the same version of Boost as installed on the server. Otherwise, link against the static libraries, this may make you executable larger, but it will run on any server, regardless of the Boost version installed there (even none).
sudo apt install libboost-program-options-dev
I am working on a project which I would like to be able to "ship" to other Linux based computers as a complete executable with no dependencies. (In order that I can copy just the 1 file to other systems, and then run that file on those systems.)
In the windows world, I think static linking is done just by passing -static to the compiler, perhaps with some other options for specific libraries*, if you are using Visual Studio.
*eg: Using SFML you also have to define SFML_STATIC for some reason?
Is this possible using gcc / g++, and if so how? I tried searching for this but didn't manage to find anything. I have heard before that this may be a non-trivial task.
Edits:
BasileStarynkevitch suggested compiling with the flag -static.
I don't know if this is what I want, but I wrote a test program to try it out:
#include <iostream>
int main()
{
std::cout << "Link statically please" << std::endl;
return 0;
}
And then compiled with:
g++ main.cpp -o a.out -static
g++ main.cpp -o b.out
The results are:
-rwxr-xr-x 1 1653098 a.out
-rwxr-xr-x 1 9167 b.out
So it looks like it might be working?
TonyD suggested a method of checking:
ldd a.out
not a dynamic executable
ldd b.out
linux-vdso.so.1 => (0x00007fff3d5ac000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fce5e34a000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fce5df85000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fce5dc7e000)
/lib64/ld-linux-x86-64.so.2 (0x00007fce5e677000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fce5da67000)
Is it possible to compile statically with gcc or g++ on Linux based systems?
It depends.
You might try to compile and link all your code with gcc -static or g++ -static. In several cases (e.g. pure command-line applications, like your hello world), it would work.
Linux distributions like a lot shared libraries. Most of them are using shared libraries extensively (notably for graphical applications). Read Drepper's How to Write Shared Libraries paper for more.
You might have some licensing issues. To simplify outrageously, it might be illegal (against the LGPL license) to ship code statically linked to some LGPL (or GPL) library. The evil is in the details.
Some core features, notably DNS related (e.g. getaddrinfo(3) & getnameinfo(3)) are internally using plugin techniques à la dlopen(3), so sort-of requires a dynamic libc.so (see nsswitch.conf(5) for more).
Some X11 things, in particular font related, are also expecting plugin related things (IIRC, Xft); perhaps SFML uses them. BTW, SFML is very probably installed as shared libraries, so you'll need to rebuild SFML from source code...
At last, a statically linked program might be more tied to some particular kernel version that a dynamically linked one (in principle, this is not the case). It might happen that you could have incompatibilities with very old or future kernels (but usually not).
See also ldd(1), file(1), pmap(1), proc(5), vdso(7)
It might be actually simpler to ship the source code to the target system, ask the sysadmin to install required dependencies, and build your code on the remote target (e.g. using ssh)
You could try to link statically most libraries but not all (e.g. link statically libstdc++.a and dynamically libc.so) by playing with GCC linking options. See this & that
Perhaps you'll first should try to link statically some SFML demo.... or simply scp your (dynamically linked) binary program and try to run it remotely (it might be able to run).
Compiling with -static appears to work for basic c++ programs, probably all of the standard library?
However when using with other libraries, this may no longer work.
This may be a stupid question, but if I compile a shared library using g++ on one distribution of Linux, and then move those libraries as object files via flash drive to another computer with the exact same Linux distro and version of g++ will I still be able to link those libraries in my source files on the second machine?
I'm asking because I don't have the permissions to install the necessary libraries before compiling on the second machine, so it'd be easier for me to just compile them on my own computer and upload the compiled object files via flash drive to the second machine
Let me explain you with some example.
suppose i have binary named myapp in my machine X and i want to run it in another machine Y but when i run then it show me some error like
./myapp: error while loading shared libraries: libcgicc.so.5: cannot open shared object file: No such file or directory
This means I’m using a library that isn’t on the other machine. Of course, I could try installing all the same libraries on Y as there are on X. But i have't permission to do. Then our alternative is to statically link libraries with our program.
On Y, run the command ldd myapp. This will give something like:
libpthread.so.0 => /lib/tls/libpthread.so.0 (0xf7f77000)
libdl.so.2 => /lib/libdl.so.2 (0xf7f73000)
libgd.so.2 => /usr/lib/libgd.so.2 (0xf7f26000)
libcgicc.so.5 => not found <------------------------------------//this library missed
libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0xf7f08000)
libpng12.so.0 => /usr/lib/libpng12.so.0 (0xf7ee4000)
Let’s go back to our compiling machine, machine X, and see what ldd myapp says there for libcgicc:
libcgicc.so.5 => /usr/lib/libcgicc.so.5 (0xb7f18000)
So on machine X, the library we want is in /usr/lib. If we do ls /usr/lib/libcgicc* we can see what versions of this library are available. On machine that is:
/usr/lib/libcgicc.a
/usr/lib/libcgicc.la
/usr/lib/libcgicc.so
/usr/lib/libcgicc.so.5
/usr/lib/libcgicc.so.5.0.1
So there is a static version available,libcgicc.a. If there were not a .a version, we would need to get one - on debian/ubuntu we could track it down by doing (as superuser):
apt-file search libcgicc.a
Now, all we need to do is relink our program, replacing -lcgicc with /usr/lib/libcgicc.a. Now when we do ldd myapp on either machine, we have no more missing libraries.
However, that doesn’t guarantee all libraries are exactly the same version. A frequent problem is libstdc++ for C++ code. If you see a message like this when trying to run your code:
./myapp: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.9′ not found (required by ./myapp)
Then you’ve got a version mismatch. This may be fixable by statically linking the libstdc++ library. Check what version of g++ you are using with g++ –version, and then check for libstdc++.a in:
/usr/lib/gcc/[platform-name]/[version]
(location may be different on your computer). Once you track this file down you can link it statically as before.
I have a requirement that I link all my libraries statically including libstdc++, libc, pthread etc. There is one omniorb library which I want to link dynamically.
Currently I have dynamically linked all the libraries.
ldd shows the following
linux-vdso.so.1 => (0x00007fff251ff000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f291cc47000)
libomniDynamic4.so.1 (0x00007f291c842000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f291c536000)
libm.so.6 => /lib64/libm.so.6 (0x00007f291c2e0000)
libgomp.so.1 => /usr/lib64/libgomp.so.1 (0x00007f291c0d7000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f291bebf000)
libc.so.6 => /lib64/libc.so.6 (0x00007f291bb66000)
/lib64/ld-linux-x86-64.so.2 (0x00007f291ce63000)
librt.so.1 => /lib64/librt.so.1 (0x00007f291b95d000)
libomniORB4.so.1 (0x00007f291b6aa000)
libomnithread.so.3 (0x00007f291cf35000
I need ldd to show libomniDynamic4.so.1 as the only dynamically linked library.
How do I achieve this?
Trying to make a linux executable that runs on all distros eh? Good luck...But I digress...
You want to look at the -v flag output for g++. It shows the internal link commands executed by g++/ld. Specifically, you'll want to inspect the the final link command collect2 and all of its arguments. You can then specify the exact paths to the .a libs you want to link against. You'll also have to track down static libs of everything. My libstdc++.a is in /usr/lib/gcc/x86_64-linux-gnu/4.4/libstdc++.a
rant on: My biggest complaint about linux is the fractured state of executables. Why cant I compile a binary on one machine and copy it to another and run it!? Even the Ubuntu distros one release apart will produce binary files that cannot be run on the other due to libc/libstdc++ ABI incompatibilites
edit #1 I just wanted to add that The script on this page produces a .png of an executables .so dependencies. This is very useful when attempting to do what you describe.
Be aware ldd <exename> will list all dependencies down the chain, not just immediate dependencies of the executable. So even if your executable only depended upon omniorb.so, but omniorb.so depended upon, libphread.so, ldd's output would list that. Look up the manpage of readelf to find only the immediate dependencies of a binary.
One other item that to be aware of. if omniorb.so depends upon libstdc++.so, you'll have no choice but to be dependant on that same lib. Otherwise ABI incompatibilities will break RTTI between your code and omniorb's code.
I need ldd to show libomniDynamic4.so.1 as the only dynamically linked library.
That is impossible.
First, ldd will always show ld-linux-x86-64.so.2 for any (x86_64) binary that requires dynamic linking. If you use dynamic linking (which you would with libomniDynamic4.so.1), then you will get ld-linux-x86-64.so.2.
Second, linux-vdso.so.1 is "injected" into your process by the kernel. You can't get rid of that either.
Next, the question is why you want to minimize use of dynamic libraries. The most common reason is usually mistaken belief that "mostly static" binaries are more portable, and will run on more systems. On Linux this is the opposite of true.
If in fact you are trying to achieve a portable binary, several methods exist. The best one so far (in my experience) has been to use apgcc.
It is very difficult to build a single binary that runs on a lot of Linux distros and linking statically is not the key point.
Please note that a binary built with an older glibc version--i.e., an old Linux distro--may run on newer Linux distros as well. This works because glibc is back-compatible.
A possible way to attain the desired result is:
compile the binary on an old Linux OS
find out all the required libraries for your compiled binary using the command ldd or lsof
(when running) on the binary, details here
copy the required libraries of the old Linux OS in a 'custom-lib' folder
always bundle/release this custom-lib folder with your binary
create a bash script that puts the custom-lib folder on top of the folders list in LD_LIBRARY_PATH environment variable, and then invokes your binary.
In this way, by executing the binary with the bash script, I was able to execute binaries on a wide range of embedded devices with very different Linux versions.
But there are always problematic cases where this fails.
Please note, I always tested this with cli applications/binaries.
Other possible ways..
There also seems to be elegant ways to compile glibc-back-compatible binaries, for example this that seems to compile binaries compatible with older ABI. But I have not checked this route.
when linking, use -static before specifying the libraries you want to link statically to, and use -dynamic before the libraries you want to link dynamically to. You should end up with a command line looking like this:
g++ <other options here> -dynamic -lomniDynamic4 -static -lpthread -lm -lgomp <etc>
Of course, you'll need .a versions of the libraries you want to link statically (duh).