diff options
Diffstat (limited to 'Help/command/macro.rst')
-rw-r--r-- | Help/command/macro.rst | 138 |
1 files changed, 101 insertions, 37 deletions
diff --git a/Help/command/macro.rst b/Help/command/macro.rst index 6bee69c73..05e5d79ac 100644 --- a/Help/command/macro.rst +++ b/Help/command/macro.rst @@ -1,27 +1,66 @@ macro ----- -Start recording a macro for later invocation as a command:: - - macro(<name> [arg1 [arg2 [arg3 ...]]]) - COMMAND1(ARGS ...) - COMMAND2(ARGS ...) - ... - endmacro(<name>) - -Define a macro named ``<name>`` that takes arguments named ``arg1``, -``arg2``, ``arg3``, (...). -Commands listed after macro, but before the matching -:command:`endmacro()`, are not invoked until the macro is invoked. -When it 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. +Start recording a macro for later invocation as a command + +.. code-block:: cmake + + macro(<name> [<arg1> ...]) + <commands> + endmacro() + +Defines a macro named ``<name>`` that takes arguments named +``<arg1>``, ... Commands listed after macro, but before the +matching :command:`endmacro()`, are not executed until the macro +is invoked. + +Per legacy, the :command:`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 :command:`cmake_policy()` command documentation for the behavior +of policies inside macros. + +See the :ref:`Macro vs Function` section below for differences +between CMake macros and :command:`functions <function>`. + +Invocation +^^^^^^^^^^ + +The macro invocation is case-insensitive. A macro defined as + +.. code-block:: cmake + + macro(foo) + <commands> + endmacro() + +can be invoked through any of + +.. code-block:: cmake + + 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. -Additionally ``${ARGV}`` holds the list of all arguments given to the + +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 @@ -29,48 +68,73 @@ behavior. Checking that ``${ARGC}`` is greater than ``#`` is the only way to ensure that ``${ARGV#}`` was passed to the function as an extra argument. -See the :command:`cmake_policy()` command documentation for the behavior -of policies inside macros. +.. _`Macro vs Function`: + +Macro vs Function +^^^^^^^^^^^^^^^^^ -Macro Argument Caveats -^^^^^^^^^^^^^^^^^^^^^^ +The ``macro`` command is very similar to the :command:`function` command. +Nonetheless, there are a few important differences. -Note that the parameters to a macro and values such as ``ARGN`` are -not variables in the usual CMake sense. They are string -replacements much like the C preprocessor would do with a macro. -Therefore you will NOT be able to use commands like:: +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 :ref:`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 :command:`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 :command:`return()` in macros altogether. + +.. _`Argument Caveats`: + +Argument Caveats +^^^^^^^^^^^^^^^^ + +Since ``ARGN``, ``ARGC``, ``ARGV``, ``ARGV0`` etc. are not variables, +you will NOT be able to use commands like + +.. code-block:: cmake 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:: +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 + +.. code-block:: cmake 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:: +existing variable instead of the arguments. For example: + +.. code-block:: cmake - macro(_BAR) + macro(bar) foreach(arg IN LISTS ARGN) - [...] + <commands> endforeach() endmacro() - function(_FOO) - _bar(x y z) + function(foo) + bar(x y z) endfunction() - _foo(a b c) + foo(a b c) -Will loop over ``a;b;c`` and not over ``x;y;z`` as one might be expecting. +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. |