# How to set -dynamic-linker from the outside?

**URL:** <https://discourse.cmake.org/t/how-to-set-dynamic-linker-from-the-outside/4659>\
**Category:** Code\
**Tags:** os:linux\
**Created:** [December 14, 2021, 2:17pm UTC](https://discourse.cmake.org/t/how-to-set-dynamic-linker-from-the-outside/4659 "2021-12-14T14:17:19Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Adam\_Badura](https://discourse.cmake.org/user_avatar/discourse.cmake.org/adam_badura/32/1058_2.png) [@Adam\_Badura](https://discourse.cmake.org/u/Adam_Badura)\
**Post date:** [December 14, 2021, 2:17pm UTC](https://discourse.cmake.org/t/how-to-set-dynamic-linker-from-the-outside/4659/1 "2021-12-14T14:17:19Z")

</div>

Our project is compiled using various systems (like Yocto, home-grown a’la Maven, etc.) for different platforms, including both native (for example run tests) and target machines (cross-compilation).

One of the challenges we are facing is setting `--rpath` and `-dynamic-linker` properties. So far we have been doing it like

```cmake
add_link_options(
    LINKER:--rpath,<rpath-path>
    LINKER:-dynamic-linker,<dynamic-linker-path>
)

```

where the exact values depended on what is building us and for what platform. Resulting in a rather messy CMake code that dealt mostly with the environment rather than the project itself.

I would like to change that and force specific settings outside of CMake to keep project CMake clean and embed platform and system-specific settings in “recipes” for that configuration. (And with Yocto for example it means no-op since it comes configured correctly.)

It seems the `--rpath` part can be addressed by providing [`CMAKE_BUILD_RPATH`](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_RPATH.html) upon CMake configuration. Hence, the `LINKER:--rpath` part disappears. Yay!

_[Side note] It seems with [`CMAKE_BUILD_RPATH`](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_RPATH.html) also `--rpath-link` is set. As of now, I’m not sure about the consequences, but it seems to work fine._

However, what about the `-dynamic-linker` part? What to provide to CMake during the configuration stage to enforce specific `-dynamic-linker`? Since by itself it seems to be detecting one from the machine I happen to use for building, rather than the one I expect it to use.

Of course, I could use a custom CMake configuration variable to pass the value. But I guess there must be some standard variables or paths checked when looking for this value and it would be better to change the accordingly instead of “cluttering” my CMake code with custom variables.

---

<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:** [December 14, 2021, 8:13pm UTC](https://discourse.cmake.org/t/how-to-set-dynamic-linker-from-the-outside/4659/2 "2021-12-14T20:13:31Z")

</div>

I don’t think CMake provides an abstraction for `-dynamic-linker`. What does it normally do?

---

<div class="post-metadata">

**Author:** ![Adam\_Badura](https://discourse.cmake.org/user_avatar/discourse.cmake.org/adam_badura/32/1058_2.png) [@Adam\_Badura](https://discourse.cmake.org/u/Adam_Badura)\
**Post date:** [December 15, 2021, 6:00am UTC](https://discourse.cmake.org/t/how-to-set-dynamic-linker-from-the-outside/4659/3 "2021-12-15T06:00:35Z")

</div>

Well, I expect it doesn’t have anything direct. I think I would have found it already if it had…

But it does find it _somehow_ since I see that without providing it explicitly with `add_link_options` a different one (local to the build host machine) is used. So, where CMake looks for it? Some sysroot? Prefix? What else?

---

<div class="post-metadata">

**Author:** ![fenrir](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fenrir/32/734_2.png) [@fenrir](https://discourse.cmake.org/u/fenrir)\
**Post date:** [December 15, 2021, 8:13am UTC](https://discourse.cmake.org/t/how-to-set-dynamic-linker-from-the-outside/4659/4 "2021-12-15T08:13:07Z")

</div>

AFAIK the compiler/linker does it by itself (CMake does not mess with that by itself). One has to use `-dynamic-linker` only if one wants to override what the toolchains’ default is. Even in cross-compilation scenario, where you don’t necessarily have the dynamic linker for the target, your toolchain writes something as the dynamic linker into ELF headers.

---

<div class="post-metadata">

**Author:** ![Adam\_Badura](https://discourse.cmake.org/user_avatar/discourse.cmake.org/adam_badura/32/1058_2.png) [@Adam\_Badura](https://discourse.cmake.org/u/Adam_Badura)\
**Post date:** [December 15, 2021, 8:49am UTC](https://discourse.cmake.org/t/how-to-set-dynamic-linker-from-the-outside/4659/5 "2021-12-15T08:49:48Z")

</div>

I have built a project and then `grep`-ed over generated files. The `dynamic-linker` shows in two files:

* * *

**`CMakeFiles/CMakeOutput.log`** (one file, many occurrences)

This one shows the same regardless of whether I have the `add_link_options` or not.

I’m not sure what this file really contains or how to interpret this. But I can see cases like:

```nohighlight
COLLECT_GCC_OPTIONS=(...)
 (...) -dynamic-linker /lib64/ld-linux-x86-64.so.2 (...)
COLLECT_GCC_OPTIONS=(...)

```

```nohighlight
Parsed C implicit link information from the above output:
(...)
  link line: [(...) -dynamic-linker /lib64/ld-linux-x86-64.so.2 (...)]
    (...)
    arg [-dynamic-linker] ==> ignore
    arg [/lib64/ld-linux-x86-64.so.2] ==> ignore
    (...)

```

Then another iteration of “the same” for CXX.

* * *

**`(...)/link.txt`** (many files, single occurrence)

This one shows only if I have the `add_link_options`. Otherwise, the option is missing.

All cases here seem to be like:

```nohighlight
/usr/bin/nice (...) -Wl,-dynamic-linker,<path> (...)

```

where the `<path>` is the one I provided rather than the `/lib64/ld-linux-x86-64.so.2`.

* * *

Without the `add_link_options` the resulting binaries do not load.

It _seems_ like if I could impact the “implicit link information” from `CMakeOutput.log` so that it would pick the right linker and not ignore it I would have it working. But how to?

---

<div class="post-metadata">

**Author:** ![fenrir](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fenrir/32/734_2.png) [@fenrir](https://discourse.cmake.org/u/fenrir)\
**Post date:** [December 15, 2021, 11:32am UTC](https://discourse.cmake.org/t/how-to-set-dynamic-linker-from-the-outside/4659/6 "2021-12-15T11:32:32Z")

</div>

Those are informations provided by your toolchain. Quite possibly extracted from the output of `gcc -dumpspecs` or something like that.

I think your toolchain assumes something about the target that simply is not true (the dynamic loader lacation). To influence that you’d have to use specs files or re-compile your toolchain with some special parameters (both of which is annoying and can be quite difficult to get right).

I’d expect this is the kind of thing that should be somehow possible to set globally in a cmake toolchain file.

---

<div class="post-metadata">

**Author:** ![Adam\_Badura](https://discourse.cmake.org/user_avatar/discourse.cmake.org/adam_badura/32/1058_2.png) [@Adam\_Badura](https://discourse.cmake.org/u/Adam_Badura)\
**Post date:** [December 16, 2021, 11:50am UTC](https://discourse.cmake.org/t/how-to-set-dynamic-linker-from-the-outside/4659/7 "2021-12-16T11:50:06Z")

</div>

By trial and error, I found out that my current (yeah, it should be `-rpath` rather than `--rpath`…):

```auto
add_link_options(
    LINKER:-rpath,<rpath-path>
    LINKER:-dynamic-linker,<dynamic-linker-path>
)

```

could be replaced in a few ways revolving around various variables.

* * *

As of now, I’m going to use:

```nohighlight
LDFLAGS="${LDFLAGS} -Wl,-dynamic-linker,<dynamic-linker-path>"
CMAKE_BUILD_RPATH=<rpath-path>

```

`LDFLAGS` is an environment variable while `CMAKE_BUILD_RPATH` is provided as `-D<var>=<value>` command-line argument do `cmake` configuration call.

However, this particular choice is dictated mostly by the setup we have right now. In a different setup perhaps a different approach would be better.

* * *

For completeness, I will list here variables that seem to be related to the topic:

- environment variables:  
– [`LDFLAGS`](https://cmake.org/cmake/help/latest/envvar/LDFLAGS.html)
- CMake variables:  
– [`CMAKE_SKIP_RPATH`](https://cmake.org/cmake/help/latest/variable/CMAKE_SKIP_RPATH.html)  
– [`CMAKE_BUILD_RPATH`](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_RPATH.html)  
– [`CMAKE_BUILD_RPATH_USE_ORIGIN`](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_RPATH_USE_ORIGIN.html)  
– [`CMAKE_BUILD_WITH_INSTALL_RPATH`](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_WITH_INSTALL_RPATH.html)  
– [`CMAKE_EXE_LINKER_FLAGS`](https://cmake.org/cmake/help/latest/variable/CMAKE_EXE_LINKER_FLAGS.html)  
– [`CMAKE_EXE_LINKER_FLAGS_<CONFIG>`](https://cmake.org/cmake/help/latest/variable/CMAKE_EXE_LINKER_FLAGS_CONFIG.html)  
– [`CMAKE_EXE_LINKER_FLAGS_<CONFIG>_INIT`](https://cmake.org/cmake/help/latest/variable/CMAKE_EXE_LINKER_FLAGS_CONFIG_INIT.html)  
– [`CMAKE_EXE_LINKER_FLAGS_INIT`](https://cmake.org/cmake/help/latest/variable/CMAKE_EXE_LINKER_FLAGS_INIT.html)  
– [`CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH`](https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH.html)  
– [`CMAKE_INSTALL_RPATH`](https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_RPATH.html)  
– [`CMAKE_INSTALL_RPATH_USE_LINK_PATH`](https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH.html)  
– [`CMAKE_MODULE_LINKER_FLAGS`](https://cmake.org/cmake/help/latest/variable/CMAKE_MODULE_LINKER_FLAGS.html)  
– [`CMAKE_MODULE_LINKER_FLAGS_<CONFIG>`](https://cmake.org/cmake/help/latest/variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG.html)  
– [`CMAKE_MODULE_LINKER_FLAGS_<CONFIG>_INIT`](https://cmake.org/cmake/help/latest/variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG_INIT.html)  
– [`CMAKE_MODULE_LINKER_FLAGS_INIT`](https://cmake.org/cmake/help/latest/variable/CMAKE_MODULE_LINKER_FLAGS_INIT.html)  
– [`CMAKE_SHARED_LINKER_FLAGS`](https://cmake.org/cmake/help/latest/variable/CMAKE_SHARED_LINKER_FLAGS.html)  
– [`CMAKE_SHARED_LINKER_FLAGS_<CONFIG>`](https://cmake.org/cmake/help/latest/variable/CMAKE_SHARED_LINKER_FLAGS_CONFIG.html)  
– [`CMAKE_SHARED_LINKER_FLAGS_<CONFIG>_INIT`](https://cmake.org/cmake/help/latest/variable/CMAKE_SHARED_LINKER_FLAGS_CONFIG_INIT.html)  
– [`CMAKE_SHARED_LINKER_FLAGS_INIT`](https://cmake.org/cmake/help/latest/variable/CMAKE_SHARED_LINKER_FLAGS_INIT.html)  
– [`CMAKE_SKIP_BUILD_RPATH`](https://cmake.org/cmake/help/latest/variable/CMAKE_SKIP_BUILD_RPATH.html)  
– [`CMAKE_SKIP_INSTALL_RPATH`](https://cmake.org/cmake/help/latest/variable/CMAKE_SKIP_INSTALL_RPATH.html)  
– [`CMAKE_LANG_LINKER_WRAPPER_FLAG`](https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_LINKER_WRAPPER_FLAG.html)  
– [`CMAKE_LANG_LINKER_WRAPPER_FLAG_SEP`](https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_LINKER_WRAPPER_FLAG_SEP.html)

TBH, I’m somewhat lost in all those options… However, I will share some thoughts on them I have after spending significant time on this topic:

1. I don’t like setting environment variable [`LDFLAGS`](https://cmake.org/cmake/help/latest/envvar/LDFLAGS.html) (because I don’t like dependency on environment variables in general).  
– However, it does save me from setting three variables: [`CMAKE_EXE_LINKER_FLAGS_INIT`](https://cmake.org/cmake/help/latest/variable/CMAKE_EXE_LINKER_FLAGS_INIT.html), [`CMAKE_MODULE_LINKER_FLAGS_INIT`](https://cmake.org/cmake/help/latest/variable/CMAKE_MODULE_LINKER_FLAGS_INIT.html), and [`CMAKE_SHARED_LINKER_FLAGS_INIT`](https://cmake.org/cmake/help/latest/variable/CMAKE_SHARED_LINKER_FLAGS_INIT.html).  
– If using a [`CMAKE_TOOLCHAIN_FILE`](https://cmake.org/cmake/help/latest/variable/CMAKE_TOOLCHAIN_FILE.html), as already suggested by @fenrir, maybe I would opt for separate variables, but having to pass them all via `-D<var>=<value>` seems a bit too verbose.  
– We use [`LDFLAGS`](https://cmake.org/cmake/help/latest/envvar/LDFLAGS.html) already anyway for other flags, I’m not sure how it would behave if I would separately set the `CMAKE_<TYPE>_LINKER_FLAGS_INIT` variables but I expect it would overwrite everything that would be taken from [`LDFLAGS`](https://cmake.org/cmake/help/latest/envvar/LDFLAGS.html) which is not desired.
2. I don’t know if it is better to set `rpath` by linker flags or by CMake variables.  
– I assume CMake variables are better since it will lead to a cleaner situation from CMake’s point of view and avoid conflicts.  
– And also they are more fine-grained. It is easier to have a single variable with single path of clear purpose rather than append to a cumulative options variable.
3. The [`add_link_options`](https://cmake.org/cmake/help/latest/command/add_link_options.html) has a nice `LINKER:` mode that covers specifics of the compiler (for example, `-Wl` for GCC and `-Xlinker` for Clang).  
– When setting the variables manually within CMake you can still use [`CMAKE_LANG_LINKER_WRAPPER_FLAG`](https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_LINKER_WRAPPER_FLAG.html) and [`CMAKE_LANG_LINKER_WRAPPER_FLAG_SEP`](https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_LINKER_WRAPPER_FLAG_SEP.html). Probably non-trivial and verbose to use it correctly, but at least possible.  
– However, when setting them from the outside (which is the whole point of setting them in the first place) you now must cover the compiler specifics on your own and the same settings will not work with both GCC and Clang.

---

<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:** [December 17, 2021, 7:20am UTC](https://discourse.cmake.org/t/how-to-set-dynamic-linker-from-the-outside/4659/8 "2021-12-17T07:20:33Z")

</div>

It sounds like you should be using a toolchain file, which by definition will be specific to one toolchain (so one file for gcc, another file for clang, etc.). In that toolchain file, you can set `CMAKE_EXE_LINKER_FLAGS_INIT`, `CMAKE_SHARED_LINKER_FLAGS_INIT` and `CMAKE_MODULE_LINKER_FLAGS_INIT` to hold whatever custom linker flags you want to enforce. In your case, that would be to add `-Wl,-dynamic-linker,<somePath>` or similar. I’d recommend using `CMAKE_BUILD_RPATH` if you need to enforce a particular RPATH/RUNPATH for binaries in the build directory. That seems a little odd that you’d need to do that though. Normally CMake works out what the build directory RPATH needs to be for each executable, but I don’t know your specific situation.
