让人不鼓励使用 `$CACHE{variable}` 访问 CMake 缓存变量的原因有哪些?

huangapple go评论85阅读模式
英文:

What reasons are there to discourage accessing CMake cache variables using `$CACHE{variable}`?

问题

# 问题

我正在阅读[Professional CMake](https://crascit.com/professional-cmake/),第5.5节“变量的潜在意外行为”不建议使用`$CACHE{variable}`来访问缓存变量,除非用于调试。确切的引用如下:

> 项目通常不应该使用这个,除非用于临时调试,因为它破坏了长期以来的期望,即普通变量将覆盖在缓存中设置的值。

我不理解这个理由,所以我创建了两个示例。第一个示例使用了`$CACHE{variable}`,第二个示例通过取消设置遮盖缓存变量的普通变量来避免使用它。

**方法1:**
```cmake
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}.")

方法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}.")

两者都产生了预期的输出:

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: ...

因此,似乎$CACHE{variable}更能显示作者的意图,而${variable}虽然破坏了"长期期望",但我很难看出有人会因此而感到困惑。

我在Google上找不到任何信息,我查看了最新版本(3.27)的CMake文档,但它没有提到是否应该使用它。

问题

目前,我更喜欢使用$CACHE{variable}的简洁性和简洁性,我想知道除了破坏"长期期望"之外,是否有任何理由不应该在CMakeLists.txt中使用$CACHE{variable}来访问所有缓存变量?


Here's the translation of your text. Let me know if you need any further modifications or the complete code:

```markdown
# 问题

我正在阅读[Professional CMake](https://crascit.com/professional-cmake/),第5.5节“变量的潜在意外行为”不建议使用`$CACHE{variable}`来访问缓存变量,除非用于调试。确切的引用如下:

> 项目通常不应该使用这个,除非用于临时调试,因为它破坏了长期以来的期望,即普通变量将覆盖在缓存中设置的值。

我不理解这个理由,所以我创建了两个示例。第一个示例使用了`$CACHE{variable}`,第二个示例通过取消设置遮盖缓存变量的普通变量来避免使用它。

**方法1:**
```cmake
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}.")

方法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}.")

两者都产生了预期的输出:

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: ...

因此,似乎$CACHE{variable}更能显示作者的意图,而${variable}虽然破坏了"长期期望",但我很难看出有人会因此而感到困惑。

我在Google上找不到任何信息,我查看了最新版本(3.27)的CMake文档,但它没有提到是否应该使用它。

问题

目前,我更喜欢使用$CACHE{variable}的简洁性和简洁性,我想知道除了破坏"长期期望"之外,是否有任何理由不应该在CMakeLists.txt中使用$CACHE{variable}来访问所有缓存变量?


<details>
<summary>英文:</summary>

# Problem

I am working through [Professional CMake](https://crascit.com/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:

&gt; 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
cmake_minimum_required(VERSION 3.27)
project(example)

set(variable &quot;Hello&quot; CACHE STRING &quot;An example variable&quot; FORCE)
set(variable &quot;Goodbye&quot;)
message(&quot;The normal variable&#39;s value is ${variable}.&quot;)
message(&quot;The cache variable&#39;s value is $CACHE{variable}.&quot;)

Approach 2:

cmake_minimum_required(VERSION 3.27)
project(example)

set(variable &quot;Hello&quot; CACHE STRING &quot;An example variable&quot; FORCE)
set(variable &quot;Goodbye&quot;)
message(&quot;The normal variable&#39;s value is ${variable}.&quot;)
unset(variable)
message(&quot;The cache variable&#39;s value is ${variable}.&quot;)

Both produce the expected output of:

The normal variable&#39;s value is Goodbye.
The cache variable&#39;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?

答案1

得分: 1

Here's the translated code:

我只是要扩展一下273K在评论中所说的,因为虽然我同意遵循手册是“如此容易”的,但我也认为理解手册为什么建议这样做是合理的(也很重要)。

假设您正在构建一个库:

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

其中 foolib_special_behavior 是通常在缓存中设置的变量。

现在有人试图在另一个项目中将您的库用作依赖项:

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

这是将某物包含为子目录时的常见模式:在包含子目录之前,您可以设置要使用的任何配置选项。

现在,如果您使用了 target_compile_definitions(foolib PRIVATE "$CACHE{foolib_special_behavior}"),这将不起作用 - 嵌套您的项目的项目将不得不在缓存中设置变量。

Please let me know if you need any further modifications or assistance with the code.

英文:

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 &quot;${foolib_special_behavior}&quot;)
...

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 &quot;SPECIAL&quot;)
add_subdirectory(&quot;dependencies/foolib&quot;)
...

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 &quot;$CACHE{foolib_special_behavior}&quot;), this would not work - the project embedding you would have to set variables in the cache.

huangapple
  • 本文由 发表于 2023年7月23日 22:26:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76748751.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定