Linking to a dynamic library with dependencies

Consider the following scenario:

  • The libA.so shared library without dependencies.
  • The shared library is libB.so, with libA.so as its dependency.

I want to compile a binary file that links to libB. Should I link the binary to libB only or to libA either?

Is there a way to associate only with direct dependencies by allowing the resolution of unresolved characters from dependencies for the runtime?

My concern is that the implementation of the libB library may change in the future by introducing other dependencies (libC, libD, libE, for example). Will I have problems with this?

In other words:

  • LibA files: a.cpp ah
  • Libb files: b.cpp bh
  • main program files: main.cpp

Of course, b.cpp includes ah and main.cpp includes bh

Compilation Commands:

g++ -fPIC a.cpp -c g++ -shared -o libA.so ao g++ -fPIC b.cpp -c -I. g++ -shared -o libB.so bo -L. -lA 

Which of the following options should I use?

 g++ main.cpp -o main -I. -L. -lB 

or

 g++ main.cpp -o main -I. -L. -lB -lA 

I could not use the first option. The compiler complains about unresolved characters from the libA library. But that sounds a little strange to me.

Thank you very much.

- Updated comments:

When I link the binary, the linker will try to resolve all characters from the main and libB. However, libB has undefined characters from libA. This is why the linker complains about this.

This is why I need to link to libA too. However, I found a way to ignore unresolved characters from shared libraries. It looks like I should use the following command line for this:

 g++ main.cpp -o main -I. -L. -lB -Wl,-unresolved-symbols=ignore-in-shared-libs 

It looks like you can still use the -rpath option. However, I need to understand this a little better.

Does anyone know of any possible errors 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 make the library find in this directory. The -unresolved-symbol approach looks much better.

Thanks again.

+46
gcc dll g ++ dependencies
Jun 15 '12 at 17:34
source share
4 answers

It looks like you are most there. Well done with your investigation. Let's see if I can help clarify the why for this.

This is what the linker does. When you link your executable ("main" above), it has some characters (functions and other things) that are not allowed. He will look down the list of subsequent libraries, trying to resolve unresolved characters. Along the way, he discovered that some characters were provided by libB.so, so he notes that they are now allowed by this library.

However, it also discovers that some of these characters use other characters that are not yet allowed in your executable file, so now you must also eliminate these characters. Without a link to libA.so, your application will be incomplete. As soon as it contacts libA.so, all characters are resolved and the connection is complete.

As you saw, using -unresolved-symbols-in-shared-libs does not fix the problem. It just puts it off so that these characters are allowed at runtime. This is what -rpath : is for specifying libraries to search at runtime. If these characters cannot be resolved, your application will not start.

It is not easy to calculate library dependencies because a symbol can be provided by more than one library and is satisfied by contacting any of them.

Here is another description of this process: Why does the order in which libraries are linked sometimes cause errors in GCC?

+26
May 31 '13 at 1:58
source share

For dynamic linking only with direct dependencies, you can use -Wl,--as-needed with the addition of libs after -Wl,--as-needed :

 gcc main.c -o main -I. -L. -Wl,--as-needed -lB -lA 

To check for direct dependencies, you should use readelf instead of ldd , because ldd also shows indirect dependencies.

 $ readelf -d main | grep library 0x0000000000000001 (NEEDED) Shared library: [libB.so] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 

ldd also shows indirect dependencies:

 $ LD_LIBRARY_PATH=. ldd ./main linux-vdso.so.1 (0x00007fff13717000) libB.so => ./libB.so (0x00007fb6738ed000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb6734ea000) libA.so => ./libA.so (0x00007fb6732e8000) /lib64/ld-linux-x86-64.so.2 (0x00007fb673af0000) 

If you are using cmake , you can add the following lines to include direct dependencies only:

 set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_EXE_LINKER_FLAGS}") set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_SHARED_LINKER_FLAGS}") 
+10
Mar 23 '15 at 11:10
source share

Another option is to use libtool

If you change the g++ call to libtool --mode=compile g++ to compile the source code, and then libtool --mode=link g++ to disable the libB application, then libA will automatically bind.

+1
Jun 14 '16 at 14:36
source share

This is an interesting post - I also hit my head about it, but I think you missed the point here.

The idea is right?

 main.cpp =(depends)=> libB.so =(depends)=> libA.so 

Next, consider that ..

  • In a.cpp (and only there) you define a class / variable, name it "symA"
  • In b.cpp (and only there) you define a class / variable, call it "symB".
  • symB uses symA
  • main.cpp uses symB

Now libB.so and libA.so have been compiled as described above. After that, your first option should work, that is:

 g++ main.cpp -o main -I. -L. -lB 

I assume your problem is that

in main.cpp you also reference symA

Am I right?

If you use a symbol in your code, then this symbol must be found in the .so file

The whole idea of ​​inter-rated shared libraries (for example, creating APIs) is that the characters in the deeper layers are hidden (think about the bow of the bow) and are not used. .. that is, do not refer to symA in main.cpp, but only to symB instead (and let symB only refer to symA).

0
Aug 15 '17 at 17:23
source share



All Articles