# GNUInstallDirs: Special CMAKE\_INSTALL\_FULL\_\<dir\> contain double slash for CMAKE\_INSTALL\_PREFIX starting with /opt when CMP0192 is OLD

**URL:** https://discourse.cmake.org/t/gnuinstalldirs-special-cmake-install-full-dir-contain-double-slash-for-cmake-install-prefix-starting-with-opt-when-cmp0192-is-old/15879
**Category:** Development
**Tags:** os:linux, tool:cmake
**Created:** [October 18, 2026, 12:51am UTC](https://discourse.cmake.org/t/gnuinstalldirs-special-cmake-install-full-dir-contain-double-slash-for-cmake-install-prefix-starting-with-opt-when-cmp0192-is-old/15879 "2026-10-18T00:51:19Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![michael-g-matthews](https://discourse.cmake.org/user_avatar/discourse.cmake.org/michael-g-matthews/32/5540_2.png) [@michael-g-matthews](https://discourse.cmake.org/u/michael-g-matthews)
#### Post date: [October 18, 2026, 12:51am UTC](https://discourse.cmake.org/t/gnuinstalldirs-special-cmake-install-full-dir-contain-double-slash-for-cmake-install-prefix-starting-with-opt-when-cmp0192-is-old/15879/1 "2026-10-18T00:51:19Z")

</div>

Hi all,

I believe I’ve run into a small bug in `GNUInstallDirs` and wanted to check here before opening an issue.

When `CMAKE_INSTALL_PREFIX` is under `/opt/` and CMP0192 is OLD or unset, the FHS special case produces a doubled separator. `CMAKE_INSTALL_FULL_SYSCONFDIR` comes out as `/etc//opt/foo` instead of `/etc/opt/foo`, and `CMAKE_INSTALL_FULL_LOCALSTATEDIR` and `CMAKE_INSTALL_FULL_RUNSTATEDIR` have the same problem. The [special cases documentation](https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html#special-cases) says “the `SYSCONFDIR` value `etc` becomes `/etc/opt/...`”, so I don’t think the `//` is intended. I noticed it because installing to `CMAKE_INSTALL_FULL_SYSCONFDIR` triggers the CMP0177 warning, since normalizing would change the path.

```cmake
cmake_minimum_required(VERSION 3.25)
project(Foo C)
set(CMAKE_INSTALL_PREFIX /opt/foo)
include(GNUInstallDirs)
message("SYSCONFDIR: ${CMAKE_INSTALL_FULL_SYSCONFDIR}")
message("LOCALSTATEDIR: ${CMAKE_INSTALL_FULL_LOCALSTATEDIR}")
message("RUNSTATEDIR: ${CMAKE_INSTALL_FULL_RUNSTATEDIR}")
install(FILES CMakeLists.txt DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR})

```

Output:

```txt
SYSCONFDIR: /etc//opt/foo
LOCALSTATEDIR: /var//opt/foo
RUNSTATEDIR: /var/run//opt/foo
CMake Warning (policy) at CMakeLists.txt:8 (install):
  Policy CMP0177 is not set: install() DESTINATION paths are normalized. Run
  "cmake --help-policy CMP0177" for policy details. Use the cmake_policy
  command to set the policy and suppress this warning.
This warning is for project developers. Use -Wno-author or -Wno-policy to
suppress it.

```

Setting CMP0177 silences the warning, but the `//` is still there. Only CMP0192 NEW gives clean values. Results with a fresh build directory each time:

| CMP0177 | CMP0192 | CMP0177 warning | `FULL_<dir>` values |
| --- | --- | --- | --- |
| unset | unset | yes | contain `//` |
| unset | OLD | yes | contain `//` |
| unset | NEW | no | normalized |
| OLD or NEW | unset or OLD | no | contain `//` |
| OLD or NEW | NEW | no | normalized |

From reading `Modules/GNUInstallDirs.cmake`, I think the cause is `_GNUInstallDirs_special_absolute`, which builds the path as `"/${original_path}/${install_prefix}"`. The prefix already starts with `/`, so the result is `/etc//opt/foo`. Both policy settings go through this helper. The difference is whether the result gets normalized afterwards:

- CMP0192 NEW: `__GNUInstallDirs_default_in_root` applies the special case when computing the default `CMAKE_INSTALL_SYSCONFDIR`, then runs `cmake_path(NORMAL_PATH)`, and `/etc/opt/foo` is cached. That value is already absolute, so `GNUInstallDirs_get_absolute_install_dir` copies it into `CMAKE_INSTALL_FULL_SYSCONFDIR` unchanged.
- CMP0192 OLD: the cached default stays relative (`etc`), and `GNUInstallDirs_get_absolute_install_dir` calls `_GNUInstallDirs_special_absolute` itself without normalizing, so the `//` ends up in `CMAKE_INSTALL_FULL_SYSCONFDIR`.

So as far as I can tell, CMP0192 behaves as documented. Its NEW behavior just happens to hide the doubled separator. The RunCMake GNUInstallDirs tests set CMP0192 NEW for every case, which may be why the OLD path wasn’t caught.

I’m using CMake 4.4.4 on Ubuntu 26.04.1 LTS, and the same code looks unchanged on current master commit (5856adc). I think the cleanest fix is to normalize the result in `GNUInstallDirs_get_absolute_install_dir`, either just for the special-case directories or for every `FULL_<dir>`, depending on how much of a behavior change is acceptable. Normalizing inside `_GNUInstallDirs_special_absolute` would also work.

Does this look like a bug worth an issue, or am I missing something? I’m happy to open an issue or put together a merge request, including a test for the CMP0192 OLD case.

---

<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: [October 18, 2026, 7:49pm UTC](https://discourse.cmake.org/t/gnuinstalldirs-special-cmake-install-full-dir-contain-double-slash-for-cmake-install-prefix-starting-with-opt-when-cmp0192-is-old/15879/2 "2026-10-18T19:49:05Z")

</div>

Thanks for the explanation. Yes, I think opening an issue for this seems appropriate. If you’re happy to make a merge request to fix it too, that would also be welcome.

---

<div class="post-metadata">

### Author: ![michael-g-matthews](https://discourse.cmake.org/user_avatar/discourse.cmake.org/michael-g-matthews/32/5540_2.png) [@michael-g-matthews](https://discourse.cmake.org/u/michael-g-matthews)
#### Post date: [October 19, 2026, 3:46am UTC](https://discourse.cmake.org/t/gnuinstalldirs-special-cmake-install-full-dir-contain-double-slash-for-cmake-install-prefix-starting-with-opt-when-cmp0192-is-old/15879/3 "2026-10-19T03:46:08Z")

</div>

Thanks! I’ve opened [#28186](https://gitlab.kitware.com/cmake/cmake/-/work_items/28186) and submitted a merge request with a fix and additional tests: [!12673](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/12673)
