Skip to content

Inconsistencies with install() and relative path to GNUInstallDirs

CMake implementation of install() seems inconsistent with what the documentation recommends.

Current documentation

The documentation of install() specifies that:

DESTINATION <dir>

Specify the directory on disk to which a file will be installed. <dir> should be a relative path. An absolute path is allowed, but not recommended.

[…]

To make packages compliant with distribution filesystem layout policies, if projects must specify a DESTINATION, it is strongly recommended that they use a path that begins with the appropriate relative GNUInstallDirs variable.

and the documentation of GNUInstallDirs specifies that:

CMAKE_INSTALL_<dir>

Destination for files of a given type. This value may be passed to the DESTINATION options of install() commands for the corresponding file type. It should be a path relative to the installation prefix so that it can be converted to an absolute path in a relocatable way.

While absolute paths are allowed, they are not recommended as they do not work with the cmake --install command's --prefix option, or with the cpack installer generators. In particular, there is no need to make paths absolute by prepending CMAKE_INSTALL_PREFIX; this prefix is used by default if the DESTINATION is a relative path.

GNUInstallDirs with different CMAKE_INSTALL_PREFIX

Here is a table of the install directories computed by GNUInstallDirs depending on CMAKE_INSTALL_PREFIX on a Debian machine:

Prefix/Dir /usr /usr/local /home/foo
BINDIR relative=bin, full=/usr/bin relative=bin, full=/usr/local/bin relative=bin, full=/home/foo/bin
SBINDIR relative=sbin, full=/usr/sbin relative=sbin, full=/usr/local/sbin relative=sbin, full=/home/foo/sbin
LIBEXECDIR relative=libexec, full=/usr/libexec relative=libexec, full=/usr/local/libexec relative=libexec, full=/home/foo/libexec
SYSCONFDIR relative=etc, full=/etc relative=etc, full=/usr/local/etc relative=etc, full=/home/foo/etc
SHAREDSTATEDIR relative=com, full=/usr/com relative=com, full=/usr/local/com relative=com, full=/home/foo/com
LOCALSTATEDIR relative=var, full=/var relative=var, full=/usr/local/var relative=var, full=/home/foo/var
RUNSTATEDIR relative=var/run, full=/var/run relative=var/run, full=/usr/local/var/run relative=var/run, full=/home/foo/var/run
LIBDIR relative=lib/x86_64-linux-gnu, full=/usr/lib/x86_64-linux-gnu relative=lib, full=/usr/local/lib relative=lib, full=/home/foo/lib
INCLUDEDIR relative=include, full=/usr/include relative=include, full=/usr/local/include relative=include, full=/home/foo/include
OLDINCLUDEDIR relative=/usr/include, full=/usr/include relative=/usr/include, full=/usr/include relative=/usr/include, full=/usr/include
DATAROOTDIR relative=share, full=/usr/share relative=share, full=/usr/local/share relative=share, full=/home/foo/share
DATADIR relative=share, full=/usr/share relative=share, full=/usr/local/share relative=share, full=/home/foo/share
INFODIR relative=share/info, full=/usr/share/info relative=share/info, full=/usr/local/share/info relative=share/info, full=/home/foo/share/info
LOCALEDIR relative=share/locale, full=/usr/share/locale relative=share/locale, full=/usr/local/share/locale relative=share/locale, full=/home/foo/share/locale
MANDIR relative=share/man, full=/usr/share/man relative=share/man, full=/usr/local/share/man relative=share/man, full=/home/foo/share/man
DOCDIR relative=share/doc/test, full=/usr/share/doc/test relative=share/doc/test, full=/usr/local/share/doc/test relative=share/doc/test, full=/home/foo/share/doc/test

Problem

The problem is that when the prefix is /usr, it is not possible to use a relative path to install in SYSCONFDIR.

install(
  FILES foo.txt
  TYPE SYSCONF # or DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}
)

It will install in /usr/etc instead of /etc. It means that we have to use CMAKE_INSTALL_FULL_<dir> for this case which:

  1. is contrary to the documentation
  2. prevents usage of the --prefix option

Related to https://discourse.cmake.org/t/gnuinstalldir-differences-in-prefix-paths-and-inconsistency-with-documentation/5102.

Edited by Damien
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information