I am trying to run an executable file - SaTScanBatch, executable of the SaTScan software - on a remote machine from the terminal.
Here is the error I get
/usr/lib64/libstdc++.so.6: version 'GLIBCXX_3.4.15' not found
The problem is similar to these:
/usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.15' not found or How to fix: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.15' not found or /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.15' not found
What is different in my case is that I do not have admin rights, so I cannot add libraries in usr/lib file. I downloaded libstdc++.6.0.15 in my remote repository, and I want to use it to execute my file.
Here are the possibilities I tried
i) Modify environment variable LD_LIBRARY_PATH or LD_RUN_PATH or LD_PRELOAD to the path of libstdc++.so.6.0.15.
--> Did not change anything
ii) Include the library in a static way
gcc SaTScanBatch -static-libstdc++
--> -static option is not recognized, I guess the remote machine's GCC version is too old.
iii) Try to link the file to the additional library:
gcc SaTScanBatch -L /path/library -l stdc++
or similarly
gcc SaTScanBatch -Wl,-rpath,path/to/library
--> Error
/usr/bin/ld: warning: Cannot create .eh_frame_hdr section, --eh-frame-hdr ignored.
/usr/bin/ld: error in SaTScanBatch64(.eh_frame); no .eh_frame_hdr table will be created.
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../lib64/crt1.o: In function _start:
(.text+0x20): undefined reference to "main"
collect2: ld returned 1 exit status
iv) Use PatchElf to link the file and the library --> I cannot install PatchElf because no admin rights
Thank you for any suggestion !
Modify environment variable LD_LIBRARY_PATH or LD_RUN_PATH or LD_PRELOAD to the path of libstdc++.so.6.0.15. --> Did not change anything
What exactly did you try?
LD_LIBRARY_PATH should be set to the directory containing the new libstdc++.so.6 not the the file itself, and you need to export the environment variable so it's available to child processes, not just to your shell. And you need a symlink from libstdc++.so.6 to libstdc++.so.6.0.15 because the dynamic loader is going to look for that name, not libstdc++.so.6.0.15
LD_RUN_PATH is used during linking to bake a path into the executable. It does nothing at run-time when trying to run the executable. If you use it you need to set it to the directory that will contain the libstdc++.so.6 file on the remote machine. Again, it needs to be set to a directory, not the path of the file.
LD_PRELOAD is something different again, and almost certainly not what you want. You would use it to force a particular shared library to be loaded before anything else when the executable runs. That can be used to pre-load a newer libstdc++ but it's usually better to use LD_LIBRARY_PATH to set a path at run-time or LD_RUN_PATH to set a path at link-time.
Try to link the file to the additional library:
The commands you showed are nonsense, they don't include any objects in the link, so you're trying to create an executable out of nothing. That's why you get the error undefined reference to "main"
For your scenario I would recommend using LD_LIBRARY_PATH.
Related
I'm trying to compile a program and during the configure checks one library cannot be found. Linking in my .bashrc file to this library with:
LD_LIBRARY_PATH=/usr/lib/:/users/much/needed/library/:$LD_LIBRARY_PATH:/path/to/other/libs/
export LD_LIBRARY_PATH
after that I source the .bashrc file with
source ~/.bashrc
and check with echo $LD_LIBRARY_PATH to see if the LD_LIBRARY_PATH contains the path to the library I need (and it's there).
However, when I run ./configure again - the same error appears. Do you have any hints as to what might be wrong here? I can't find any problem...
Could you try exporting LDFLAGS="-L/usr/lib/:/users/much/needed/library/" in addition to the LD_LIBRARY_PATH you mentioned?
LD_LIBRARY_PATH tells the loader where to find libraries when executing a binary at runtime, but the linker needs to find the required library at link time too.
Sounds like you need to run ldconfig to create the linker bindings. Add the directory to /etc/ld.so.conf and then run ldconfig (as root).
I have a directory with the following contents:
bin/busybox
lib/ld-linux.so.2
lib/libc.so.6
and when I invoke:
chroot . bin/busybox sh
it fails with the following:
/bin/busybox: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
When I move lib/libc.so.6 to usr/lib, it works fine.
Why is libc required to be in /usr/lib? When I invoke:
objcdump -p bin/busybox | grep NEEDED
I get:
NEEDED libc.so.6
So I thought, as only the soname of the library is used without slashes etc. the loaded will be able to find it in the standard folders, which is /lib and /usr/lib. Apparently, this is not the case.
To make matters even more confusing, ld-linux.so.2 seems to have to be in /lib because when it is moved to /usr/lib, chroot fails with:
chroot: failed to run command '/bin/busybox': No such file or directory
which I learned is actually an error that the loader cannot be found, not the busybox binary.
Is the issue with libc.so.2 distro specific? If this is important, I'm using Arch Linux.
The location of the loader (typically something like /lib/ld-linux.so) is hard-coded in the binary. There's no search process for this component — if it cannot be found, the binary won't run at all.
(The exact path depends on what libc and architecture you're using. It's at /lib64/ld-linux-x86-64.so.2 for glibc on x86_64, for instance.)
The locations that will be searched for dynamic libraries are configurable in /etc/ld.so.conf. If you don't have that file in the chroot, though, some of the standard paths may not be configured!
I'm using eclipse cdt to compile and run C++ application.
My_main_program needs specifically libjpeg.so.62.
My Ubuntu system previously have libjpeg.so.9 at /usr/local/lib/. I happened to compiled and run using libjpeg.so.9 before run-time compatibility errors was raised.
Then I deleted all libjpeg.* and installed libjpeg.la, libjpeg.so, libjpeg.so.62 and libjpeg.so.62.0.0 from source. Then I run ldconfig.
I can build the project. The problem is the dynamic linker keeps searching for libjpeg.so.9 and throwing
'error while loading shared libraries: libjpeg.so.9: cannot open shared object file: No such file or directory'
at run-time.
This problem is killing me.
I have checked that the symlink of libjpeg.so is correct.
Please help!
I can build the project. The problem is the dynamic linker keeps searching for libjpeg.so.9 and throwing
'error while loading shared libraries: libjpeg.so.9: ... No such file ...
You need to understand a couple of things:
A shared library may have SONAME dynamic tag (visible with readelf -d foo.so | grep SONAME).
If an executable is linked against such a library, the SONAME is recorded as a NEEDED dynamic tag (in the executable), regardless of what the library itself is called. That is, you can name the library foo.so, foo.so.1234, or anything else. IF the library has SONAME of libbar.so.7, then the executable will require libbar.so.7, no matter what [1].
On to your problem. Your executable fails to load libjpeg.so.9, therefor we conclude that it is being linked (at build time) with a shared library which has SONAME: libjpeg.so.9.
I deleted all libjpeg.* and installed libjpeg.so.62
You must not have deleted the libjpeg.so that is used at executable build time (which is somewhere other than /usr/local/lib). That library still has SONAME: libjpeg.so.9, and is causing you grief.
You can find out which libraries are being used at link time by passing -Wl,-t flag on the link line.
[1] Not strictly true: if the executable doesn't need any symbols from foo.so, and if --as-needed linker option is in effect, then NEEDED: libbar.so.7 will not be recorded after all.
Update:
I have also check ldd executable and it returns libjpeg.so.62
This means that the executable that you run ldd on is correct, but the executable that actually run is not, and they must be different executables.
Update 2:
You're right. ldd executable shows both libjpeg.so.62 and libjpeg.so.9 are included
Actually, no, I wasn't. But I will be right this time.
What's happening is that your executable correctly records NEEDED: libjpeg.so.62 (you can verify this with the following command: readelf -d /path/to/exe | grep 'NEEDED.*libjpeg').
But you also have some other shared library (one of the ones listed in ldd output), which has not been rebuilt, and still has a dependency on libjpeg.so.9.
You can find that library by running readelf -d /path/to/libXXX.so | grep 'NEEDED.*libjpeg\.so\.9' on all libraries listed in ldd output.
Once you find it, you'll have to rebuild it so it also depends on libjpeg.so.62.
The problem I faced has been solved here:
Loading shared library in open-mpi/ mpi-run
I know not how, setting LD_LIBRARY_PATH or specifying -x LD_LIBRARY_PATH fixes the problem, when my installation itself specifies the necessary -L arguments. My installation is in ~/mpi/
I have also included my compile-link configs.
$ mpic++ -showme:version
mpic++: Open MPI 1.6.3 (Language: C++)
$ mpic++ -showme
g++ -I/home/vigneshwaren/mpi/include -pthread -L/home/vigneshwaren/mpi/lib
-lmpi_cxx -lmpi -ldl -lm -Wl,--export-dynamic -lrt -lnsl -lutil -lm -ldl
$ mpic++ -showme:libdirs
/home/vigneshwaren/mpi/lib
$ mpic++ -showme:libs
mpi_cxx mpi dl m rt nsl util m dl % Notice mpi_cxx here %
When I compiled with mpic++ <file> and ran with mpirun a.out I got a (shared library) linker error
error while loading shared libraries: libmpi_cxx.so.1:
cannot open shared object file: No such file or directory
The error has been fixed by setting LD_LIBRARY_PATH. The question is how and why? What am i missing? Why is LD_LIBRARY_PATH required when my installation looks just fine.
libdl, libm, librt, libnsl and libutil are all essential system-wide libraries and they come as part of the very basic OS installation. libmpi and libmpi_cxx are part of the Open MPI installation and in your case are located in a non-standard location that must be explicitly included in the linker search path LD_LIBRARY_PATH.
It is possible to modify the configuration of the Open MPI compiler wrappers and make them pass the -rpath option to the linker. -rpath takes a library path and appends its to a list, stored inside the executable file, which tells the runtime link editor (a.k.a. the dynamic linker) where to search for libraries before it consults the LD_LIBRARY_PATH variable. For example, in your case the following option would suffice:
-Wl,-rpath,/home/vigneshwaren/mpi/lib
This would embed the path to the Open MPI libraries inside the executable and it would not matter if that path is part of LD_LIBRARY_PATH at run time or not.
To make the corresponding wrapper add that option to the list of compiler flags, you would have to modify the mpiXX-wrapper-data.txt file (where XX is cc, c++, CC, f90, etc.), located in mpi/share/openmpi/. For example, to make mpicc pass the option, you would have to modify /home/vigneshwaren/mpi/share/openmpi/mpicc-wrapper-data.txt and add the following to the line that starts with linker_flags=:
linker_flags= ... -Wl,-rpath,${prefix}/lib
${prefix} is automatically expanded by the wrapper to the current Open MPI installation path.
In my case, I just simply appends
export LD_LIBRARY_PATH=/PATH_TO_openmpi-version/lib:$LD_LIBRARY_PATH
For example
export LD_LIBRARY_PATH=/usr/local/openmpi-1.8.1/lib:$LD_LIBRARY_PATH
into $HOME/.bashrc file and then source it to active again source $HOME/.bashrc.
I installed mpich 3.2 using the following command on Ubuntu.
sudo apt-get install mpich
When I tried to run the mpi process using mpiexec, I got the same error.
/home/node1/examples/.libs/lt-cpi: error while loading shared libraries: libmpi.so.0: cannot open shared object file: No such file or directory
Configuring LD_LIBRARY_PATH didn't fix my problem.
I did a search for the file 'libmpi.so.0' on my machine but couldn't find it. Took me some time to figure out that 'libmpi.so.0' file is named as 'libmpi.so' on my machine. So I renamed it to 'libmpi.so.0'.
It solved my problem!
If you are having the same problem and you installed the library through apt-get, then do the following.
The file 'libmpi.so' should be in the location '/usr/lib/'. Rename the file to 'libmpi.so.0'
mv /usr/lib/libmpi.so /usr/lib/libmpi.so.0
After that MPI jobs should run without any problem.
If 'libmpi.so' is not found in '/usr/lib', you can get its location using the following command.
whereis libmpi.so
first, run this command
$ sudo apt-get install libcr-dev
if still have this problem then configure LD_LIBRARY_PATH like this:
export LD_LIBRARY_PATH=/usr/local/mpich-3.2.1/lib:$LD_LIBRARY_PATH
then add it to ~/.bashrc before this line:
[ -z "$PS1" ] && return
Simply running
$ ldconfig
appears to me as a better way to solve the problem (taken from a comment on this question). In particular, since it avoids misuse of the LD_LIBRARY_PATH environment variable. See here and here, for why I believe it's misused to solve the problem at hand.
I have the following warning during link:
/usr/bin/ld: warning: libxxx.so.6, needed by /a/b/c/libyyy.so, not found (try using -rpath or -rpath-link)
Setting environment variable LD_LIBRARY_PATH=path_to_libxxx.so.6 silence the warning (adding -Lpath_to_libxxx.so.6 doesn't help).
I have a separate compilation server, where the resulting binary is only compile.
The binary is executed on other server and there the libxxx.so.6 is seen by the binary (checked with ldd executable).
Is there're other way to get rid of the warning at compilation time (I have it several times and it's very annoying)?
You need to add the dynamic library equivalent of -L:
-Wl,-rpath-link,/path/to/lib
This will cause the linker to look for shared libraries in non-standard places, but only for the purpose of verifying the link is correct.
If you want the program to find the library at that location at run-time, then there's a similar option to do that:
-Wl,-rpath,/path/to/lib
But, if your program runs fine without this then you don't need it.
Make sure the paths to the needed libraries are known to the runtime linker. This is done by adding a file in /etc/ld.so.conf.d/ with the needed path. For example, /etc/ld.so.conf.d/foo with the following contents:
/usr/local/lib/foo/
If you have a very old Linux version, /etc/ld.so.conf.d/ might not be supported, in which case you might have to add the paths directly into the /etc/ld.so.conf file.
After you've done that, you need to update the linker's database by executing the "ldconfig" command.
I know this is old, but here's a better fix:
The root cause:
The problem actually happens when LD invoked by GCC starts resolving
library dependencies. Both GCC and LD are aware of the sysroot
containing libraries, however LD may be missing one critical
component: the /etc/ld.so.conf file. Here’s an exampleld.so.conf file
from a Raspberry PI system:
include /etc/ld.so.conf.d/*.conf
The /etc/ld.so.conf.d directory contains the following files:
00-vmcs.conf:
/opt/vc/lib
arm-linux-gnueabihf.conf:
/lib/arm-linux-gnueabihf /usr/lib/arm-linux-gnueabihf
libc.conf:
/usr/local/lib
The universal solution
The problem can be easily solved by copying the LD configuration files
to a location where the cross-toolchain’s LD can find them. There’s
one pitfall however: if your cross-toolchain was built with MinGW
(most are), it probably did not have access to the glob() function so
it won’t be able to parse a wildcard-enabled include statement
like *.conf. The workaround here is to just manually combine the
contents of all .conf files from /etc/ld.so.conf.d and paste them
into /etc/ld.so.conf
*/opt/vc/lib
/lib/arm-linux-gnueabihf
/usr/lib/arm-linux-gnueabihf
/usr/local/lib*
Once you create the ld.so.conf file in the correct folder, your
toolchain will be able to resolve all shared library references
automatically and you won’t see that error message again!
The only way to silence these warning using command line options would be the -L flag which curiously does not work for you (maybe you can post more details on this). Since the warning is generated by ld we could try to use -Wl,option to disable a linker warning but from the documentation of GNU ld however there is no option for (de)activating this warnings.
So this leaves us with writing a wrapper script filtering out this warning or compile a custom version of ld.