3.6.2. Cache variables¶
Cache variables saved in CMakeCache.txt file:
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
set(abc "687" CACHE STRING "")
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -Hcache-cmakecachetxt -B_builds
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
[usage-of-variables]> grep abc _builds/CMakeCache.txt
abc:STRING=687
3.6.2.1. No scope¶
Unlike regular variables CMake cache variables have no scope and are set globally:
# Top level CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
add_subdirectory(boo)
message("A: ${A}")
# CMakeLists.txt from 'boo' directory
set(A "123" CACHE STRING "")
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -Hcache-no-scope -B_builds
A: 123
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
3.6.2.2. Double set¶
If variable is already in cache then command set(... CACHE ...)
will have no
effect - old variable will be used still:
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
set(abc "123" CACHE STRING "")
message("Variable from cache: ${abc}")
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cp double-set/1/CMakeLists.txt double-set/
[usage-of-variables]> cmake -Hdouble-set -B_builds
Variable from cache: 123
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
[usage-of-variables]> grep abc _builds/CMakeCache.txt
abc:STRING=123
Update CMakeLists.txt (don’t remove cache!):
--- /home/docs/checkouts/readthedocs.org/user_builds/cgold/checkouts/latest/docs/examples/usage-of-variables/double-set/1/CMakeLists.txt
+++ /home/docs/checkouts/readthedocs.org/user_builds/cgold/checkouts/latest/docs/examples/usage-of-variables/double-set/2/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
-set(abc "123" CACHE STRING "")
+set(abc "789" CACHE STRING "")
message("Variable from cache: ${abc}")
[usage-of-variables]> cp double-set/2/CMakeLists.txt double-set/
[usage-of-variables]> cmake -Hdouble-set -B_builds
Variable from cache: 123
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
[usage-of-variables]> grep abc _builds/CMakeCache.txt
abc:STRING=123
3.6.2.3. -D¶
Cache variable can be set by -D
command line option. Variable that set by
-D
option take priority over set(... CACHE ...)
command.
[usage-of-variables]> cmake -Dabc=444 -Hdouble-set -B_builds
Variable from cache: 444
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
[usage-of-variables]> grep abc _builds/CMakeCache.txt
abc:STRING=444
3.6.2.4. Initial cache¶
If there are a lot of variables to set it’s not so convenient to use -D
.
In this case user can define all variables in separate file and load
it by -C
:
# cache.cmake
set(A "123" CACHE STRING "")
set(B "456" CACHE STRING "")
set(C "789" CACHE STRING "")
# CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
message("A: ${A}")
message("B: ${B}")
message("C: ${C}")
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -C initial-cache/cache.cmake -Hinitial-cache -B_builds
loading initial cache file initial-cache/cache.cmake
A: 123
B: 456
C: 789
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
3.6.2.5. Force¶
If you want to set cache variable even if it’s already present in cache file
you can add FORCE
:
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
set(A "123" CACHE STRING "" FORCE)
message("A: ${A}")
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -DA=456 -Hforce -B_builds
A: 123
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
This is quite surprising behavior for user and conflicts with the nature of cache variables that was designed to store variable once and globally.
Warning
FORCE
usually is an indicator of badly designed CMake code.
3.6.2.6. Force as a workaround¶
FORCE
can be used to fix the problem that described
earlier:
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
set(A "123")
set(A "456" CACHE STRING "")
message("A: ${A}")
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -Hno-force-confuse -B_builds
A: 456
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
[usage-of-variables]> cmake -Hno-force-confuse -B_builds
A: 123
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
With FORCE
variable will be set even it’s already present in cache, so
regular variable with the same name will be unset too each time:
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
set(A "123")
set(A "456" CACHE STRING "" FORCE)
message("A: ${A}")
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -Hforce-workaround -B_builds
A: 456
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
[usage-of-variables]> cmake -Hforce-workaround -B_builds
A: 456
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
3.6.2.7. Cache type¶
Though type of any variable is always string you can add some hints which will be used by CMake-GUI:
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
set(FOO_A "YES" CACHE BOOL "Variable A")
set(FOO_B "boo/info.txt" CACHE FILEPATH "Variable B")
set(FOO_C "boo/" CACHE PATH "Variable C")
set(FOO_D "abc" CACHE STRING "Variable D")
message("FOO_A (bool): ${FOO_A}")
message("FOO_B (file path): ${FOO_B}")
message("FOO_C (dir path): ${FOO_C}")
message("FOO_D (string): ${FOO_D}")
Run configure:
Variable FOO_A
will be treated as boolean. Uncheck box and run configure:
Variable FOO_B
will be treated as path to the file. Click on ...
:
Select file:
Run configure:
Variable FOO_C
will be treated as path to directory. Click on ...
:
Select directory:
Run configure:
Variable FOO_D
will be treated as string. Click near variable name and
edit:
Run configure:
Description of variable:
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
set(FOO_A "YES" CACHE BOOL "Variable A")
set(FOO_B "boo/info.txt" CACHE FILEPATH "Variable B")
set(FOO_C "boo/" CACHE PATH "Variable C")
set(FOO_D "abc" CACHE STRING "Variable D")
message("FOO_A (bool): ${FOO_A}")
message("FOO_B (file path): ${FOO_B}")
message("FOO_C (dir path): ${FOO_C}")
message("FOO_D (string): ${FOO_D}")
Will pop-up as a hint for users:
CMake documentation
3.6.2.8. Enumerate¶
Selection widget can be created for variable of string type:
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
set(FOO_CRYPTO "OpenSSL" CACHE STRING "Backend for cryptography")
set_property(CACHE FOO_CRYPTO PROPERTY STRINGS "OpenSSL;Libgcrypt;WinCNG")
CMake documentation
3.6.2.9. Internal¶
Variable with type INTERNAL
will not be shown in CMake-GUI (again, real type
is a string still):
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
set(FOO_A "123" CACHE STRING "")
set(FOO_B "456" CACHE INTERNAL "")
set(FOO_C "789" CACHE STRING "")
Also such type of variable implies FORCE
:
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
set(FOO_A "123" CACHE INTERNAL "")
set(FOO_A "456" CACHE INTERNAL "")
set(FOO_A "789" CACHE INTERNAL "")
set(FOO_B "123" CACHE STRING "")
set(FOO_B "456" CACHE STRING "")
set(FOO_B "789" CACHE STRING "")
message("FOO_A (internal): ${FOO_A}")
message("FOO_B (string): ${FOO_B}")
Variable FOO_A
will be set to 123
then rewritten to 456
because
behavior is similar to variable with FORCE, then one more time to 789
,
so final result is 789
. Variable FOO_B
is a cache variable with no
FORCE so first 123
will be set to cache, then since FOO_B
is already
in cache 456
and 789
will be ignored, so final result is 123
:
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -Hinternal-force -B_builds
FOO_A (internal): 789
FOO_B (string): 123
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
3.6.2.10. Advanced¶
If variable is marked as advanced:
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
set(FOO_A "123" CACHE STRING "")
set(FOO_B "456" CACHE STRING "")
set(FOO_C "789" CACHE STRING "")
mark_as_advanced(FOO_B)
it will not be shown in CMake-GUI if Advanced
checkbox is not set:
CMake documentation
3.6.2.11. Use case¶
The ability of cache variables respect user’s settings fits perfectly for creating project’s customization option:
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
set(FOO_A "Default value for A" CACHE STRING "")
set(FOO_B "Default value for B")
message("FOO_A: ${FOO_A}")
message("FOO_B: ${FOO_B}")
Default value:
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -Hproject-customization -B_builds
FOO_A: Default value for A
FOO_B: Default value for B
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
User’s value:
[usage-of-variables]> cmake -DFOO_A=User -Hproject-customization -B_builds
FOO_A: User
FOO_B: Default value for B
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
Note that such approach doesn’t work for regular CMake variable FOO_B
:
[usage-of-variables]> cmake -DFOO_B=User -Hproject-customization -B_builds
FOO_A: User
FOO_B: Default value for B
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
3.6.2.12. Option¶
Command option
can be used for creating boolean cache entry:
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
option(FOO_A "Option A" OFF)
option(FOO_B "Option B" ON)
message("FOO_A: ${FOO_A}")
message("FOO_B: ${FOO_B}")
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -Hoption -B_builds
FOO_A: OFF
FOO_B: ON
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
[usage-of-variables]> grep FOO_ _builds/CMakeCache.txt
FOO_A:BOOL=OFF
FOO_B:BOOL=ON
CMake documentation
3.6.2.13. Unset¶
If you want to remove variable X
from cache you need to use
unset(X CACHE)
. Note that unset(X)
will remove regular variable from
current scope and have no effect on cache:
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
set(X "123" CACHE STRING "X variable")
set(X "456")
message("[0] X = ${X}")
unset(X)
message("[1] X = ${X}")
unset(X CACHE)
message("[2] X = ${X}")
option(Y "Y option" ON)
set(Y OFF)
message("[0] Y = ${Y}")
unset(Y)
message("[1] Y = ${Y}")
unset(Y CACHE)
message("[2] Y = ${Y}")
When we have both cache and regular X
variables regular variable has
higher priority and will be printed:
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -Hunset-cache -B_builds
[0] X = 456
[1] X = 123
[2] X =
[0] Y = OFF
[1] Y = ON
[2] Y =
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
Command unset(X)
will remove regular variable so cache variable will be
printed:
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -Hunset-cache -B_builds
[0] X = 456
[1] X = 123
[2] X =
[0] Y = OFF
[1] Y = ON
[2] Y =
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
Command unset(X CACHE)
will remove cache variable too. Now no variables
left:
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -Hunset-cache -B_builds
[0] X = 456
[1] X = 123
[2] X =
[0] Y = OFF
[1] Y = ON
[2] Y =
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
Since option
do modify cache same logic applied here:
cmake_minimum_required(VERSION 2.8)
project(foo NONE)
set(X "123" CACHE STRING "X variable")
set(X "456")
message("[0] X = ${X}")
unset(X)
message("[1] X = ${X}")
unset(X CACHE)
message("[2] X = ${X}")
option(Y "Y option" ON)
set(Y OFF)
message("[0] Y = ${Y}")
unset(Y)
message("[1] Y = ${Y}")
unset(Y CACHE)
message("[2] Y = ${Y}")
[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -Hunset-cache -B_builds
[0] X = 456
[1] X = 123
[2] X =
[0] Y = OFF
[1] Y = ON
[2] Y =
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds
3.6.2.14. Recommendation¶
Because of the global nature of cache variables and options
(well it’s cache too) you should do prefix it with the name of the project to
avoid clashing in case several projects are mixed together by
add_subdirectory
:
# top-level CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(zoo)
add_subdirectory(boo)
add_subdirectory(foo)
# foo/CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(foo)
option(FOO_FEATURE_1 "Enable feature 1" OFF)
option(FOO_FEATURE_2 "Enable feature 2" OFF)
# boo/CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(boo)
option(BOO_FEATURE_1 "Enable feature 1" ON)
option(BOO_FEATURE_2 "Enable feature 2" ON)
See also
Besides the fact that both features can be set independently now also CMake-GUI will group them nicely:
3.6.2.15. Summary¶
Use cache to set global variables
Cache variables fits perfectly for expressing customized options: default value and respect user’s value
Type of cache variable helps CMake-GUI users
Prefixes should be used to avoid clashing because of the global nature of cache variables