macro — CMake 3.15.0 Documentation

# macro

Start recording a macro for later invocation as a command

    macro(<name> [<arg1> ...])
      <commands>
    endmacro()

Defines a macro named `<name>` that takes arguments named `<arg1>`, … Commands listed after macro, but before the matching `endmacro()`, are not executed until the macro is invoked.

Per legacy, the `endmacro()` command admits an optional `<name>` argument. If used, it must be a verbatim repeat of the argument of the opening `macro` command.

See the `cmake_policy()` command documentation for the behavior of policies inside macros.

See the Macro vs Function section below for differences between CMake macros and `functions`.

## Invocation

The macro invocation is case-insensitive. A macro defined as

    macro(foo)
      <commands>
    endmacro()

can be invoked through any of

    foo()
    Foo()
    FOO()

and so on. However, it is strongly recommended to stay with the case chosen in the macro definition. Typically macros use all-lowercase names.

## Arguments

When a macro is invoked, the commands recorded in the macro are first modified by replacing formal parameters (`${arg1}`, …) with the arguments passed, and then invoked as normal commands.

In addition to referencing the formal parameters you can reference the values `${ARGC}` which will be set to the number of arguments passed into the function as well as `${ARGV0}`, `${ARGV1}`, `${ARGV2}`, … which will have the actual values of the arguments passed in. This facilitates creating macros with optional arguments.

Furthermore, `${ARGV}` holds the list of all arguments given to the macro and `${ARGN}` holds the list of arguments past the last expected argument. Referencing to `${ARGV#}` arguments beyond `${ARGC}` have undefined behavior. Checking that `${ARGC}` is greater than `#` is the only way to ensure that `${ARGV#}` was passed to the function as an extra argument.

## Macro vs Function

The `macro` command is very similar to the `function()` command. Nonetheless, there are a few important differences.

In a function, `ARGN`, `ARGC`, `ARGV` and `ARGV0`, `ARGV1`, … are true variables in the usual CMake sense. In a macro, they are not, they are string replacements much like the C preprocessor would do with a macro. This has a number of consequences, as explained in the Argument Caveats section below.

Another difference between macros and functions is the control flow. A function is executed by transferring control from the calling statement to the function body. A macro is executed as if the macro body were pasted in place of the calling statement. This has the consequence that a `return()` in a macro body does not just terminate execution of the macro; rather, control is returned from the scope of the macro call. To avoid confusion, it is recommended to avoid `return()` in macros altogether.

## Argument Caveats

Since `ARGN`, `ARGC`, `ARGV`, `ARGV0` etc. are not variables, you will NOT be able to use commands like

    if(ARGV1) # ARGV1 is not a variable
    if(DEFINED ARGV2) # ARGV2 is not a variable
    if(ARGC GREATER 2) # ARGC is not a variable
    foreach(loop_var IN LISTS ARGN) # ARGN is not a variable

In the first case, you can use `if(${ARGV1})`. In the second and third case, the proper way to check if an optional variable was passed to the macro is to use `if(${ARGC} GREATER 2)`. In the last case, you can use `foreach(loop_var ${ARGN})` but this will skip empty arguments. If you need to include them, you can use

    set(list_var "${ARGN}")
    foreach(loop_var IN LISTS list_var)

Note that if you have a variable with the same name in the scope from which the macro is called, using unreferenced names will use the existing variable instead of the arguments. For example:

    macro(bar)
      foreach(arg IN LISTS ARGN)
        <commands>
      endforeach()
    endmacro()

    function(foo)
      bar(x y z)
    endfunction()

    foo(a b c)

Will loop over `a;b;c` and not over `x;y;z` as one might have expected. If you want true CMake variables and/or better CMake scope control you should look at the function command.