In cmake-gui, a list of CMake "options" and "cache entries" are presented to the developer building your project so they can make adjustments to various aspects of your project's build. For example, a common option is BUILD_SHARED_LIBS. If set to ON, then add_library calls default to producing shared libraries. Otherwise, add_library calls default to producing static libraries. This option appears in cmake-gui as a checkbox.

Using the CMake "option" command, it is trivial to add new options to your project. The cmake-gui is tuned to present these options as checkbox controls: checked means the option is ON, unchecked means it is OFF. Other types of cache entries may also appear in cmake-gui. Using the CACHE form of the cmake SET command, you may add cache entries for file names, directory names, or arbitrary strings. Each type of entry has its corresponding type of control: the file names have a browse-for-file control, the directory names have a browse-for-directory control, and the string entries have a free form text editing control.

Sometimes, as a the developer of a CMakeLists.txt file, you would like to present a cache entry whose potential values are restricted to a well-known set of strings. Similar to a list of "enum" values for you C++-heads. With CMake 2.8 and later, it is now possible to present this elegantly with a drop-down combo box appearing for each such cache entry in cmake-gui.

Starting with CMake 2.8.0, we extended the set_property command to enable adding properties to CMake CACHE variables. Specifically, we added a STRINGS property, with the specific intent of providing a container for a list of the possible values that an otherwise free-form STRING cache entry was allowed to have. Then we also extended cmake-gui to be aware of this new property, and to use it to populate a drop-down combo box when a user wants to edit the cache entry's value.

So here's how it works: for each cache entry that you want to constrain to some set of values, define it as usual with a default value as a STRING cache variable, for example:

  set(BaseName "binary" CACHE STRING "BaseName chosen by the user at CMake configure time")

Now, after defining the cache entry with its initial default value, define the set of strings to which its value should be constrained:

  set_property(CACHE BaseName PROPERTY STRINGS binary octal decimal hexadecimal)

After the set_property call, cmake-gui knows to present a drop-down combo box for editing the "BaseName" cache entry, and it knows that the four valid choices for this entry that it should present are binary, octal, decimal and hexadecimal.

The example code presented at the end demonstrates using various techniques to define the list. There is even one technique allowing the user to edit the list of values as a free form STRING entry, and then use those edits on subsequent configures to present (now different) choices in the drop-down combo box for another entry. Whether this technique is wise or not remains to be seen. (I am of the firm opinion that it is probably unwise, in general, but I present it here anyway for completeness, and because it may be useful for some use case that I'm just not thinking of right  now...)

For completeness, I should also mention that there is no code in cmake itself to enforce the constraint that a cache entry must have one of the values mentioned in its corresponding STRINGS property. After editing by cmake-gui, the edited cache entry will have one of the listed values, but if a user runs cmake -Dentry=blah then the entry will have value blah regardless of the listed values in the STRINGS property. If you wish to have fully bulletproof, "this value must be in this list" validation, then you must write code in your CMakeLists.txt file to enforce it.

What follows is a CMakeLists.txt file that demonstrates using the STRINGS cache property for various cache entries to achieve a constrained "limited list of choices" in cmake-gui. Save it and give it a test drive with cmake-gui, it's neato-keen.

##############################################################################
#
# The "set_property(CACHE" capability first appeared in CMake version 2.8.0.
# This file will yield a configure-time error with CMake 2.6.4 and earlier...
#
# See also:
#   http://cmake.org/cmake/help/cmake-2-8-docs.html#property:STRINGS
#   http://cmake.org/cmake/help/cmake-2-8-docs.html#command:set
#
cmake_minimum_required(VERSION 2.8.0 FATAL_ERROR)
project(ChoicesChoices)

#
# The "set_property(CACHE" capability first appeared in CMake version 2.8.0.
# This file will yield a configure-time error with CMake 2.6.4 and earlier...
#

#
# Demonstrate using fixed/programmatically-defined/invisible-to-the-user lists
# to fill drop-down combo boxes in cmake-gui (the "values" used for
# the STRINGS property are either simply hard-coded, local, or of CACHE type
# INTERNAL)
#

#
# hard-coded
#
set(BaseName "binary" CACHE STRING
  "BaseName chosen by the user at CMake configure time")

set_property(CACHE BaseName PROPERTY STRINGS binary octal decimal hexadecimal)

message(STATUS "BaseName='${BaseName}'")

#
# local variable
#
set(Language "English" CACHE STRING
  "Language chosen by the user at CMake configure time")

set(LanguageValues
  "English;Spanish;German;French;Chinese;Japanese;Korean;Hebrew;Arabic;Other")

set_property(CACHE Language PROPERTY STRINGS ${LanguageValues})

message(STATUS "Language='${Language}'")

#
# CACHE INTERNAL
#
set(WrapperLanguage "python" CACHE STRING
  "WrapperLanguage chosen by the user at CMake configure time")

set(WrapperLanguageValues "c#;java;lua;perl;php;python;ruby;tcl" CACHE INTERNAL
  "List of possible values for the Language cache variable")

set_property(CACHE WrapperLanguage PROPERTY STRINGS ${WrapperLanguageValues})

message(STATUS "WrapperLanguage='${WrapperLanguage}'")


#
# Demonstrate using a variable/user-modifiable list to fill a drop-down combo
# box in cmake-gui (the "Values" variable used for the STRINGS property is type
# STRING)
#

set(Color "Red" CACHE STRING
  "Color chosen by the user at CMake configure time")

set(ColorValues "Red;Orange;Yellow;Green;Blue;Violet" CACHE STRING
  "List of possible values for the Color cache variable")

set_property(CACHE Color PROPERTY STRINGS ${ColorValues})

message(STATUS "Color='${Color}'")

Share