1

Problem

I am working through Professional CMake and section 5.5 - Potentially Surprising Behaviour of Variables discourages accessing cache variables using $CACHE{variable} except when debugging. The exact quote is:

Projects should not generally make use of this other than for temporary debugging, since it breaks the long-established expectation that normal variables will override values set in the cache.

I did not understand this reasoning so I created two examples. The first uses $CACHE{variable} and the second avoids it by unsetting the normal variable that is shadowing the cache variable.

Approach 1:

cmake_minimum_required(VERSION 3.27)
project(example)

set(variable "Hello" CACHE STRING "An example variable" FORCE)
set(variable "Goodbye")
message("The normal variable's value is ${variable}.")
message("The cache variable's value is $CACHE{variable}.")

Approach 2:

cmake_minimum_required(VERSION 3.27)
project(example)

set(variable "Hello" CACHE STRING "An example variable" FORCE)
set(variable "Goodbye")
message("The normal variable's value is ${variable}.")
unset(variable)
message("The cache variable's value is ${variable}.")

Both produce the expected output of:

The normal variable's value is Goodbye.
The cache variable's value is Hello.
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: ...

It therefore seems that $CACHE{variable} is better at showing the author's intention than ${variable} and while it does break "long-established expectation", I struggle to see how someone could get confused by this.

I could not find anything on Google and I looked at the CMake documentation for the latest version (3.27) but it did not mention whether it should be used or not.

Question

At the moment, I prefer the simplicity and conciseness of $CACHE{variable} and want to know, beyond breaking "long-established expectation", if there is any reason why I should not use $CACHE{variable} to access all the cache variables in CMakeLists.txt?

273K
  • 29,503
  • 10
  • 41
  • 64
Toggy Smith
  • 330
  • 2
  • 7
  • I'm not sure why Stackoverflow is applying syntax highlighting to the expected output code block. I tried `plain`, `plaintext`, and `console`. – Toggy Smith Jul 23 '23 at 14:29
  • You should not use `$CACHE{variable}`. Cmake uses `${variable}` - a user defined value if any or a cached value otherwise. Just follow the manual. If you use `$CACHE{variable}`, you make users not to able to use scoped variable values. – 273K Jul 23 '23 at 16:26
  • @273K Why would using `$CACHE{variable}` to access a cache variable prevent another user from using scoped variable values? The manual (documentation) that I linked to introduces the `$CACHE{variable}` but does not say when to use it. – Toggy Smith Jul 23 '23 at 17:53
  • 1
    User wants that your cmake module uses this specific variable value in this specific scope, but you with `$CACHE{variable}` ignore user's variable value and user's wish. Just follow the manual and don't use it for other than debugging purposes, it's so easy. – 273K Jul 23 '23 at 18:05

1 Answers1

1

I'm just going to expand on what 273K said in the comments, because while I agree it's "so easy" to follow the manual, I also think it's valid (and important) to understand why the manual recommends what it does.

Assume you're building a library:

...
add_library(foolib STATIC ...)
target_compile_definitions(foolib PRIVATE "${foolib_special_behavior}")
...

Where foolib_special_behavior is a variable that's usually set in the cache.

Now someone is trying to use your library as a dependency in another project:

...
set(foolib_special_behavior "SPECIAL")
add_subdirectory("dependencies/foolib")
...

This is a usual pattern when including something as a subdirectory: you set any configuration options you want to use before including the subdirectory.

Now if you had used target_compile_definitions(foolib PRIVATE "$CACHE{foolib_special_behavior}"), this would not work - the project embedding you would have to set variables in the cache.

Wutz
  • 2,246
  • 13
  • 15
  • Thanks for the example, this makes more sense now. – Toggy Smith Jul 23 '23 at 18:40
  • quoting the question post: "_and want to know, beyond breaking "long-established expectation"_" what does this add on top of what the asker knows and is not looking for? / @ToggySmith why did you accept this answer? – starball Jul 24 '23 at 00:56
  • 1
    @starball The intention was to explain what the "long-established expectation" actually is and why it's broken by using `CACHE`. Which, technically, is not an answer to the question I guess. But I assumed (correctly, judging by the answer being accepted) that the asker simply didn't know/understand why this was a problem. – Wutz Jul 24 '23 at 17:17
  • @starball I meant that I wanted an answer beyond "long-established expectation" because that is very similar to "do this because it's how we've always done things". I accepted this answer because it did what Professional CMake did not do, namely it explained why we should not use `$CACHE{variable}` and gave an example too. – Toggy Smith Aug 06 '23 at 10:07