Skip to content
Advertisement

Trying to build C++ exe that uses .so that uses other .so files

I’m trying to build a C++ executable that links with a shared library, libA.so. libA.so was built and linked with another shared library, libB.so. libB.so was built using -rpath to look for a custom build of a system library in my home directory (liblapack.so). If I do a “readelf -d” on libB.so, I see liblapack.so as “NEEDED”, and I also see the custom build path listed under “RPATH”. If I do a “readelf -d” on libA.so, I only see libB.so listed as “NEEDED”; no RPATH entries. When I then try to build my exe using libA.so, it is not looking in the custom path specified in libB.so; it’s picking up the one in the system location, which doesn’t have the right functions so the linking fails. Does anyone know of a way to achieve what I want to do here? Is there any way to get libB’s RPATH entries to propagate to libA?

I’m using GCC 9 on RHEL 7.

Thanks in advance.

ETA: The app, libA, and libB are all separate packages, so I would prefer to keep their build processes and unusual rpath info known only to themselves. I can change the link flags of each black box. They’re also established packages, so I can’t change to autoconf or something like that.

ETA2: Restating things, when I build libA and link with libB, it does mark libA as needing libB, which is great. Then an app can link with libA and implicitly get libB, which libA needs to function. But why does linking libB with libA throw away libB’s rpath info? Or, when app is linking, why doesn’t it see that since libA requires libB, link with libB and preserve libB’s rpath specification? The bottom line is that libB’s rpath specification is being lost somewhere, and it seems like it shouldn’t be. (By the way: This is a new thing to me, so I don’t doubt there are issues with the way I think it should work. But logically, it sounds right to me.)

Advertisement

Answer

Use -rpath-link when linking and specify your custom library location.

gcc -o app source.o -lA -Wl,-rpath-link=$HOME

This will cause the linker to look in $HOME to find shared libraries referenced by other shared libraries. But only when linking. At run time, when dynamic linking is done, the rpath-link option has no effect and the normal RPATH, LD_LIBRARY_PATH, etc. search order is used.

The DT_RPATH or DT_RUNPATH in a shared library ARE searched. But they are not first in the search order. Your alternate version of libB must be in a path that comes first, so it’s found rather than the one you want. Try renaming it and see what happens or perhaps check your LD_LIBRARY_PATH and LD_RUN_PATH variables.

There isn’t a way the change the order, but -rpath-link comes first, so this can fix the problem.

To make libB self contained, use something like a pkgconfig file that contains the options needed to use the library. This also works for finding header files or with static libraries.

You could also rename libA to libMyA to avoid the name collision with the alternate version also installed.

Alternatively, one can avoid the link failure without really fixing the problem by using the --allow-shlib-undefined linker option. Then it shouldn’t matter if it finds the wrong version as the missing symbols won’t be an error.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement