how to link shared library from non existing(in compile time) folder - c++

i'm trying to link shared library to another shared library(protobuf) with -rpath option, the problem is that the lib is in another direcory in compile time than in runtime, and -rpath option requires an existing in compile time path. (so i get an "No such file or directory" error)
Is there any workaround for that?
I would rather not to use LD_LIBRARY_PATH variable to solve this problem.

-rpath specifies the runtime library search path.
Here is a quoate from the link Program Library HOWTO
"
During development, there's the potential problem of modifying a library that's also used by many other programs -- and you don't want the other programs to use the developmental''library, only a particular application that you're testing against it. One link option you might use is ld'srpath'' option, which specifies the runtime library search path of that particular program being compiled. From gcc, you can invoke the rpath option by specifying it this way:
-Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)
If you use this option when building the library client program, you don't need to bother with LD_LIBRARY_PATH (described next) other than to ensure it's not conflicting, or using other techniques to hide the library. "

I found an answer here Can I change 'rpath' in an already compiled binary?
Changing rpath after compilation solves my problem.
[edited]
There is another, better approach: how to link to shared lib from shared lib with relative path

Related

How to prefer one library location vs. another one with Clang?

I have a system-wide libc++.so in /usr/lib64. I want to link my binary against another libc++.so which is located somewhere else, say, in $HOME/.local/lib. Also, I want to be able to find all other libraries the same way as before, assuming that $HOME/.local/lib contains only libc++.so.
I'm trying to do this like: clang++ -L$HOME/.local/lib -lc++, but the compiler still links against /usr/lib64/libc++.so.
How to force the compiler (or linker) to link against a specific library location?
-L adds the directory to the search path used by the linker. This has no effect on the search paths used at runtime. At runtime, the search paths, in order, are:
The environment variable LD_LIBRARY_PATH
rpath specified in the executable
System library path
While you can achieve what you want by specifying the environment variable LD_LIBRARY_PATH=$HOME/.local/lib, it is a bad solution since it modifies the search paths of all executables. Specifying the rpath is a much cleaner solution since it only affects the behaviour of your executable. You can do this through the linker option of your toolchain, which is likely -rpath. So the command would be clang++ -rpath $HOME/.local/lib -lc++.

Linking libraries in c++

I have a C++ file a.cpp with the library dependency in the path /home/name/lib and the name of the library abc.so.
I do the compilation as follows:
g++ a.cpp -L/home/name/lib -labc
This compiles the program with no errors.
However while running the program, I get the ERROR:
./a.out: error while loading shared libraries: libabc.so.0: cannot open shared object file: No such file or directory
However if before running the program, I add the library path as
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/name/lib;
and compile and run now, it works fine.
Why am I not able to link the library by giving it from the g++ command?
Because shared object libraries are linked at runtime - you either need to add the location to the library search path (as you've done), place it somewhere within an already existing path (like /usr/lib), or add a symbolic link to an existing library path that links to the location where it exists.
If you want to compile the library in so there is no runtime dependency, you'll need a static library (which would be abc.a) - note that this has numerous downsides, however (if the library is updated, you'll need to recompile your executable to incorporate that update).
Why am I not able to link the library by giving it from the g++ command?
You are able to link, and you did link the library succesfully. Otherwise you would not be able to build executable (in your case a.out). The problem you mixed 2 different things: linking with shared libraries and loading them at runtime. Loading shared libraries is a pretty complex concept and described pretty well here Program-Library-HOWTO read from 3.2.
You are linking dynamically, is the default behavior with GCC. LD_LIBRARY_PATH is used to specify directories where to look for libraries (is a way of enforce using an specific library), read: Program-Library-HOWTO for more info. There is also an ld option -rpath to specify libraries search path for the binary being compiled (this info is written in the binary and only used for that binary, the LD_LIBRARY_PATH affect other apps using the same library, probably expecting a new or old version).
Linking statically is possible (but a little tricky) and no dependency would be required (but sometimes is not recommended, because prevent the update of the dependent libraries, for example for security reason, in static linking your always are using the versions of the libraries you have when compiled the binary).

libgomp.so.1: cannot open shared object file

