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

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

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

问题

  1. # 问题
  2. 我正在阅读[Professional CMake](https://crascit.com/professional-cmake/),第5.5节“变量的潜在意外行为”不建议使用`$CACHE{variable}`来访问缓存变量,除非用于调试。确切的引用如下:
  3. > 项目通常不应该使用这个,除非用于临时调试,因为它破坏了长期以来的期望,即普通变量将覆盖在缓存中设置的值。
  4. 我不理解这个理由,所以我创建了两个示例。第一个示例使用了`$CACHE{variable}`,第二个示例通过取消设置遮盖缓存变量的普通变量来避免使用它。
  5. **方法1:**
  6. ```cmake
  7. cmake_minimum_required(VERSION 3.27)
  8. project(example)
  9. set(variable "Hello" CACHE STRING "An example variable" FORCE)
  10. set(variable "Goodbye")
  11. message("The normal variable's value is ${variable}.")
  12. message("The cache variable's value is $CACHE{variable}.")

方法2:

  1. cmake_minimum_required(VERSION 3.27)
  2. project(example)
  3. set(variable "Hello" CACHE STRING "An example variable" FORCE)
  4. set(variable "Goodbye")
  5. message("The normal variable's value is ${variable}.")
  6. unset(variable)
  7. message("The cache variable's value is ${variable}.")

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

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

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

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

问题

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

  1. Here's the translation of your text. Let me know if you need any further modifications or the complete code:
  2. ```markdown
  3. # 问题
  4. 我正在阅读[Professional CMake](https://crascit.com/professional-cmake/),第5.5节“变量的潜在意外行为”不建议使用`$CACHE{variable}`来访问缓存变量,除非用于调试。确切的引用如下:
  5. > 项目通常不应该使用这个,除非用于临时调试,因为它破坏了长期以来的期望,即普通变量将覆盖在缓存中设置的值。
  6. 我不理解这个理由,所以我创建了两个示例。第一个示例使用了`$CACHE{variable}`,第二个示例通过取消设置遮盖缓存变量的普通变量来避免使用它。
  7. **方法1:**
  8. ```cmake
  9. cmake_minimum_required(VERSION 3.27)
  10. project(example)
  11. set(variable "Hello" CACHE STRING "An example variable" FORCE)
  12. set(variable "Goodbye")
  13. message("The normal variable's value is ${variable}.")
  14. message("The cache variable's value is $CACHE{variable}.")

方法2:

  1. cmake_minimum_required(VERSION 3.27)
  2. project(example)
  3. set(variable "Hello" CACHE STRING "An example variable" FORCE)
  4. set(variable "Goodbye")
  5. message("The normal variable's value is ${variable}.")
  6. unset(variable)
  7. message("The cache variable's value is ${variable}.")

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

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

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

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

问题

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

  1. <details>
  2. <summary>英文:</summary>
  3. # Problem
  4. 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:
  5. &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.
  6. 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.
  7. **Approach 1:**
  8. ```cmake
  9. cmake_minimum_required(VERSION 3.27)
  10. project(example)
  11. set(variable &quot;Hello&quot; CACHE STRING &quot;An example variable&quot; FORCE)
  12. set(variable &quot;Goodbye&quot;)
  13. message(&quot;The normal variable&#39;s value is ${variable}.&quot;)
  14. message(&quot;The cache variable&#39;s value is $CACHE{variable}.&quot;)

Approach 2:

  1. cmake_minimum_required(VERSION 3.27)
  2. project(example)
  3. set(variable &quot;Hello&quot; CACHE STRING &quot;An example variable&quot; FORCE)
  4. set(variable &quot;Goodbye&quot;)
  5. message(&quot;The normal variable&#39;s value is ${variable}.&quot;)
  6. unset(variable)
  7. message(&quot;The cache variable&#39;s value is ${variable}.&quot;)

Both produce the expected output of:

  1. The normal variable&#39;s value is Goodbye.
  2. The cache variable&#39;s value is Hello.
  3. -- Configuring done (0.0s)
  4. -- Generating done (0.0s)
  5. -- 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在评论中所说的,因为虽然我同意遵循手册是“如此容易”的,但我也认为理解手册为什么建议这样做是合理的(也很重要)。

假设您正在构建一个库:

  1. ...
  2. add_library(foolib STATIC ...)
  3. target_compile_definitions(foolib PRIVATE "${foolib_special_behavior}")
  4. ...

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

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

  1. ...
  2. set(foolib_special_behavior "SPECIAL")
  3. add_subdirectory("dependencies/foolib")
  4. ...

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

现在,如果您使用了 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:

  1. ...
  2. add_library(foolib STATIC ...)
  3. target_compile_definitions(foolib PRIVATE &quot;${foolib_special_behavior}&quot;)
  4. ...

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:

  1. ...
  2. set(foolib_special_behavior &quot;SPECIAL&quot;)
  3. add_subdirectory(&quot;dependencies/foolib&quot;)
  4. ...

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:

确定