Question

I am trying to link a number of dynamic libraries into an application and running into problems with g++.

Consider:

  • libA.so
  • libB.so depends on libA.so
  • libC.so depends on libB.so
  • Application D depends directly on libC.so

If I try to link application D just to libC.so, I get unresolved symbols for the symbols in A and B. I feel as if the compiler should be able to figure it out, and when I use the intel compiler, it does. G++, however, can't figure out the linking. I would like my libraries and executables to only have to link to the things they directly need, not try to anticipate what the libraries they are using need.

I have also had problems when libA.so links to a static library, and when I try to compile the executable I get unresolved symbols from the static library that libA.so was supposed to be using.

I have seen a number of other people ask this and similar questions and get a variety of answers (Linking with dynamic library with dependencies), but the answers are all rather vague, often conflicting, and very much along the lines of "keep on trucking and RTFM".

I get the impression that link order matters. How so, and how do I know what order to link in?

Update

I believe that what is happening is something along the lines of libA.so contains two functions (AA and AB). libB.so needs AA and libC.so needs AB. When libB.so gets linked, g++ gets libA.so, sees that only AA is used, and drops AB. Then when libC.so is linked in, g++ sees that libA.so was already linked and doesn't revisit it, resulting in AB being undefined. I have seen documentation indicating that static libraries work this way, but would the compiler treat dynamic libraries the same way? If so, is there a way to work around it?

Was it helpful?

Solution

(You haven't shown the actual linker error, or provided nearly enough information about the problem, so what follows is partly guesswork...)

If I try to link application D just to libC.so, I get unresolved symbols for the symbols in A and B.

When linking an executable the GNU linker checks that all symbols are available. You can turn that off with --allow-shlib-undefined (to tell GCC to pass that to the linker use -Wl,--allow-shlib-undefined)

It is better not to use that option, but in that case the linker needs to know where to find libA.so and libB.so so it can check that the symbols needed by libC.so will be found. You can do that with the -rpath-link linker option

When using ELF or SunOS, one shared library may require another. This happens when an "ld -shared" link includes a shared library as one of the input files.

When the linker encounters such a dependency when doing a non-shared, non-relocatable link, it will automatically try to locate the required shared library and include it in the link, if it is not included explicitly.

So you should be able to fix the problem by using -Wl,-rpath-link,. to tell the linker to look in the current directory (.) for the libraries libC.so depends on.

I get the impression that link order matters. How so, and how do I know what order to link in?

Yes, link order matters. You should link in the obvious order ;-) If a file foo.cc depends on a library then put the library later in the linker line, so it will be found after processing foo.cc, and if that library depends on another library put that even later, so it will be processed after the earlier library that needs it. If you put a library at the start of the link line then the linker doesn't have any unresolved symbols to look up, so doesn't need to link to that library.

OTHER TIPS

You need to explicitly specify all libraries that you directly use.

During static linking, the dependencies of the loaded .so are not used; when linking the main program, all symbols have to be found in either the main program itself, in a static library specified on the command line, or in a shared library specified on the command line.

This is where you get an error.

When the program is executed, the dependencies of dynamic libraries are loaded so that references from within other shared libraries can be resolved. By the time the program runs, it might actually be linked (dynamically) against a different version of the shared library. This different version might have different dependencies, so the main program MUST NOT rely on the set of additional libraries that get loaded as dependencies.

This is why the static linker stops you early.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top