Find out which options the traditional configuration offers to the users (for example, by running ./configure --help). The Vim project offers a very long list of options and flags and to keep the discussion in this chapter simple, we will implement only four of the options on the CMake side:
--disable-netbeans Disable NetBeans integration support.
--disable-channel Disable process communication support.
--enable-terminal Enable terminal emulation support.
--with-features=TYPE tiny, small, normal, big or huge (default: huge)
We will also ignore any GUI support and emulate --enable-gui=no, since it would complicate the example without significantly adding to the learning outcome.
We will place the following options and defaults in CMakeLists.txt:
option(ENABLE_NETBEANS "Enable netbeans" ON)
option(ENABLE_CHANNEL "Enable channel" ON)
option(ENABLE_TERMINAL "Enable terminal" ON)
We will emulate the --with-features flag using a variable, FEATURES, that can be defined with cmake -D FEATURES=value. We make sure that if FEATURES is not set, it defaults to "huge":
if(NOT FEATURES)
set(FEATURES "huge" CACHE STRING
"FEATURES chosen by the user at CMake configure time")
endif()
We also make sure that users provide a valid value for FEATURES:
list(APPEND _available_features "tiny" "small" "normal" "big" "huge")
if(NOT FEATURES IN_LIST _available_features)
message(FATAL_ERROR "Unknown features: \"${FEATURES}\". Allowed values are: ${_available_features}.")
endif()
set_property(CACHE FEATURES PROPERTY STRINGS ${_available_features})
The last line, containing set_property(CACHE FEATURES PROPERTY STRINGS ${_available_features}), has the nice effect that when configuring the project using cmake-gui, the user is presented with a selection field for FEATURES listing all available features that we have defined already (see also https://blog.kitware.com/constraining-values-with-comboboxes-in-cmake-cmake-gui/).
The options can either be placed in the top-level CMakeLists.txt (as we have done here) or they can be defined close to the targets that query ENABLE_NETBEANS, ENABLE_CHANNEL, ENABLE_TERMINAL, and FEATURES. The former strategy has the advantage that options are listed in one place and one does not need to traverse a tree of CMakeLists.txt files to find the definition of an option. Since we have not defined any targets yet, we can start with keeping the options in a central file, but we may later move the option definition closer to the targets to localize scope and arrive at more reusable CMake building blocks.