Let’s say we have a library A, which depends on library B. Library A is built using cmake and library B is linked to it publicly using target_link_libraries(…)
Now i want to build an executable target, which depends on A, and B. I link them both publicly, but in my code, i will use only the functions, provided by A. The program compiles and links perfectly, but when i try to run it i get “error while loading shared libraries: libB.so: cannot open shared object file: No such file or directory” error. And i have to use LD_LIBRARY_PATH to point the executable on the library.
Then i add some functions, provided by B library, compile and link the program and LD_LIBRARY_PATH is not needed any more, because the paths become resolved.
After the first build ldd shows B as “not found”, after the second build everything is ok.
My question is: is there a way to help cmake resolve the RPATHs correctly in the first build (without using B functionality)
If you’re using imported targets, rpath entries are not added like they are if you use an absolute path. The first issue is arguably A’s problem; it should have an RPATH entry for B.
Long term, I’d like there to be usage requirements related to runtime paths, but other things need to happen first. One, I think, is install properties being associated to the install rather than the target so that you can have properties for different installs of the same artifact. This would allow a library to go to $prefix/lib and $prefix/Applications/foo.app/Contents/Libraries and have correct bits for each.
As far as i can control the builds of both libraries and the executable, i would be greatful if you could tell me what should i do with A to solve the problem. As i said, now it links B publicly simply with target_link_libraries(), no special flags or anything else.
As for installs, this could be the solution, but what if i need to run the tests? As i consider, we must run them after build, but before the installation, so we can’t use installation RPATHs, and the build ones are broken.
Or maybe, i’m wrong. In any case, i am greatful for your answer and would be even more greatful for the continuation of the dialog.
The build rpaths should be everything you need. The problem is at installation, most of those go away.
If A is installed in the same prefix as B, just use a $ORIGIN RPATH (or @loader_path for macOS). The build should get all the rpaths you need and then at install time, the relative RPATH in use lets it work.
First of all, thank you for your answer.
According to it i am trying to add the following option to library A:
target_link_options(A PUBLIC “-Wl,-rpath=$ORIGIN”)
and after building the target i try the following command:
objdump -x libA.so | egrep ‘R(|UN)PATH’
which gives me “RUNPATH $$ORIGIN”
and the problem i described in this topic continues. I guess, the problem is in those “$$” dollar marks instead of one. How can i get rid of one of them?
Looking forward to your answer, i can’t use all those beautiful constructions like " BUILD_RPATH_USE_ORIGIN", because they were added in cmake 3.14 and i have to use only the 3.13 version.
Thanks in advance