Consider the following scenario:
I want to compile a binary file that links with the libB. Should I link the binary with libB only or with libA either?
Is there any way to link only with the direct dependencies, letting the resolution of unresolved symbols from the dependencies for runtime?
I'm worried about the fact that the library libB implementation may change in the future, introducing other dependencies (libC, libD, libE for instance). Am I going to have problems with that?
In other words:
Of course, b.cpp includes a.h and main.cpp includes b.h.
Compilation commands:
g++ -fPIC a.cpp -c g++ -shared -o libA.so a.o g++ -fPIC b.cpp -c -I. g++ -shared -o libB.so b.o -L. -lA
Which of the bellow options should I use?
g++ main.cpp -o main -I. -L. -lB
or
g++ main.cpp -o main -I. -L. -lB -lA
I couldn't use the first option. The linker complains about the unresolved symbols from the library libA. But it sound a little strange to me.
Thanks very much.
-- Updated comments:
When I link the binary, the linker will try to resolve all symbols from the main and the libB. However, libB has undefined symbols from the libA. That's why the linker complains about that.
That's why I need to link with the libA too. However I found a way to ignore unresolved symbols from shared libraries. Looks like I should use the following command line to do that:
g++ main.cpp -o main -I. -L. -lB -Wl,-unresolved-symbols=ignore-in-shared-libs
Looks like it is still possible to use the -rpath
option. However I need to understand it a little better.
Does anyone knows any possible pitfalls when using the -Wl,-unresolved-symbols=ignore-in-shared-libs
option?
-- Updated comments 2:
-rpath
should not be used for this purpose. It is useful to force a library to be found in a given directory. The -unresolved-symbol
approach looks much better.
Thanks again.
Static libraries are linked to the executable when the program is compiled. Dynamic libraries are linked later, either at runtime or at load time. Static libraries are not shared between programs because they are written into the individual executable.
Steps to find shared library dependency in Linux:Launch your preferred terminal application. Get absolute path of the program you want to check. Print shared object dependencies using ldd. Print verbose dependency info using ldd.
You can't statically link a shared library (or dynamically link a static one).
Yes for instance when you call windows functions from within your static lib they are normally from some dynamic library so there should be no difference.
It looks like you are most of the way there already. Well done with your investigation. Let's see if I can help clear up the 'why' behind it.
Here's what the linker is doing. When you link your executable ('main' above) it has some symbols (functions and other things) that are unresolved. It will look down the list of libraries that follow, trying to resolve unresolved symbols. Along the way, it finds that some of the symbols are provided by libB.so, so it notes that they are now resolved by this library.
However, it also discovers that some of those symbols use other symbols that are not yet resolved in your executable, so it now needs to resolve those as well. Without linking against libA.so, your application would be incomplete. Once it links against libA.so, all symbols are resolved and linking is complete.
As you saw, the use of -unresolved-symbols-in-shared-libs
, doesn't fix the problem. It just defers it so that those symbols are resolved at run time. That's what -rpath
is for: to specify the libraries to be searched at run time. If those symbols can't be resolved then, your app will fail to start.
It's not an easy thing to figure out library dependencies because a symbol could be provided by more than one library and be satisfied by linking against any one of them.
There is another description of this process here: Why does the order in which libraries are linked sometimes cause errors in GCC?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With