# cmake\_language(DEFER) not evaluating variable references is inconsistent

**URL:** https://discourse.cmake.org/t/cmake-language-defer-not-evaluating-variable-references-is-inconsistent/2061
**Category:** Development
**Created:** [October 24, 2020, 6:23am UTC](https://discourse.cmake.org/t/cmake-language-defer-not-evaluating-variable-references-is-inconsistent/2061 "2020-10-24T06:23:20Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [October 24, 2020, 6:23am UTC](https://discourse.cmake.org/t/cmake-language-defer-not-evaluating-variable-references-is-inconsistent/2061/1 "2020-10-24T06:23:20Z")

</div>

The docs for the new `cmake_language(DEFER)` subcommand added for CMake 3.19 say the following:

> Variable references in arguments are evaluated at the time the deferred call is executed.

This makes this command behave differently to other CMake commands (and even other subcommands of `cmake_language()`) and is rather unintuitive. If the user wants to, it is easy to avoid variable dereferences by using bracket syntax, so I’m wondering why the command was given this inconsistent behavior. I’d recommend we avoid this inconsistency and evaluate variables just like other commands do. We should make this change now since the 3.19 release is the first version in which it will appear.

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [October 24, 2020, 6:24am UTC](https://discourse.cmake.org/t/cmake-language-defer-not-evaluating-variable-references-is-inconsistent/2061/2 "2020-10-24T06:24:13Z")

</div>

@kyle.edwards @alcroito Sorry, I meant to CC you both in the original message.

---

<div class="post-metadata">

### Author: ![alcroito](https://discourse.cmake.org/user_avatar/discourse.cmake.org/alcroito/32/186_2.png) [@alcroito](https://discourse.cmake.org/u/alcroito)
#### Post date: [October 24, 2020, 12:32pm UTC](https://discourse.cmake.org/t/cmake-language-defer-not-evaluating-variable-references-is-inconsistent/2061/3 "2020-10-24T12:32:20Z")

</div>

Check Brad’s reasoning at [https://gitlab.kitware.com/cmake/cmake/-/merge\_requests/5262#note\_835244](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/5262#note_835244)  
and my comments before that.

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [October 24, 2020, 9:33pm UTC](https://discourse.cmake.org/t/cmake-language-defer-not-evaluating-variable-references-is-inconsistent/2061/4 "2020-10-24T21:33:14Z")

</div>

Thanks, yes now I recall seeing that back then but didn’t get to follow up at the time. I’m not sure I necessarily agree with the reasoning stated there. @brad.king’s comment:

> The existing `cmake_language(CALL <command> [<args>...])` evaluates `<args>` after the command name at the point at which the call is made. No additional layer of evaluation is added. It just happens that the call is made immediately in that case.

I recall having previous discussions about that, see [issue 20707](https://gitlab.kitware.com/cmake/cmake/-/issues/20707) for the details. To the user, this appears as an internal implementation detail, since it still looks to them as though variables are evaluated as normal. Maybe there’s a corner case where it makes a difference, but I note that there is no mention in the docs about this delayed evaluation.

Continuing with Brad’s reasoning:

> In the `DEFER` case, the `CALL` has the same argument evaluation semantics, but the time the call is made happens to be later. Delaying argument evaluation:
> 
> - is consistent with the existing `CALL` signature,
> - is consistent with the documentation stating that the call is made as if written at the end of the `CMakeLists.txt` file,
> - provides a lot of power from which one can opt-out with EVAL anyway, and
> - happens to be ~~easier~~ possible to implement.

I’m suggesting that while the DEFER case might be consistent with the _implementation_ of the CALL signature, it doesn’t seem consistent with the perceived behavior. Also, rather than having to opt-out using EVAL, one could effectively opt-in by using bracket syntax to avoid evaluation at the call site.

Reading back over the discussions again in issue 20707, I can’t say how feasible it is to evaluate variables immediately at the call to `cmake_command()`. I’ve raised my concerns about consistency and intuitive behavior, but I’ll have to defer to @brad.king on this.

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [October 26, 2020, 1:52pm UTC](https://discourse.cmake.org/t/cmake-language-defer-not-evaluating-variable-references-is-inconsistent/2061/5 "2020-10-26T13:52:52Z")

</div>

I thought extensively about this when implementing the feature and stand by my justifications for delayed evaluation. As just one example, without it the following would not work:

```cmake
cmake_language(DEFER CALL set var "value")
cmake_language(DEFER CALL message "${var}") # prints "value"

```

On the implementation side, it is not really possible to implement anything else anyway. Every command does its own argument evaluation after `cmMakefile` calls it, and there is no way to tell commands that their arguments have already been evaluated. Adding one would require updating every single command’s implementation to have such special cases.

I consider this decision closed.

---

<div class="post-metadata">

### Author: ![drywolf](https://discourse.cmake.org/user_avatar/discourse.cmake.org/drywolf/32/2205_2.png) [@drywolf](https://discourse.cmake.org/u/drywolf)
#### Post date: [February 20, 2022, 8:01pm UTC](https://discourse.cmake.org/t/cmake-language-defer-not-evaluating-variable-references-is-inconsistent/2061/6 "2022-02-20T20:01:46Z")

</div>

Hi, I am having trouble using `cmake_language(DEFER)` for the aforementioned reasons.

I have a function like `function my_finalizer(some_param)` which should be automatically scheduled to be called from within another function `function(do_stuff some_param)`

Initially in my `do_stuff()` function I tried:

```cmake
cmake_language(DEFER CALL my_finalizer "${some_param}")

```

but that obviously failed, for the reasons outlined above.

I even tried the following:

```cmake
cmake_language(DEFER CALL set "some_param" "${some_param}")
cmake_language(DEFER CALL my_finalizer "${some_param}")

```

which in hindsight, is obviously no better than the single line I tried before, but I am a bit desperate here, ngl 😑

Sorry if I overlooked anything obvious, but how would I achieve what I want here with the way how `cmake_language(DEFER)` works currently ?  
PS: I would really like to not rely on any global variables / global state … I know that this would work, but IMO is really bad practice.

Thanks for any help

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [February 20, 2022, 8:12pm UTC](https://discourse.cmake.org/t/cmake-language-defer-not-evaluating-variable-references-is-inconsistent/2061/7 "2022-02-20T20:12:20Z")

</div>

If I understand your difficulty correctly, you need to wrap the `cmake_language(DEFER)` in a `cmake_language(EVAL)` in order to force the immediate evaluation of the variable. Something like the following is what I think you’re looking for:

```cmake
cmake_language(EVAL CODE
    "cmake_language(DEFER CALL my_finalizer [[${some_param}]])"
)

```

---

<div class="post-metadata">

### Author: ![drywolf](https://discourse.cmake.org/user_avatar/discourse.cmake.org/drywolf/32/2205_2.png) [@drywolf](https://discourse.cmake.org/u/drywolf)
#### Post date: [February 20, 2022, 9:07pm UTC](https://discourse.cmake.org/t/cmake-language-defer-not-evaluating-variable-references-is-inconsistent/2061/8 "2022-02-20T21:07:01Z")

</div>

Thanks for the quick reply @craig.scott

The code you gave indeed does work for me 🙌

And now I had a second look at the [cmake\_language(DEFER)](https://cmake.org/cmake/help/latest/command/cmake_language.html#deferred-call-examples) manual page, and indeed this is mentioned, but I had to scroll way down to the ‘examples’ section of the page.

I think it would be worthwhile to note this behavior also at the very top of the documentation.

There is already a sentence hinting at this behavior at the top of function documentation, but the workaround for it is not mentioned:

> Variable references in arguments are evaluated at the time the deferred call is executed.

I would suggest to enhance that a bit like so:

> Variable references in arguments are evaluated at the time the deferred call is executed.
> 
> If you need variable references to be evaluated at the call-site of `cmake_language(DEFER)`, you need to wrap it in a call of `cmake_language(EVAL CODE)` and surround each of the variable references with square brackets `[[${variable}]]`
> 
> (see the [Deferred Call Examples](https://cmake.org/cmake/help/latest/command/cmake_language.html#deferred-call-examples) for details)

Thanks
