# Setting RPATH and not RUNPATH for executable

**URL:** https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011
**Category:** Code
**Created:** [February 6, 2024, 3:22am UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011 "2024-02-06T03:22:49Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![dconnell](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dconnell/32/4274_2.png) [@dconnell](https://discourse.cmake.org/u/dconnell)
#### Post date: [February 6, 2024, 3:22am UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/1 "2024-02-06T03:22:49Z")

</div>

I am working on a project that I would like to be able to distribute pre-compiled binaries for and I believe I’m in a scenario where I really do need to set RPATH and not RUNPATH but all the `CMAKE_*_RPATH` seem to be setting RUNPATH instead of RPATH. I tried using `target_link_options` to set it with `LINKER:-rpath,"$ORIGIN/..."` but am still getting RUNPATH set instead of RPATH (note the `$ORIGIN` needs some escaping but I didn’t bother figuring that out) so I’m not sure if this is actually on the compiler/linker side of things (I’m using GCC) rather than CMake?

Based on this [stackoverflow question](https://stackoverflow.com/questions/7967848/use-rpath-but-not-runpath) it sounds like RUNPATH is fully preferred over RPATH but I believe I’m in a situation where I can’t get around needing RPATH (but open to alternatives). The [CMake wiki’s entry on RPATH](https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling) says RUNPATH behaves exactly like RPATH except paths on RUNPATH are searched after paths on LD\_LIBRARY\_PATH while RPATH is searched before. It also says RPATH is ignored if RUNPATH is present so I would need to ensure RUNPATH is empty.

## Scenario

I’m writing a C extension for MATLAB that wraps around a third-party C lib. On Linux, MATLAB ships with an old version of stdlibc++. The third-party C lib needs a newer version to compile correctly. When calling MATLAB, it sets up LD\_LIBRARY\_PATH to give the libraries it ships with preference. Because of this the dynamic linker finds the old copy of stdlibc++ and I end up with `GLIBCXX_3.4.29` not found errors. I’m using CMake’s install functions to collect the RUNTIME\_DEPENDENCY\_SET and install it in a lib directory with the executables. Then I use `(set CMAKE_INSTALL_RPATH "$ORIGIN/lib")` so the linker will find those. The linker continues to find the old lib though. I can confirm removing the old lib from MATLAB’s library directory fixes the problem (though I’d rather a solution that doesn’t require the end user to touch their MATLAB install). I think my only option is to set the RPATH (I would not want to mess with LD\_LIBRARY\_PATH because I don’t want to impact the libraries other executables are using).

Additionally, the above wiki page indicates after setting the RPATH I can confirm it’s been set with `objdump -x <executable> | grep "RPATH"`, this results in no output, but replacing RPATH with RUNPATH does return a list of paths.

Is there anyway to force the use RPATH? Has it been fully deprecated at this point? Is there anything else I can do to ensure the linker finds the libs shipped with my package?

---

<div class="post-metadata">

### Author: ![dconnell](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dconnell/32/4274_2.png) [@dconnell](https://discourse.cmake.org/u/dconnell)
#### Post date: [February 6, 2024, 6:53am UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/2 "2024-02-06T06:53:15Z")

</div>

Found it as discussed [here](https://stackoverflow.com/questions/52018092/how-to-set-rpath-and-runpath-with-gcc-ld), I was looking for the linker flag `--disable-new-dtags`. And the choice of setting RUNPATH vs RPATH by default does look to be a linker specific decision.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 7, 2024, 8:54pm UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/3 "2024-02-07T20:54:50Z")

</div>

Yes, the behavior is up to the linker itself. Note that another difference is that `RPATH` entries are inherited (used when loading libraries loaded by the current library) where as `RUNPATH` entries are only used when loading libraries referenced from the library with the `RUNPATH` entry.

---

<div class="post-metadata">

### Author: ![dconnell](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dconnell/32/4274_2.png) [@dconnell](https://discourse.cmake.org/u/dconnell)
#### Post date: [February 8, 2024, 1:02am UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/4 "2024-02-08T01:02:15Z")

</div>

I was wondering about that when trying to figure out if the order the needed share libraries show up in the ELF’s dynamic section mattered.

When dealing with C extensions for high-level languages, I believe a SO can only be loaded into the interpreter’s environment once (i.e. can’t have multiple definitions of the same symbols) and the C extensions are SOs that get dynamically loaded when first needed. As such, in this specific case, I don’t think there’s anything I can do to my extensions RPATH/RUNPATH to affect the version of an SO both my extension and the interpreter depends on because the linker can’t know that my extension is going to be needed at a later time. (But my understanding of all this is limited so that might be wrong.)

So I think my only option was to get my extension to work with the libraries the intepreter uses. (Which I did manage eventually.)

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 8, 2024, 5:14am UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/5 "2024-02-08T05:14:06Z")

</div>

> [@dconnell](#):
>
> I believe a SO can only be loaded into the interpreter’s environment once (i.e. can’t have multiple definitions of the same symbols)

For ELF platforms, there is a global symbol table[1]. Once a symbol is bound by a library that is it (this is how `LD_PRELOAD` works. There’s also a flag (`-Wl,-z,now`?) for eager bindings that can’t be preloaded over. So if you load `libstdc++` from GCC 4.8, loading a `libstdc++` from GCC 13 later will _add_ the set difference of symbols to the symbol table. Hopefully `libstdc++`'s ABI stability is accurate because you’re going to have GCC 13 code calling GCC 4.8 symbols where they exist already.

Note that MATLAB has also caused me pain years ago because they shipped an ancient Boost build that conflicted with our Boost build. Luckily, `#define boost myboost` in strategic spots can avoid this specific one, but their ABI cleanliness is quite annoying.

[1] There are symbol namespaces via `dlmopen`, but they are a _very_ limited resource (16 by default), and `glibc`-only. Ends up being a lot of platform specific code for not a lot of gain.

---

<div class="post-metadata">

### Author: ![dabrahams](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dabrahams/32/4265_2.png) [@dabrahams](https://discourse.cmake.org/u/dabrahams)
#### Post date: [February 16, 2024, 5:39pm UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/6 "2024-02-16T17:39:53Z")

</div>

> [@dconnell](#):
>
> all the `CMAKE_*_RPATH` seem to be setting RUNPATH instead of RPATH.

Well, that’s good to know! The fact that it’s [not documented](https://gitlab.kitware.com/cmake/cmake/-/issues/25683) is a problem, so I’m glad I found this thread.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 16, 2024, 6:35pm UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/7 "2024-02-16T18:35:33Z")

</div>

Note that CMake only models “rpath” as a concept (arguably CMake should have been named `RUNTIME_LIBRARY_SEARCH_PATHS` or something, but that ship sailed long ago); linkers started defaulting to `DT_RUNPATH` rather than `DT_RPATH` ELF entries years ago (all with the same flags).

---

<div class="post-metadata">

### Author: ![dconnell](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dconnell/32/4274_2.png) [@dconnell](https://discourse.cmake.org/u/dconnell)
#### Post date: [February 17, 2024, 12:51am UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/8 "2024-02-17T00:51:50Z")

</div>

I think the way CMake handles it is appropriate but it might be worth adding a note to the RPATH wike page I linked above. I’ve seen that page reference in several places discussing RPATH vs RUNPATH since it does a good job differentiating between RPATH and RUNPATH. But then it starts using the word RPATH everywhere. It would be helpful to mention in the “CMake and the RPATH” section that whether RPATH or RUNPATH is used is determined by the linker.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 17, 2024, 5:41am UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/9 "2024-02-17T05:41:34Z")

</div>

[I agree](https://gitlab.kitware.com/cmake/cmake/-/issues/25683#note_1483641). If someone wants to make that documentation page, I can help review it.

---

<div class="post-metadata">

### Author: ![dabrahams](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dabrahams/32/4265_2.png) [@dabrahams](https://discourse.cmake.org/u/dabrahams)
#### Post date: [February 17, 2024, 5:44am UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/10 "2024-02-17T05:44:06Z")

</div>

It needs to be made by someone who actually knows how this part of CMake works. Is there likely to be such a person outside Kitware?

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 17, 2024, 5:53am UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/11 "2024-02-17T05:53:46Z")

</div>

LWN has published an article on how library loading works:

> **[A look at dynamic linking \[LWN.net\]](https://lwn.net/SubscriberLink/961117/4fee35eea3af7e75/)**
>
> The dynamic linker is a critical component of modern Linux systems, being
> responsible for setting up the address space of most processes. While statically
> linked binaries have become more popular over time as the tradeoffs that
> originally led to...

Though it kind of glosses over the library search procedure (though I’ve found `man 8 ld-linux` to be very useful for that).

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 17, 2024, 6:03am UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/12 "2024-02-17T06:03:06Z")

</div>

For documentation, I have found that getting at least a pass over it by a non-expert helps to keep it useful for non-experts. For something like this, I think that describing how it works _at all_ first gives the proper context for the knobs CMake offers abstractions for controlling it (with other things left to platform-specific flags which might be documented for the common use cases).

---

<div class="post-metadata">

### Author: ![dabrahams](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dabrahams/32/4265_2.png) [@dabrahams](https://discourse.cmake.org/u/dabrahams)
#### Post date: [February 17, 2024, 7:12pm UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/13 "2024-02-17T19:12:35Z")

</div>

> [@ben.boeckel](#):
>
> For documentation, I have found that getting at least a pass over it by a non-expert helps to keep it useful for non-experts.

I’ll be the first to volunteer to make such an editorial pass. I volunteer!

---

<div class="post-metadata">

### Author: ![dabrahams](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dabrahams/32/4265_2.png) [@dabrahams](https://discourse.cmake.org/u/dabrahams)
#### Post date: [February 17, 2024, 7:14pm UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/14 "2024-02-17T19:14:14Z")

</div>

> [@ben.boeckel](#):
>
> LWN has published an article on how library loading works:
> 
> [A look at dynamic linking [LWN.net]](https://lwn.net/SubscriberLink/961117/4fee35eea3af7e75/)

Sure, but it’s not CMake’s job to document that. What’s missing from CMake’s documentation is simply what _CMake_ does with these variable settings.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 18, 2024, 3:07am UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/15 "2024-02-18T03:07:39Z")

</div>

I agree; links to these resources may be useful rather than restated in CMake’s documentation. Note that library _search_ is highly relevant to CMake and background is probably far more useful than “how symbols get located at an address”. Things like “why does CMake warn about not being able to make a reliable RPATH ordering?” truly need the background context to really make sense.

---

<div class="post-metadata">

### Author: ![dabrahams](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dabrahams/32/4265_2.png) [@dabrahams](https://discourse.cmake.org/u/dabrahams)
#### Post date: [February 18, 2024, 3:56am UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/16 "2024-02-18T03:56:00Z")

</div>

SGTM. Also there should be some description of the high-level uniform programmer experience CMake is trying to create by handling these different platforms in specific ways.

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [February 18, 2024, 5:05am UTC](https://discourse.cmake.org/t/setting-rpath-and-not-runpath-for-executable/10011/17 "2024-02-18T05:05:32Z")

</div>

The last part of my “Deep CMake For Library Authors” deals specifically with RPATH and RUNPATH, including reference to the equivalent on macOS.

> **[CppCon 2019: Deep CMake For Library Authors](https://crascit.com/2019/10/16/cppcon-2019-deep-cmake-for-library-authors/)**
>
> This talk highlights key CMake features relevant to C++ cross-platform library authors, digging deeper into platform-specific quirks and conventions.
