# Regenerate/recompile at install time

**URL:** https://discourse.cmake.org/t/regenerate-recompile-at-install-time/3287
**Category:** Usage
**Created:** [May 10, 2021, 2:36pm UTC](https://discourse.cmake.org/t/regenerate-recompile-at-install-time/3287 "2021-05-10T14:36:02Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![cerna](https://discourse.cmake.org/user_avatar/discourse.cmake.org/cerna/32/1299_2.png) [@cerna](https://discourse.cmake.org/u/cerna)
#### Post date: [May 10, 2021, 2:36pm UTC](https://discourse.cmake.org/t/regenerate-recompile-at-install-time/3287/1 "2021-05-10T14:36:03Z")

</div>

Hello,

I am writing a build system for an old project currently using hand-written Make files. In the sourcefiles, there are numerous hard-coded paths to files in the absolute form. (Mostly to the configuration files and as a back-up for the situation when some environment variable is not available, but not all.) The prerequisite for this project is that it should run both in the _BINARY_ tree and installed, thus these hard-coded paths will differ in these situations.

**As it is very similar to the RPATH problem, I am thinking if there is any solution in CMake which would allow me to recompile/relink/regenerate objects (objects in the general form) at install time?**

So far what I was doing is to collect them all in one STATIC library (so I can track them all in simple manner) - in the original Makefile they were passed as simple _DEFINE_s, so I created a config file where these are defined as `extern` symbol. Then created this symbol in library.

As a hack, I could change this _STATIC_ library to _SHARED_ one and use the symbol interposition hack to create two libraries during build time, one for the _BINARY_ tree and the other for the installed location. In _BINARY_ tree, the dependencies would have the `RPATH` set to the build library and during installation only the second, install one would be installed and `RPATH` set.

However, this feels ugly. Is there a better way?

---

<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: [May 10, 2021, 3:04pm UTC](https://discourse.cmake.org/t/regenerate-recompile-at-install-time/3287/2 "2021-05-10T15:04:18Z")

</div>

> [@cerna](#):
>
> As it is very similar to the RPATH problem, I am thinking if there is any solution in CMake which would allow me to recompile/relink/regenerate objects (objects in the general form) at install time?

CMake does not provide such functionality.

> [@cerna](#):
>
> However, this feels ugly. Is there a better way?

Yes. Use APIs such as `dlsym` and `dladdr` to get the location of the shared library[1] containing a given symbol on-disk (Windows has analogous APIs). Then, use the CMake-configured information about where the library lives in the install prefix and then compute where the data is relative to that prefix. Things to note:

- it requires the install and build trees be laid out in the same way
- it requires that the prefix not be symlinked into through an incompatible view (can give more details if it matters; really only visible on things like Nix or Homebrew)
- setting up the `OUTPUT_DIRECTORY` variables to match the install tree destinations is manual
- I’m unsure how easy this is to do in practice with multi-config generators; so far I’ve been lucky to just ignore them, but there are likely details about that which will need figured out.

[1] Note that this does not work well for static builds; the final executable likely needs to provide some information about where the data lives next to it for this case.

---

<div class="post-metadata">

### Author: ![cerna](https://discourse.cmake.org/user_avatar/discourse.cmake.org/cerna/32/1299_2.png) [@cerna](https://discourse.cmake.org/u/cerna)
#### Post date: [May 11, 2021, 12:40pm UTC](https://discourse.cmake.org/t/regenerate-recompile-at-install-time/3287/3 "2021-05-11T12:40:03Z")

</div>

> [@ben.boeckel](#):
>
> Yes. Use APIs such as `dlsym` and `dladdr` to get the location of the shared library[1] containing a given symbol on-disk (Windows has analogous APIs).

Thank you for the reply, however I don’t think I completely understand your proposal. The software is based on plug-in extensibility heavily using the `DLSYM` functionality, so I was already trying to consolidate _OUTPUT_s from builds to tree similar to the install one. (Lets say I am going to use the `GNUInstallDirs` module to create build tree like:

```bash
$<CONFIG>/lib
$<CONFIG>/libexec
$<CONFIG>/bin
$<CONFIG>/etc
$<CONFIG>/python-index
...(etc)...

```

In other words the output artifacts would be grouped under `$<CONFIG>` mount-point.)

Problem is, I need to point to the default location of config files. If I understand correctly, you are saying to use relative paths from the executable/library to the configure file instead of the current absolute ones. That would certainly make the software more relocatable. However, it would also mean that the output directory structure in the `CMAKE_BINARY_TREE` would not be stable, as with `CMAKE_INSTALL_PREFIX` set to `/usr`, the tree would be:

```bash
$<CONFIG>/usr/lib
$<CONFIG>/usr/libexec
$<CONFIG>/usr/bin
$<CONFIG>/etc
$<CONFIG>/python-index

```

Right? (As the configuration files will mostly live in `etc`, it is important for installed version. Because it can be `/etc` or `/usr/local/etc` or `/opt/<org_name>/etc` and similar.)

(Just to be clear, the `libconfig` is just a header and ELF file with very few symbols pointing to `.rodata` section, where the absolute paths to some other locations are stored. It will live in the same `*/lib` as any other library from this project.)

BTW, this is a Linux only project.

---

<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: [May 11, 2021, 2:29pm UTC](https://discourse.cmake.org/t/regenerate-recompile-at-install-time/3287/4 "2021-05-11T14:29:27Z")

</div>

Ah, yeah, `/etc` is a pain. Because if you’re under `/usr/local`, I’ve seen some things (e.g., BSD Ports) use `/usr/local/etc` where everything _does_ just work, but then distros tend to stuff everything under `/usr` and `/etc` is “in the wind”. For this, I would just hard-code `/etc` as a search location since it is relative to the entire system in such situations. A flag for whether that is absolute or prefix-relative is probably warranted as well.

---

<div class="post-metadata">

### Author: ![cerna](https://discourse.cmake.org/user_avatar/discourse.cmake.org/cerna/32/1299_2.png) [@cerna](https://discourse.cmake.org/u/cerna)
#### Post date: [May 18, 2021, 6:34pm UTC](https://discourse.cmake.org/t/regenerate-recompile-at-install-time/3287/5 "2021-05-18T18:34:01Z")

</div>

Yesterday, I happened to discover that when you set the `CMAKE_INSTALL_PREFIX` on Debian system to `/usr`, it will set the `CMAKE_INSTALL_LIBEXECDIR` to `lib/<compiler-triplet>` instead of `libexec` as one would presume, so for example the output artifacts are in `${CMAKE_BINARY_DIR}/Debug/lib/x86_64-linux-gnu` and not in `${CMAKE_BINARY_DIR}/Debug/libexec`.

So, given that the `CMAKE_INSTALL_PREFIX` is already influencing the `GNUInstallDirs` based on OS and such, it probably makes sense to prepend the `*_OUTPUT` directories with the `usr/` for all but `etc`. (Not sure how it would be implemented in CMake, I haven’t studied the source much yet.)

* * *

I have been playing with Ninja Multi-Config in connection with `configure_file()` followed by `file(GENERATE)` and I think that most of the configuration file generation issues could be solved by some clever application of generator expressions. (_Are you generating the file for the BINARY tree build? Then use this string. Are you generating this file for installation? Then use this other string._)
