# Save CMake function parameter forwarding

**URL:** https://discourse.cmake.org/t/save-cmake-function-parameter-forwarding/1002
**Category:** Code
**Created:** [April 13, 2020, 3:17pm UTC](https://discourse.cmake.org/t/save-cmake-function-parameter-forwarding/1002 "2020-04-13T15:17:43Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![mensinda](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mensinda/32/913_2.png) [@mensinda](https://discourse.cmake.org/u/mensinda)
#### Post date: [April 13, 2020, 3:17pm UTC](https://discourse.cmake.org/t/save-cmake-function-parameter-forwarding/1002/1 "2020-04-13T15:17:43Z")

</div>

Is it generally possible to safely forward function parameters? I know that `${ARGV}` is less than ideal since it flattens lists, etc. So I am looking for a solution that doesn’t have the same issues.

More specifically I am analyzing the CMake trace output, and I want to keep track of the `CMAKE_CURRENT_BINARY_DIR` and `CMAKE_CURRENT_SOURCE_DIR` at the same time ([`variable_watch`](https://cmake.org/cmake/help/latest/command/variable_watch.html) doesn’t seem to work for these for some reason).

The best solution I have come up with so far is to override the functions in question and insert some code to keep track of the variables manually. See [https://github.com/mesonbuild/meson/blob/master/mesonbuild/cmake/data/preload.cmake](https://github.com/mesonbuild/meson/blob/master/mesonbuild/cmake/data/preload.cmake). This works OK-ish for `add_custom_{command,target}`, however, I also want to add `set_property` and `set_source_files_properties`, where `${ARGV}` will break for arbitrary projects.

If possible, the solution should work for CMake 3.7+ (since 3.7 is the first version with the CMake server). And yes, I am aware that the `_original_function` behavior is (currently) undocumented.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 13, 2020, 3:49pm UTC](https://discourse.cmake.org/t/save-cmake-function-parameter-forwarding/1002/2 "2020-04-13T15:49:21Z")

</div>

`cmake_parse_arguments(PARSE_ARGV 0)` may help here. It might still collapse list arguments, but it should be able to “see” quoting and handle that properly at least.

---

<div class="post-metadata">

### Author: ![mensinda](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mensinda/32/913_2.png) [@mensinda](https://discourse.cmake.org/u/mensinda)
#### Post date: [April 13, 2020, 4:25pm UTC](https://discourse.cmake.org/t/save-cmake-function-parameter-forwarding/1002/3 "2020-04-13T16:25:01Z")

</div>

Thanks for the response, but how do I pass the result of `cmake_parse_arguments` to `set_source_files_properties` without flattening the list (the actual properties are passed as key/value paired lists)?

Example:

```cmake
function(set_source_files_properties)
    set(options)
    set(oneValueArgs)
    set(multiValueArgs PROPERTIES)
    cmake_parse_arguments(PARSE_ARGV 0 MY_FPROP "${options}" "${oneValueArgs}" "${multiValueArgs}")
                            
    _set_source_files_properties(${PARSE_ARGV_UNPARSED_ARGUMENTS} PROPERTIES ${PARSE_ARGV_PROPERTIES})
endfunction()

set_source_files_properties(foo.cpp PROPERTIES HEADER_FILE_ONLY ON COMPILE_FLAGS "-Dasd=C;M;a;k;e")

```

As far as I can tell, the above example would still flatten the properties in `PARSE_ARGV_PROPERTIES`.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 13, 2020, 5:20pm UTC](https://discourse.cmake.org/t/save-cmake-function-parameter-forwarding/1002/4 "2020-04-13T17:20:52Z")

</div>

Hmm. Indeed. Maybe `set_property` is the better thing to do here? You may need to just iterate over the `ARGN` list and build up a list of quoted arguments you then pass down to `set_source_files_properties`.

---

<div class="post-metadata">

### Author: ![mensinda](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mensinda/32/913_2.png) [@mensinda](https://discourse.cmake.org/u/mensinda)
#### Post date: [April 13, 2020, 5:25pm UTC](https://discourse.cmake.org/t/save-cmake-function-parameter-forwarding/1002/5 "2020-04-13T17:25:42Z")

</div>

Yeah, that function wouldn’t be a problem, however, I have no control over what function is used. The script in the link is injected via `CMAKE_PROJECT_INCLUDE` and should work for _any_ project. More specifically I want to track the `HEADER_FILE_ONLY` property since there is no way to get this information out of the server API (which we still have to support).

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 13, 2020, 5:33pm UTC](https://discourse.cmake.org/t/save-cmake-function-parameter-forwarding/1002/6 "2020-04-13T17:33:28Z")

</div>

Ah, OK. Then I suggest iterating over `ARGN` yourself and calling `set_property` internally with quoted arguments. Unfortunately, it sounds like you need to support an older CMake than has `foreach (key value IN LISTS ARGN)`, so you’ll have to do the pairing manually.

---

<div class="post-metadata">

### Author: ![mensinda](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mensinda/32/913_2.png) [@mensinda](https://discourse.cmake.org/u/mensinda)
#### Post date: [April 13, 2020, 5:36pm UTC](https://discourse.cmake.org/t/save-cmake-function-parameter-forwarding/1002/7 "2020-04-13T17:36:55Z")

</div>

Thanks, I didn’t think about converting `set_source_files_properties` to `set_property`.

---

<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: [April 13, 2020, 9:59pm UTC](https://discourse.cmake.org/t/save-cmake-function-parameter-forwarding/1002/8 "2020-04-13T21:59:43Z")

</div>

For others following this thread, the issues with argument forwarding and list flattening are discussed in the following article:

> **[Forwarding Command Arguments In CMake - Crascit](https://crascit.com/2019/01/29/forwarding-command-arguments-in-cmake/)**
>
> This article highlights dangers with using ARGV or ARGN to forward arguments to CMake commands, including list flattening and dropping of empty arguments.

Since that was written, the `cmake_command()` command has landed in [CMake master](https://cmake.org/cmake/help/git-master/command/cmake_command.html). There could potentially be a way to use that to do argument forwarding without the list flattening (specifically the `cmake_command(EVAL CODE...)` form). It could be a bit convoluted, but perhaps possible. Not useful for this query, but worth keeping in mind for anyone else stumbling across this thread sometime in the future.

---

<div class="post-metadata">

### Author: ![mensinda](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mensinda/32/913_2.png) [@mensinda](https://discourse.cmake.org/u/mensinda)
#### Post date: [April 14, 2020, 5:48pm UTC](https://discourse.cmake.org/t/save-cmake-function-parameter-forwarding/1002/9 "2020-04-14T17:48:51Z")

</div>

For anyone interested, this is the `set_source_files_properties` to `set_property` conversion function I came up with:

```cmake
function(set_source_files_properties)
  set(FILES)
  set(I 0)
  set(PROPERTIES OFF)

  while(I LESS ARGC)
    if(NOT PROPERTIES)
      if("${ARGV${I}}" STREQUAL "PROPERTIES")
        set(PROPERTIES ON)
      else()
        list(APPEND FILES "${ARGV${I}}")
      endif()

      math(EXPR I "${I} + 1")
    else()
      set(ID_IDX ${I})
      math(EXPR PROP_IDX "${ID_IDX} + 1")

      set(ID "${ARGV${ID_IDX}}")
      set(PROP "${ARGV${PROP_IDX}}")

      set_property(SOURCE ${FILES} PROPERTY "${ID}" "${PROP}")
      math(EXPR I "${I} + 2")
    endif()
  endwhile()
endfunction()

```

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 14, 2020, 7:41pm UTC](https://discourse.cmake.org/t/save-cmake-function-parameter-forwarding/1002/10 "2020-04-14T19:41:13Z")

</div>

This may be made simpler with `foreach (I IN LISTS ARGN)` rather than `math(EXPR)`, but that’s more a style thing.

---

<div class="post-metadata">

### Author: ![mensinda](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mensinda/32/913_2.png) [@mensinda](https://discourse.cmake.org/u/mensinda)
#### Post date: [April 14, 2020, 7:51pm UTC](https://discourse.cmake.org/t/save-cmake-function-parameter-forwarding/1002/11 "2020-04-14T19:51:52Z")

</div>

Thanks, but with `foreach (I IN LISTS ARGN)` the “group two parameters” logic will be more anoying.
