dgnuff
dgnuff

Reputation: 3557

Cmake: How to set rpath to ${ORIGIN} with cmake

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 .sos 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

Answers (2)

brookbot
brookbot

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

NelDav
NelDav

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

Related Questions