C++ shared libraries - c++

I am trying to get my head around the way shared libraries work in the c++ unix environment. I understand we only need header files and no shared libraries specification when compiling code. But if I want to create an executable or shared library from my compiled files, do I need to specify shared library dependencies (those are dynamic)? And do the paths of shared libraries need to match the path at runtime loading?
I am using Linux 2.6.18-164.11.1.el5 #1 SMP x86_64 GNU/Linux
I am having a problem where my code is not able to pick up a library at runtime. I have tried setting LD_LIBRARY_PATH and PATH. But at runtime when I run the executable, I get the following error:
Error: librc.so: cannot open shared object file: No such file or directory
Sam

The headers are only for the compile phase. At link time, you usually have to specify which shared libs you are going to link to. You might see -L options to set locations to where shared libraries reside, and/or -l to specify which libraries to link. There is usually also a switch on the command line to alert the linker as to whether you are using thread-safe versions of the libs or the 'regular' ones, and another switch to specify dynamic linking.
At run time, whether you are starting the program that uses the libs, or running ldd to find out what it needs, the OS has a system for locating .so files, and this can vary from one unix version to another. The LD_LIBRARY_PATH variable specifies where to look for .so files, but may not be the full story, depending on the exact unix version in question. Also, you probably don't want to fiddle around with modifying LD_LIBRARY_PATH except from a throw-away shell, since it has system wide effects. A better option is to check it the 'missing' .so files are or are not on the existing path set by LD_LIBRARY_PATH, and if not, try putting copies of them somewhere on that path.

At run time, dynamic libraries are searched:
in a path recorded in the executable (under linux with -rpath at link time, under Solaris with -R, using $ORIGIN in a directory name allows to specify a directory relative to the directory containing the executable)
in the LD_LIBRARY_PATH (or equivalent, there are sometimes 64/32 bits variant). If a path has been recorded in the executable, LD_LIBRARY_PATH may not searched (under Linux it is searched after the recorded path if the executable has been linked with the option --enable-new-dtags; I don't remember Solaris behavior for now)
in a set of system dependant directories (Linux allows to specify them in /etc/ld.so.conf and has a cache, see ldconfig)

Related

Is there an equivalent of AddDllDirectory in Linux and Mac?

I have a folder where many Shared Libraries are in. I want to load all of them in my program so iterate them and load them but some got not loaded because it could not find a dependency which lies in the same folder but (at least in windows) it doesn't search the same folder.
I googled and found 'AddDllDirectory' for windows.
Is there a equivalent for this function in Linux and Mac?
If not how could I workaround this problem?
It needs to be runtime because the folder containing the Shared Libraries can change.
For a single, specific program, execute it from the shell (or with a script) like this:
LD_LIBRARY_PATH=path:to:libraries /path/to/program
To set up system wide libraries, adjust the contents of /etc/ld.so.conf.d or /etc/ld.so.conf.
If you just want to make your programs refer to a specific additional path, have a look at the rpath linker flags. E.g.
gcc -o my_program -Wl,-rpath='additional/library/paths'
With rpath take note about the special "variable" ${ORIGIN} which allows you to specify paths relative to the install location of the linked binary. For details read the manual page of ld.so

Telling omake to use static version of a c library

I'm using omake to build a native binary executable. After it links and i try to run it, it fails to run giving the following error:
error while loading shared libraries: libprotobuf-c.so.1: cannot open shared object file: No such file or directory
Is there a way, at compile time, to tell the executable to pick up the static version: libprotobuf-c.a and not the shared on?
I'm not familiar with omake but I believe flag to ocamlc you are looking for is dllpath:
-dllpath dir
Adds the directory dir to the run-time search path for shared C libraries. At link-
time, shared libraries are searched in the standard search path (the one corresponding
to the -I option). The -dllpath option simply stores dir in the produced executable
file, where ocamlrun(1) can find it and use it.
If you can configure omake to pass the appropriate -dllpath argument to ocamlc, you should be good to go.
Under the hood I believe this is using the rpath feature (runtime library search path) of ld, the GNU linker. See https://linux.die.net/man/1/ld . There is also a chrpath utility to change the rpath of an already-built executable.
Another option is running your executable with LD_LIBRARY_PATH set so that the shared library is on the load path. You could also install the shared library system wide if appropriate. A final option is to load the library manually when your application boots using dlopen.
The correct choice depends on how you will distribute this and to who you will distribute this, if at all. Keep in mind if you use rpath/dllpath the end user is unlikely to have protobuf installed in the same location you do.
There doesn't seem to be a global flag that can be passed to ld, the linker, that enforces the linker prefer static libraries to dynamic ones when available. In my case, I set the library name explicitly like so:
OCAML_LINK_FLAGS += -cclib -l:libprotobuf-c.a

Compiling with c++ and getting "ready to go" executable

Is it possible to compile a program with g++ so that shared libraries etc are "included" with the executable?
I have a c++ program that I'd like to compile and run at another location where I'm missing some libraries and don't have install access.
The main reason I couldn't find answers for this is probably that I don't know how to call it..
No, it's not possible.
Either link statically (with -static) so it doesn't use any shared libraries, or copy the shared libraries to the other location along with the executable.
Since the shared libraries will not be in the dynamic loader's usual search paths you'll need to ensure they can be found, either by setting the LD_LIBRARY_PATH environment variable when running the program, or by setting an RPATH in the executable when you build it.
(Assuming you're using the GNU linker ...) To set an RPATH in the executable link with '-Wl,-rpath,$ORIGIN' (the quotes are important, to stop $ORIGIN being expanded by the shell). That means the loader will look for shared libraries in the same directory as the executable itself.
See https://gcc.gnu.org/onlinedocs/libstdc++/faq.html#faq.how_to_set_paths and https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dynamic_or_shared.html#manual.intro.using.linkage.dynamic for more information.

Indicate the C++ app to look for dynamic libraries into the ./lib subfolder at runtime

Probably a newbie's question for those used to package and distribute applications:
when launching my executable on a different computer than the one used for compilation, I need to place several dynamic libraries in the same folder to run it.
I want the executable to look at runtime in a relative lib/ subfolder placed besides it and where I would have placed all these libraries. What do I have to do for this?
I don't know about Win and MacOS, but for Linux, the good solution would be to set the RPATH binary header of the executable during build-time.
For me this article helped a lot to understand the various ways dynamic libraries are looked up.
How to set the RPATH properly depends on your build system, but basically you need to specify the option -rpath=/path/to/lib/folder for the linker - this will have the effect that the specified path will always be searched first for shared libraries.
To check if your program was linked correctly, you can use
readelf --dynamic [executable or shared library] | grep PATH
It would be also possible to use the LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to set the path where the libraries are located, but these would require changes on the system where the program is run.

eclipse sfml library issues

I pulled out an application that I wrote in C++ using the sfml library, but I'm having trouble setting up the library in Eclipse. I specified the include path, the lib path and included all the necessary .so libraries to link to. the application compiles fine but it complains at runtime about missing libraries. Why is this happening? Didn't I include the path to the libraries in the project settings already? I have even tried to place all the .so's in the executable directory with no luck.
There is only the name of the shared lib stored in the executable. At program startup the dynamic linker then searches for the specified libs in its search paths. You can add/specify search paths by placing them colon separated in the environment variable LD_LIBRARY_PATH or by specifying them in /etc/ld.so.conf (at least if you use some unix based OS). On windows the whole PATH environment variable is used when searching for dynamic-link libraries (DLL).
To see the paths of shared libraries used by a given application run ldd applicationPath.