Reputation: 3557
According to this SO question, Linux executable can't find shared library in same folder passing -Wl,-rpath,${ORIGIN}
is the way to get a Linux executable to search for .so
s in the same directory as the executable.
We're using cmake, so I'm adding a line of the form
target_link_options(Executable PRIVATE -Wl,-rpath=${ORIGIN})
to CMakeLists.txt. The problem with that is that cmake tries to interpret the nine character sequence ${ORIGIN}
as a variable, and replaces it with nothing.
So far, I've tried:
$${ORIGIN}
\${ORIGIN}
$\{ORIGIN\}
$$\{ORIGIN\}
\$\{ORIGIN\}
none of which have worked. How can I get this done?
-- Edit --
As noted by @Tsyvarev's comment, it turns out this was an XY problem in my particular case, since cmake has facilities directly designed to manipulate rpath. Using this, I was able to get a solution.
In my case, adding the following three lines to CMakeLists.txt did the trick.
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
SET(CMAKE_INSTALL_RPATH "$\{ORIGIN\}")
Note that part of our build process involves copying the .so
to the output folder in preparation for building the final tarball artifact. So using -rpath=${ORIGIN}
works for both testing in the build tree, and final installation of the executable in the Docker container.
Upvotes: 16
Views: 9406
Reputation: 473
It takes more than just setting CMAKE_INSTALL_RPATH
for me (cmake version 3.20.2, 3.7.2):
I've set CMAKE_INSTALL_RPATH
in a top level CMakeLists.txt file:
set(CMAKE_INSTALL_RPATH "${LIB_INSTALL_PATH}:$ORIGIN")
This example also adds another path from a variable I created LIB_INSTALL_PATH
.
For the target's CMakeLists.txt I have:
set_target_properties(mytarget
PROPERTIES
BUILD_WITH_INSTALL_RPATH true
LINK_OPTIONS "-Wl,--disable-new-dtags"
)
The --disable-new-dtags
was need to use RPATH
instead of RUNPATH
(the new default) which apparently has issues.
Not adding anything to the target CMakeLists.txt file results in RPATH set to the build path:
0x000000000000000f (RPATH) Library rpath: [/home/brookbot/workspace/my_project/build/tgt/stuff:/home/brookbot/workspace/my_project/build/tgt]
But adding the property BUILD_WITH_INSTALL_RPATH true
to the target gives me the desired result:
0x000000000000000f (RPATH) Library rpath: [/my/install/path:$ORIGIN]
I'm using readelf -d
to examine the results.
I've also verified this works for cmake version 3.7.2 with the caveat that it generates a RUNPATH
instead of RPATH
(like the LINK_OPTIONS
property does not work), but it still runs ok for me on target:
0x000000000000001d (RUNPATH) Library runpath: [/my/install/path:$ORIGIN]
Upvotes: 1
Reputation: 910
As you already noticed, you should use CMAKE_INSTALL_RPATH
or INSTALL_RPATH
.
INSTALL_RPATH
sets the rpath
when installing a specific target.
CMAKE_INSTALL_RPATH
is the global variant, doing the same for all targets.
I also struggled, how to escape $ORIGIN
.
But, for me it works without escaping it at all:
set_target_properties(<target> PROPERTIES INSTALL_RPATH "$ORIGIN")
Upvotes: 6