I am using OpenMP in my C++ code.
The libgomp.so.1 exists in my lib folder. I also added its path to the LD_LIBRARY_PATH
Still at run-time I get the error message: libgomp.so.1: cannot open shared object file
At Compile time I compile my code with -fopenmp option.
Any idea what can cause the problem?
Thanks
Use static linking for your program. In your case, that means using -fopenmp -static, and if necessary specifying the full paths to the relevant librt.a and libgomp.a libraries.
This solves your problem as static linking just packages all code necessary to run you program together with your binary. Therefore, your target system does not need to look up any dynamic libraries, it doesn't even matter if they are present on the target system.
Note that static linking is not a miracle cure. For your particular problem with the weird hardware emulator, it should be a good approach. In general, however, there are (at least) two downsides to static linking:
binary size. Imagine if you linked all your KDE programs statically, so you would essentially have hundreds of copies of all the KDE/QT libs on your system when you could have just one if you used shared libraries
update paths. Suppose that people find a security problem in a library x. With shared libraries, it's enough if you simply update the library once a patch is available. If all your applications were statically linked, you would have to wait for all of these developers to re-link and re-release their applications.

Compiled C++ program raises "cannot open shared object file" on another system though the file is present

I wrote a tiny program that requires some libraries including libboost_filesystem, libboost_program_options and libcurl.
I compiled it on my home machine and took the binary to my computer at work to test it there. But there it gives the following error message when I try to start the program:
error while loading shared libraries:
libboost_filesystem.so.1.42.0: cannot
open shared object file
But when I search for this file I see that it exists in:
/usr/lib/libboost_filesystem.so.1.42.0
Did I something wrong during the compilation / linking of my program? If yes what do I have to do to make it work on other machines?
First, try to issue ldconfig -p | grep libboost_filesystem.so in a console to make sure the library is in your ld cache.
If it is not, you may need to add a file with a name like boost.conf to your /etc/ld.so.conf.d directory. This file should contain a path to your boost libraries. Then run sudo ldconfig to update your system's ld cache.
Hope this will help...
Looks like you need to statically link the library. Here's a good explanation. Boost static linking
Did you link against the same version of the boost_filesystem library? Depending on how you compile your application, it requires the very same version of the library to be present.
You could try to check for what your application actually looks for with:
ldd <your app name>
Probably check your LD_LIBRARY_PATH environment variable as well.
Could you make sure that /usr/lib/libboost_filesystem.so.1.42.0 is not a dead link ?
Did you compile the shared binaries of boost and provided them to the user?
Often boost can be used without any binary/shared to provide. But if you use, for example, boost::filesystem, you'll have to build the binaries, as lib or shared object, and make sure it's available to the final executable shared binary search path.
You can find an explaination and more details in the boost documentation. Here is the linux version : http://www.boost.org/doc/libs/1_44_0/more/getting_started/unix-variants.html
From this page :
Most Boost libraries are header-only:
they consist entirely of header files
containing templates and inline
functions, and require no
separately-compiled library binaries
or special treatment when linking.
...
The only Boost libraries that must be
built separately are:
Boost.Filesystem
Boost.GraphParallel
Boost.IOStreams
Boost.MPI
Boost.ProgramOptions
Boost.Python (see
the Boost.Python build documentation
before building and installing it)
Boost.Regex
Boost.Serialization
Boost.Signals
Boost.System
Boost.Thread
Boost.Wave
is /usr/lib in your LD_LIBRARY_PATH environment variable?

In linux how can I tell if I'm linking to a static or dynamic library?

I have a static and a dynamic library with the same name: libclsocket.a and libclsocket.so When I specify what library I want to link to i simply enter -lclsocket as the library. My program complies and runs perfectly fine, but what library am I using? the static library or the dynamic library? I want to give my friend my program, and I'm not sure If i need to include the libraries in the release. C++, codelite, pcLinuxOS 2010
You can try running ldd on the executable and seeing if the accompanying .so is being detected as required in the list of dependencies.
ldd man page is here.
If you use the -static flag, all components will be made static. And -l may include shared libraries. So specifying the static library filename (e.g. with /usr/lib/libfoo.a for example, no -l prepended), should get you the desired effect.