Functions with sub-options

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!

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?

1 Like

Hey @hex,

Thanks for your reply. :slight_smile:

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(subfoo "" "" "DEPENDS" "${foo_SCHEMA}")
      but then to get subfoo_DEPENDS = dep_schema1;schema3;schema4;dep1_schema4;dep2_schema4;schema5 and I have schemas and dependencies mixed up. :confused:
  • 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 ?

1 Like

You are right. With cmake_parse_arguments the keywords are stripped out and the relation between the values is lost. :neutral_face: 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.

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 :confused: . I’ve done this sublist parsing before. The code starts here 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.