Building of shared libs which depend on each other (Linux) - linux

I have a very complex bunch of libs and executables taken over (Linux). The whole system was developed using static libraries in the past, then a couple years ago the libs are migrated to be shared libraries (-fPIC etc). Checking the dependencies I found out, that there are two shared libs: libA and libB:
libA calls some functions from libB
libB calls some functions from libA
I would like to build the libs having proper dependencies: libA depends on libB and libB depends on libA. But I can't give "-llibB" to the linker, because the lib is not yet existing at the build time of libA
If I build libA without the dependancy of libB (creating unresolved symbols), I have to keep in mind if I use libA I have to link libB also, because of undefined symbols in libA. That's annoing!
What I'm looking for is a possibility to build libA and telling to the linker to create dependancy to libB WITHOUT having libB at this time, is that possible?
How can I solve my problem without merging libA and libB together?
Regards,
peters
Edit:
I found out, that I can directly generate an empty lib (without writing a source code):
gcc -shared -Wl,-soname,libB.so.$(MAJOR) -o libB.so
then I can build libA adding: -lB to the build command. After that I removed the libB.so.
Finally, after installation the libB refers to libA and libA refers to libB.
Of course the MAJOR number must match the MAJOR of the libB, this is so, because the major number is common for all libs.
I'm just asking myself if there is more suitable way to do it?

Dependencies between shared libraries aren't resolved until load time, so you can link with the following line:
gcc -shared -Wl,-soname,libA.so.$(AMAJOR) -o libA.so
gcc -shared -Wl,-soname,libB.so.$(BMAJOR) -o libB.so
and then
gcc -o myProgram a.o b.o c.o libA.so libB.so
when you load(run) myProgram, the dynamic loader will follow the unsatisfied dependencies and look for the symbols in both shared objects. The -shared option is actually a non-complaint-about-unresolved-symbols flag that allows to construct an ELF file without all resolved symbols.
Another thing that can be happening here is that the libreries are not installed. You are trying to execute them without the proper paths and get unresolved symbols (from myProgram) when executing it. One solution is to run myProgram with:
LD_LIBRARY_PATH=. myProgram
or
export LD_LIBRARY_PATH=/path/to/libraries
myProgram
In linux, libraries are cached in a system database, so loading of shared libraries is fast. Database is indexed by soname, and to regenerate the database you have to use command ldconfig(8) as root
ldconfig
Other environments may not use ldconfig(8) at all (solaris being an example)

Related

loading a shared library from any directory

I'm playing with shared library linking and loading procedures, and trying to learn about different ways to tackle the loading error:
error while loading shared libraries: ... : cannot open shared object file: No such file or directory
I managed to solve it by using LD_LIBRARY_PATH and by using rpath. I now try to comprehend the usage of ldconfig and how it can solve it, too [some of my web sources: 1, 2, 3 ]
So, I've got the following source files: test.c func1.c func2.c. Here's what I do:
Compiling them into PIC .obj files:
$ gcc -Wall -fPIC -c *.c
Creating a shared library from the object files, naming it 'libshared.so', and using 'soname':
$ gcc -shared -Wl,-soname,libshared.so -o libshared.so *.o
Linking with a shared library by telling GCC where to find the shared library (the ... is just an abbreviation for my personal shared library path):
$ gcc -L/home/.../my_shared_library -Wall -o mytest test.c -lshared
Now, I try running it, and get the loading error:
./mytest: error while loading shared libraries: libshared.so: cannot open shared object file: No such file or directory
So I try telling the loader to search my private directory for the shared library file:
ldconfig -n home/.../my_shared_library
(I also tried it with: ldconfig -n .-L when my working directory is home/.../my_shared_library)
and tried running it once again, but I still get the same error. What am I doing wrong?
Use GNU Libtool to simplify the process and avoid such errors.
Also use -fPIC option when you build your library.
Read Program Library HowTo & Drepper's paper: How to Write Shared Libraries
You probably want to set the rpath. See this question.
You might load your plugin at runtime with dlopen(3). Notice that shared object paths without any / are handled specially.

Do permanent linking to other shared libraries

currently I'm creating a shared library "libmylib.so" using libtool with statements like this:
libtool --mode=compile g++ -Wall -fPIC -shared $(CFLAGS) $(LFLAGS) $(LSTATIC)
libtool --mode=link g++ -shared -export-symbols-regex beam_ -rpath /usr/lib -lotherlib
The library created with this depends on an other (non-static) library "libotherlib.so", that's why I'm using the statement "-lotherlib".
Now when I build an executable that links against libmylib.so something strange happens: I have to link against libotherlib.so again, means I have to add a statement "-lotherlib" for this executable too.
So it seems former linking of libotherlib.so when building libmylib.so does not to be persistent. But how can I change this? How can I build libmylib.so so that it implicitely knows about its dependency to shared library libotherlib.so?
Thanks!
The answer seems to be the same like for this question: Link a static library to a shared one during build?
Big difference: when shared objects are specified for linking instead of static ones they are not included but the generated shared library remembers its dependnecy to these so's.

Any way to make LD record shared library name only, no subdirs?

I am linking a Linux executable referencing a shared library:
g++ Debug/file.o Debug/MyLib.so -o Debug/MyApp -Wl,--rpath='$ORIGIN'
The problem is that the generated MyApp file references "Debug/MyLib.so" so if I run it from the Debug directory, it does not find it. Thus, specifying -Wl,--rpath='$ORIGIN' does not help.
Is there a way to tell the GNU LD to use the 'Debug/MyLib.so' file, but record it as just 'MyLib.so' inside the executable?
If don't want to change the name of your library, you can use the soname option when
you create it.
For example:
build the library
$> g++ -fpic -c mylib.cpp
$> g++ -shared -o subdir/mylib.so mylib.o -Wl,-soname=mylib.so
build the program
g++ -o subdir/main main.cpp -Lsubdir -l:mylib.so -Wl,-rpath='$ORIGIN'
(Don't forget the colon after the -l option)
You're linking inappropriately for a shared library. You should rename the library to libMyLib.so, and link your executable using:
g++ Debug/file.o -o Debug/MyApp -Wl,--rpath='$ORIGIN' -LDebug -lMyLib
What the -LDebug says is search in the Debug directory for libraries at link time, and then the -lMyLib says look for a library called libMyLib.so (or libMyLib.a) in the paths that -L specifies, plus the standard library search path.
The standard naming convention for libraries under linux/unix is libLibraryName, and the linker knows when you ask to link to a library using -l, that it should look for a file prefixed lib thatname
When you used it in the prior form, it actually recorded the absolute library that was used when linking, rather than the normal mechanism of just recording the name of the library, and relying on the runpath to resolve the path to the library.

Mixing static libraries and shared libraries

I have a project where I have one static library libhelper.a and another with my actual shared object library, libtestlib.so. My goal is to link libhelper.a into libtestlib.so. Is that possible on Linux/BSD? When I tried and created a test program I got the following errors:
./prog1:/usr/local/lib/libtestlib.so.1.0: undefined symbol ''
My guess is that this is occurring because libhelper.a was not compiled with -fPIC while libtestlib.so was. What is the proper way to build programs that use shared libraries that also have dependancies on static libraries?
Thanks!
My goal is to link libhelper.a into libtestlib.so. Is that possible on Linux?
Sure. This should do:
gcc -shared -fPIC -o libtestlib.so $(OBJS) \
-Wl,--whole-archive -lhelper -Wl,--no-whole-archive
libhelper.a was not compiled with -fPIC
It's best to rebuild libhelper.a with -fPIC. If that's not possible, above command will still work on Linux/ix86, but not on e.g. Linux/x86_64.
What is the proper way to build programs that use shared libraries that also have dependancies on static libraries?
If you include libhelper.a into libtestlib.so as above, then simple:
gcc main.c -ltestlib
is all you need. If you insist on linking with libhelper.a, then you must tell the end-user that he must link with e.g.
gcc main.c -ltestlib -lhelper
There is no way to specify that libtestlib.so depends on libhelper.a.

How to link static libs (archives) to an empty dynamic lib with GCC4

I'm using GCC on Linux to create a shared library. The library itself has no code but links to a couple of static libraries (archives) also built using GCC.
I need to export the static libs' symbols through my shared library. What happens is that the resulting shared lib is too small and it actually does not contain any of the symbols provided by the static libs mentioned above.
I also tried with a map of exported symbols but that did not help at all.
You need the linker's --whole-archive option to pull in all of the static archives:
gcc -shared -o libwhatever.so -Wl,--whole-archive -lstatic -Wl,--no-whole-archive
The -Wl is needed because --whole-archive is a linker option.
In order to do this, the code in libstatic.a will need to have been properly compiled for use in a shared object (i.e. with -fpic on platforms that require that).

Resources