Turning CMake into a good UNIX citizen
CMake, the software build system, describes itself as:
Welcome to CMake, the cross-platform, open-source build system. CMake is a family of tools designed to build, test and package software.
However, CMake cannot keep its promises and fails with respect to packaging1. Writing software with CMake that builds everywhere is possible but in some cases not very easy and, although CMake provides its own packaging mechanism called CPack, it can only serve as a temporary solution.
The main problem on UNIX-like systems is the amount of freedom concerning installation paths. There are no guidelines where things have to go and how the paths are set up. Yes, CMake allows you to set the installation prefix by using
cmake . -DCMAKE_INSTALL_PREFIX=/usr
however, this is not enough to cover all cases. For example, the location of a
64-bit library is /usr/lib
on Debian systems and /usr/lib64
on openSUSE
systems. In an autotools-based system, you would just set --libdir
to the
appropriate location. Not so with CMake. People write all kinds of gruesome
hacks to figure this out at build time much to mental state of package
maintainers. Moreover, even if one user gets this whole mess right, a thousand
others won’t.
To fix this problem for my own software systems, I wrote the ConfigurePaths module which would be used like this:
include(ConfigurePaths)
configure_paths(FOO)
Simple, eh? With this call, you populated your global CMake namespace with
cached path variables that mimic the system variables known from configure
scripts:
# header files
install(FILES bar.h
DESTINATION ${FOO_INCLUDEDIR})
# libraries
install(TARGETS bar
LIBRARY DESTINATION ${FOO_LIBDIR})
# binaries
install(TARGETS baruser
RUNTIME DESTINATION ${FOO_BINDIR})
# pkg-config
install(FILES bar.pc
DESTINATION ${FOO_PKGCONFIGDIR})
# ...
By default, all variables are set to the configure
defaults, e.g. FOO_PREFIX
is /usr/local
, FOO_DATADIR
is FOO_PREFIX/share
, and so on. The user can
override the default values by CMake means, for example:
$ cmake . -DPREFIX=/opt -DLIBDIR=/usr/lib64
Rather than convincing you to use this, I really just want to encourage you to think about the whole mess. In the end, it may turn out that you have to package the software yourself.
I deliberately do not bash the ugly syntax here. Or say that autotools is a much better build tool on UNIX systems. No, no, I won’t.