0

So, the project I am working on uses a non-system directory to keep some DLLs that the code uses. I don't want to put them in system directories, so the executables have an rpath set to find the DLLs. However, as more and more libraries are added, there are now DLLs that depend on other DLLs in that directory.

Those libraries cannot find the DLLs that they depend on, since they are not located in a directory that the linker is looking for, e.g. a system directory.

Is there a way to get the DLLs to search this specific non-system directory? Such as an rpath? And how is that done with a library? The build system being used for the project is CMake, if that assists in the answer.

This answer does not work, since there is no rPath tag in the library: https://unix.stackexchange.com/a/272286/4193

I have considered using LD_LIBRARY_PATH, and that works, but it is annoying to type and not all that great to get other people to use the app. If there is a way to add the rPath tag to the library, that would be the best option.

Pointers to previous relevant questions and answers appreciated.

10
  • Would setting LD_LIBRARY_PATH in the runtime work for you? It would also simplify the build system. – Arkadiusz Drabczyk Mar 8 '20 at 21:43
  • @ArkadiuszDrabczyk, that works, but it is annoying to type and not all that great to get other people to use the app. If there is a way to add the rPath tag to the library, that would be the best option. – casualunixer Mar 14 '20 at 17:35
  • You can create a shell wrapper that would set LD_LIBRARY_PATH, call the app via exec and pass all arguments to the app itself via $@. You can putt a wrapper in path, call it app for example and call the real app app-bin. – Arkadiusz Drabczyk Apr 10 '20 at 22:17
  • And, why don't you want to put the shared objects in /usr/lib or /usr/lib64 in the first place? – Arkadiusz Drabczyk Apr 10 '20 at 22:21
  • 1
    And why do you think that shared objects cannot have -Wl,-rpath set? Because they can. – Arkadiusz Drabczyk Apr 10 '20 at 22:46
3
+100

Is there an rpath for dynamic linked libraries?

Yes, there is. You can use -Wl,-rpath with ELF shared objects just like with ELF executables. Clone a little example I put up here:

git clone https://gist.github.com/ardrabczyk/6aeb8545c9b754d6b15be390af4bdff0

Run make to compile. Check what libraries are needed by the main ELF executable:

$ readelf -d ./main

Dynamic section at offset 0xe30 contains 22 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libtwo.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000f (RPATH)              Library rpath: [.]
(...)

And check what libraries are needed by libtwo.so:

$ readelf -d ./libtwo.so

Dynamic section at offset 0xe38 contains 22 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libone.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000f (RPATH)              Library rpath: [libs]
 (...)

As you can see both main and libtwo.so need some shared objects and both have rpath set. You don't need to set LD_LIBRARY_PATH to run ./main:

$ ./main
I'm in bar()

main will always look for its libtwo.so dependency in . that is a current directory and libtwo.so in turn will always look for its libone.so dependency in libs directory. If libs is missing ./main will not start:

$ mv libs libs.bak
$ ./main
./main: error while loading shared libraries: libone.so: cannot open shared object file: No such file or directory

Restore it:

$ mv libs.bak libs
$ ./main
I'm in bar()
4
  • I didnt knpw rpath was a thing in programming. I like the explainations. Under Windows programs always look into their own directory. Now i know, how Linux does handle this. Good answer! – WGRM Apr 11 '20 at 19:59
  • I think you have demonstrated that main depends on libone.so due to the link line, rather than that libtwo depends on libone. This is easy to fix by making lib_two.c call foo(). Then moving aside libone.so should cause libtwo.so to fail when main is run. Then the answer will be complete. – casualunixer Apr 11 '20 at 20:38
  • @casualunixer: sorry, I don't get your point. main doesn't depend on libone.so, it depends on libtwo.so which in turn depends on libone.so. – Arkadiusz Drabczyk Apr 11 '20 at 20:55
  • @ArkadiuszDrabczyk, I missed that you included libone.so in the link line for libtwo. Everything is fine. – casualunixer Apr 12 '20 at 1:02
0

Since you don't wanna consider it as part of the system, use it as what it is; an user application!

If you add ~/.local/lib/ to your LD_LIBRARY_PATH, you can put everything there. Just create a partial FHS structure under ~/.local/ like bin, etc, lib and share. That way you don't need to call the program with a preceding environmemt variable. All other systems would just need to append this directory their library path environment variable. Very tidy and unixish.

If you reject this solution as well, there is only one possibility left. Either you use a fixed path, which is expected on every system or an environment variable, which contains a path and is also expected.

3
  • OP already said they don't want that solution. Read comments before answering. – Arkadiusz Drabczyk Apr 10 '20 at 22:47
  • @Arkadiusz updates shouldn't be in comments; they should be in the question – roaima Apr 11 '20 at 7:37
  • @roaima: ok, I've updated the question – Arkadiusz Drabczyk Apr 11 '20 at 7:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.