# Functions with sub-options

**URL:** https://discourse.cmake.org/t/functions-with-sub-options/1206
**Category:** Code
**Created:** [May 13, 2020, 1:27pm UTC](https://discourse.cmake.org/t/functions-with-sub-options/1206 "2020-05-13T13:27:31Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Mellon](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mellon/32/595_2.png) [@Mellon](https://discourse.cmake.org/u/Mellon)
#### Post date: [May 13, 2020, 1:27pm UTC](https://discourse.cmake.org/t/functions-with-sub-options/1206/1 "2020-05-13T13:27:31Z")

</div>

Hi all,

I’m would like to have a function that works as follows:

```
foo(<name> SCHEMA <path> [DEPENDS <dependency> ...] [SCHEMA <path> [DEPENDS ...] ...])

```

that means, needs at least one SCHEMA with associated optional DEPENDS, and I can have multiple SCHEMA in the same foo call. In this case DEPENDS would be a sub-option of SCHEMA.

I managed to do such function by implementing a state machine that loops through ${ARGN} and looks for the pattern `SCHEMA <path> [DEPENDS <dependency> ...]`, setting proper variables to be used later in the function. The code is somehow complicated though, and I was wondering if there would be a simpler/better implementation for this.

I tried to use `cmake_parse_arguments` with multi-args, but it doesn’t seem fit for sub-options. Would someone have a better idea ?

Cheers!

---

<div class="post-metadata">

### Author: ![hex](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hex/32/363_2.png) [@hex](https://discourse.cmake.org/u/hex)
#### Post date: [May 13, 2020, 4:39pm UTC](https://discourse.cmake.org/t/functions-with-sub-options/1206/2 "2020-05-13T16:39:37Z")

</div>

hi @Mellon,

Instead of your state machine, can you parse all top level arguments using `cmake_parse_arguments`, then parsing each sub-option using `cmake_parse_arguments`?

---

<div class="post-metadata">

### Author: ![Mellon](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mellon/32/595_2.png) [@Mellon](https://discourse.cmake.org/u/Mellon)
#### Post date: [May 14, 2020, 9:03am UTC](https://discourse.cmake.org/t/functions-with-sub-options/1206/3 "2020-05-14T09:03:11Z")

</div>

Hey @hex,

Thanks for your reply. 🙂

That’s what I tried first, but I don’t think it works (or at least I didn’t find how to make it work using `cmake_parse_arguments`). For instance if I have:

```
set(SCHEMAS_WITH_DEPENDENCIES
  SCHEMA "schema1"
  SCHEMA "schema2"
    DEPENDS "dep_schema1"
  SCHEMA "schema3"
  SCHEMA "schema4"
    DEPENDS "dep1_schema4" "dep2_schema4"
  SCHEMA "schema5"
)
foo("name" ${SCHEMAS_WITH_DEPENDENCIES})

```

then if I do :

- `cmake_parse_arguments(foo "" "" "SCHEMA;DEPENDS" "${ARGN}")`  
I get `foo_SCHEMA = schema1;schema2;schema3;schema4;schema5` and `foo_DEPENDS = dep_schema1;dep1_schema4;dep2_schema4` and then I lose the association of which schemas have dependencies.

- `cmake_parse_arguments(foo "" "" "SCHEMA" "${ARGN}")`  
I get `foo_SCHEMA = schema1;schema2;DEPENDS;dep_schema1;schema3;schema4;DEPENDS;dep1_schema4;dep2_schema4;schema5` which I can parse again with:

- `cmake_parse_arguments(foo "" "SCHEMA" "" "${ARGN}")`  
Here I get only `foo_SCHEMA = schema5` (the last argument). The DEPENDS options and their arguments are in `foo_UNPARSED_ARGUMENTS`, but again I’ve lost the correspondence with the shemas

I could go on with other tests I did, but I think it’s not that simple to just chain two calls to `cmake_parse_arguments`.

I think I’ve saw one of the core CMake commands with associative arguments, but I couldn’t find which one was it. If it’s implemented in CMake code I could use as an example. Does anyone know such command ?

---

<div class="post-metadata">

### Author: ![hex](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hex/32/363_2.png) [@hex](https://discourse.cmake.org/u/hex)
#### Post date: [May 14, 2020, 12:42pm UTC](https://discourse.cmake.org/t/functions-with-sub-options/1206/4 "2020-05-14T12:42:16Z")

</div>

You are right. With `cmake_parse_arguments` the keywords are stripped out and the relation between the values is lost. 😐 So parsing it manually is really your only option.

I do not recall any CMake command with multi-level arguments but I am not certain enough to say there isn’t any.

---

<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: [May 14, 2020, 7:46pm UTC](https://discourse.cmake.org/t/functions-with-sub-options/1206/5 "2020-05-14T19:46:15Z")

</div>

`cmake_parse_arguments` will mash all arglists with the same keyword into a single list. It’s just the way CMake argument parsing has always worked 😕 . I’ve done this sublist parsing before. The code starts [here](https://gitlab.kitware.com/paraview/paraview/-/blob/9f76167fa14f6fe3815f3863734fc93a51bcb920/CMake/ParaViewPlugin.cmake#L1880) with the docstring.

The basic outline is to have `cmake_parse_arguments` parse out what it can. These keywords must be unique. You then use the `_UNPARSED_ARGUMENTS` variable to run the argparsing state machine. This one does lots of sanity checks and errors on invalid arguments. You might be able to get away with less strict parsing.
