# Inconsistencies with install() and relative path to GNUInstallDirs

**URL:** https://discourse.cmake.org/t/inconsistencies-with-install-and-relative-path-to-gnuinstalldirs/12656
**Category:** Code
**Created:** [September 29, 2024, 4:15pm UTC](https://discourse.cmake.org/t/inconsistencies-with-install-and-relative-path-to-gnuinstalldirs/12656 "2024-09-29T16:15:01Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![petk](https://discourse.cmake.org/user_avatar/discourse.cmake.org/petk/32/4555_2.png) [@petk](https://discourse.cmake.org/u/petk)
#### Post date: [September 29, 2024, 4:15pm UTC](https://discourse.cmake.org/t/inconsistencies-with-install-and-relative-path-to-gnuinstalldirs/12656/1 "2024-09-29T16:15:01Z")

</div>

Hello,

I’m just reading and adapting a project for the installation phase which uses the GNUInstallDirs module:  
[https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html](https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html)

The module documentation mentions some special cases, where, for example, when the install prefix is `/usr`, the `CMAKE_INSTALL_FULL_SYSCONFDIR` becomes `/etc` instead of the `/usr/etc`, and similar.

However, the CMake’s `install()` command doesn’t adjust the destination according to these special cases.

Is this considered a CMake bug, or is this something that projects should adapt by themselves, or is this something that the installation phase should adapt via the `CMAKE_INSTALL_*` variables by themselves?

There is also a bug opened here  
[https://gitlab.kitware.com/cmake/cmake/-/issues/25852](https://gitlab.kitware.com/cmake/cmake/-/issues/25852)

What would be the correct approach here at this point?

Thank you much in advance for any pointers here.

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [September 30, 2024, 5:58pm UTC](https://discourse.cmake.org/t/inconsistencies-with-install-and-relative-path-to-gnuinstalldirs/12656/2 "2024-09-30T17:58:56Z")

</div>

See [special-cases](https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html#special-cases)

---

<div class="post-metadata">

### Author: ![petk](https://discourse.cmake.org/user_avatar/discourse.cmake.org/petk/32/4555_2.png) [@petk](https://discourse.cmake.org/u/petk)
#### Post date: [September 30, 2024, 6:04pm UTC](https://discourse.cmake.org/t/inconsistencies-with-install-and-relative-path-to-gnuinstalldirs/12656/3 "2024-09-30T18:04:34Z")

</div>

I did. Exactly these special cases aren’t taken into consideration when using the install() command and the installation prefix is set at the install phase (`cmake --install ... --prefix /usr`). In this case the libraries will be installed to “lib” instead of “lib/x86\_64-linux-gnu”. If the install prefix is set at the configuration phase (-DCMAKE\_INSTALL\_PREFIX=/usr) then they are installed to “lib/x86\_64-linux-gnu”, which makes the entire special cases inconsistent in CMake.

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [September 30, 2024, 6:20pm UTC](https://discourse.cmake.org/t/inconsistencies-with-install-and-relative-path-to-gnuinstalldirs/12656/4 "2024-09-30T18:20:02Z")

</div>

see too [CPack empty archive with absolute install DESTINATION path](https://discourse.cmake.org/t/cpack-empty-archive-with-absolute-install-destination-path/11503)

I do not know for what the `CMAKE_INSTALL_FULL_XXX` vars are, but I would not use them!

---

<div class="post-metadata">

### Author: ![petk](https://discourse.cmake.org/user_avatar/discourse.cmake.org/petk/32/4555_2.png) [@petk](https://discourse.cmake.org/u/petk)
#### Post date: [September 30, 2024, 6:32pm UTC](https://discourse.cmake.org/t/inconsistencies-with-install-and-relative-path-to-gnuinstalldirs/12656/5 "2024-09-30T18:32:37Z")

</div>

For what it’s worth, the CMAKE\_INSTALL\_LIBDIR is relative path (not related here to the CMAKE\_INSTALL\_FULL\_LIBDIR) and it gets changed based on the install prefix. But only if the install prefix is set during the configuration phase. It is not changed if the install prefix is set at the install phase. Meaning, I don’t use these CMAKE\_INSTALL\_FULL\_\* variables either. But I do get different but inconsistent CMAKE\_INSTALL\_\* relative path variables.

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [September 30, 2024, 7:28pm UTC](https://discourse.cmake.org/t/inconsistencies-with-install-and-relative-path-to-gnuinstalldirs/12656/6 "2024-09-30T19:28:58Z")

</div>

### Do you mean this strange behaviour:

```bash
bash-5.2$ cmake --preset default --fresh
Preset CMake variables:

  BUILD_SHARED_LIBS="NO"
  CMAKE_BUILD_TYPE="Release"
  CMAKE_CXX_STANDARD="20"
  CMAKE_DEBUG_POSTFIX="D"
  CMAKE_INSTALL_PREFIX="/usr"
  CMAKE_PREFIX_PATH:STRING="/Users/clausklein/Workspace/cpp/ModernCmakeStarter/stagedir"

Preset environment variables:

  CPM_USE_LOCAL_PACKAGES="YES"
  
-- The CXX compiler identification is AppleClang 16.0.0.16000026
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Git: /usr/local/bin/git (found version "2.46.2")
-- CPM: Adding package project_options@0.30.0 (v0.30.0 at /Users/clausklein/.cache/CPM/project_options/2de06ed3a4c11a5a7ebda8b90d2dd05882bbb095)
-- CPM: Adding package PackageProject.cmake@1.10.0 (v1.10.0 at /Users/clausklein/.cache/CPM/packageproject.cmake/41b1a5028ad2c8d2c6bb64eb6beff8b090d304e5)
-- CPM: Using local package fmt@10.0.0
-- Developer mode is OFF. For developement, use `-DENABLE_DEVELOPER_MODE:BOOL=ON`. Building the project for the end-user...
-- The default CMAKE_C_STANDARD used by external targets and tools is not set yet. Using the latest supported C standard that is 90
-- /usr/local/bin/ccache found and enabled
-- Configuring done (0.5s)
-- Generating done (0.0s)
-- Build files have been written to: /Users/clausklein/Workspace/cpp/ModernCmakeStarter/build/user
bash-5.2$ DESTDIR=/tmp/test cmake --install build/user              
-- Install configuration: "Release"
-- Up-to-date: /tmp/test/usr/etc/test.cfg
-- Up-to-date: /tmp/test/usr/include/greeter
-- Up-to-date: /tmp/test/usr/include/greeter/greeter
-- Up-to-date: /tmp/test/usr/include/greeter/greeter/version.h
-- Installing: /tmp/test/usr/lib/greeter/libgreeter.a
-- Installing: /tmp/test/usr/lib/cmake/greeter/greeterTargets.cmake
-- Installing: /tmp/test/usr/lib/cmake/greeter/greeterTargets-release.cmake
-- Up-to-date: /tmp/test/usr/lib/cmake/greeter/greeterConfigVersion.cmake
-- Up-to-date: /tmp/test/usr/lib/cmake/greeter/greeterConfig.cmake
-- Up-to-date: /tmp/test/usr/include/greeter
-- Up-to-date: /tmp/test/usr/include/greeter/greeter
-- Up-to-date: /tmp/test/usr/include/greeter/greeter/greeter.h
bash-5.2$ sudo cmake --install build/user 
Password:
-- Install configuration: "Release"
CMake Error at build/user/cmake_install.cmake:41 (file):
  file cannot create directory: /usr/etc. Maybe need administrative
  privileges.

bash-5.2$ 

```

---

<div class="post-metadata">

### Author: ![petk](https://discourse.cmake.org/user_avatar/discourse.cmake.org/petk/32/4555_2.png) [@petk](https://discourse.cmake.org/u/petk)
#### Post date: [September 30, 2024, 8:08pm UTC](https://discourse.cmake.org/t/inconsistencies-with-install-and-relative-path-to-gnuinstalldirs/12656/7 "2024-09-30T20:08:05Z")

</div>

A very simple reproducible example:

```cmake
# CMakeLists.txt
cmake_minimum_required(VERSION 3.25 FATAL_ERROR)

project(TestingInstallation LANGUAGES C)

include(GNUInstallDirs)

add_library(testinginstallation SHARED lib.c)

include(GNUInstallDirs)

install(
  TARGETS testinginstallation
)

```

```c
/* lib.c */
int foo(void) { return 0; }

```

Then here the first installation sets the installation prefix to `/usr` in the configuration step, which sets the `CMAKE_INSTALL_LIBDIR` to `lib/x86_64-linux-gnu` on Debian-based machines (Ubuntu included):

```sh
# Shell commands
cmake -S . -B build-1 --install-prefix /usr
cmake --build build-1 -j
DESTDIR=/home/user/testing-installation/1 cmake --install build-1

```

```sh
/home/user/testing-installation/1
└── usr
    └── lib
        └── x86_64-linux-gnu
            └── libtestinginstallation.so

```

The 2nd installation sets the installation prefix `/usr` (same as above) but in the installation phase using the `--prefix` option:

```sh
# Shell commands
cmake -S . -B build-2
cmake --build build-2 -j
DESTDIR=/home/user/testing-installation-2 cmake --install build-2 --prefix /usr

```

Difference in the installation directory structure here is that the libdir is the `lib` without the machine/architecture subdirectory:

```sh
/home/user/testing-installation/2
└── usr
    └── lib
        └── libtestinginstallation.so

```

Same issue happens with all these mentioned special cases in the `GNUInstallDirs` module.

I think I’ll start resolving this for now by creating a custom install module that overrides the CMake’s install commands that I use and have all the `CMAKE_INSTALL_*` variables available in their adjusted form in the install() scripts. Another option would be to not use the `--prefix` option in the `cmake --install` phase and warn about this in the documentation. But I would probably miss something then here for the CPack etc.

It would be kind of good for CMake to address these issues in the CMake code directly instead of users needing to do this kind of adjustments or that the packager needs to set all the `CMAKE_INSTALL_*` variables when packaging the software.

Because this is too difficult to get right and it makes the installation phase too cumbersome to use for the projects.

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [October 2, 2024, 7:29am UTC](https://discourse.cmake.org/t/inconsistencies-with-install-and-relative-path-to-gnuinstalldirs/12656/8 "2024-10-02T07:29:04Z")

</div>

> [@petk](#):
>
> when the install prefix is `/usr`, the `CMAKE_INSTALL_FULL_SYSCONFDIR` becomes `/etc` instead of the `/usr/etc`, and similar.

Yes, that is true, but `CMAKE_INSTALL_SYSCONFDIR` is `usr/etc`, if the installation is redirected with `DESTDIR=/tmp/stagedir cmake --install ...`

@ben.boeckel this seeam a CMake bug or stange feature?

see [Inconsistencies with install() and relative path to GNUInstallDirs - #6 by ClausKlein](https://discourse.cmake.org/t/inconsistencies-with-install-and-relative-path-to-gnuinstalldirs/12656/6)
