浏览代码

Help: Recommend good prefixes for cmake_parse_arguments, expand example

Fixes: #25773
Craig Scott 1 年之前
父节点
当前提交
2000abe74f
共有 1 个文件被更改,包括 81 次插入25 次删除
  1. 81 25
      Help/command/cmake_parse_arguments.rst

+ 81 - 25
Help/command/cmake_parse_arguments.rst

@@ -76,9 +76,42 @@ whether your macro or function was called with unrecognized parameters.
    policy :policy:`CMP0174` controls whether a corresponding
    ``<prefix>_<keyword>`` variable is defined or not.
 
+Choose a ``<prefix>`` carefully to avoid clashing with existing variable names.
+When used inside a function, it is usually suitable to use the prefix ``arg``.
+There is a very strong convention that all keywords are fully uppercase, so
+this prefix results in variables of the form ``arg_SOME_KEYWORD``.  This makes
+the code more readable, and it minimizes the chance of clashing with cache
+variables, which also have a strong convention of being all uppercase.
 
-Consider the following example macro, ``my_install()``, which takes similar
-arguments to the real :command:`install` command:
+.. code-block:: cmake
+
+   function(my_install)
+       set(options OPTIONAL FAST)
+       set(oneValueArgs DESTINATION RENAME)
+       set(multiValueArgs TARGETS CONFIGURATIONS)
+       cmake_parse_arguments(PARSE_ARGV 0 arg
+           "${options}" "${oneValueArgs}" "${multiValueArgs}"
+       )
+
+       # The above will set or unset variables with the following names:
+       #   arg_OPTIONAL
+       #   arg_FAST
+       #   arg_DESTINATION
+       #   arg_RENAME
+       #   arg_TARGETS
+       #   arg_CONFIGURATIONS
+       #
+       # The following will also be set or unset:
+       #   arg_UNPARSED_ARGUMENTS
+       #   arg_KEYWORDS_MISSING_VALUES
+
+When used inside a macro, ``arg`` might not be a suitable prefix because the
+code will affect the calling scope.  If another macro also called in the same
+scope were to use ``arg`` in its own call to ``cmake_parse_arguments()``,
+and if there are any common keywords between the two macros, the later call's
+variables can overwrite or remove those of the earlier macro's call.
+Therefore, it is advisable to incorporate something unique from the macro name
+in the ``<prefix>``, such as ``arg_lowercase_macro_name``.
 
 .. code-block:: cmake
 
@@ -86,40 +119,63 @@ arguments to the real :command:`install` command:
        set(options OPTIONAL FAST)
        set(oneValueArgs DESTINATION RENAME)
        set(multiValueArgs TARGETS CONFIGURATIONS)
-       cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}"
-                             "${multiValueArgs}" ${ARGN} )
+       cmake_parse_arguments(arg_my_install
+           "${options}" "${oneValueArgs}" "${multiValueArgs}"
+           ${ARGN}
+       )
+       # ...
+   endmacro()
 
+   macro(my_special_install)
+       # NOTE: Has the same keywords as my_install()
+       set(options OPTIONAL FAST)
+       set(oneValueArgs DESTINATION RENAME)
+       set(multiValueArgs TARGETS CONFIGURATIONS)
+       cmake_parse_arguments(arg_my_special_install
+           "${options}" "${oneValueArgs}" "${multiValueArgs}"
+           ${ARGN}
+       )
        # ...
+   endmacro()
 
-Assume ``my_install()`` has been called like this:
+Suppose the above macros are called one after the other, like so:
 
 .. code-block:: cmake
 
    my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub CONFIGURATIONS)
-
-After the ``cmake_parse_arguments`` call, the macro will have set or undefined
-the following variables::
-
-   MY_INSTALL_OPTIONAL = TRUE
-   MY_INSTALL_FAST = FALSE # was not used in call to my_install
-   MY_INSTALL_DESTINATION = "bin"
-   MY_INSTALL_RENAME <UNDEFINED> # was not used
-   MY_INSTALL_TARGETS = "foo;bar"
-   MY_INSTALL_CONFIGURATIONS <UNDEFINED> # was not used
-   MY_INSTALL_UNPARSED_ARGUMENTS = "blub" # nothing expected after "OPTIONAL"
-   MY_INSTALL_KEYWORDS_MISSING_VALUES = "CONFIGURATIONS"
-            # No value for "CONFIGURATIONS" given
-
-You can then continue and process these variables.
+   my_special_install(TARGETS barry DESTINATION sbin RENAME FAST)
+
+After these two calls, the following describes the variables that will be
+set or unset::
+
+   arg_my_install_OPTIONAL = TRUE
+   arg_my_install_FAST = FALSE # was not present in call to my_install
+   arg_my_install_DESTINATION = "bin"
+   arg_my_install_RENAME <UNSET> # was not present
+   arg_my_install_TARGETS = "foo;bar"
+   arg_my_install_CONFIGURATIONS <UNSET> # was not present
+   arg_my_install_UNPARSED_ARGUMENTS = "blub" # nothing expected after "OPTIONAL"
+   arg_my_install_KEYWORDS_MISSING_VALUES = "CONFIGURATIONS" # value was missing
+
+   arg_my_special_install_OPTIONAL = FALSE # was not present
+   arg_my_special_install_FAST = TRUE
+   arg_my_special_install_DESTINATION = "sbin"
+   arg_my_special_install_RENAME <UNSET> # value was missing
+   arg_my_special_install_TARGETS = "barry"
+   arg_my_special_install_CONFIGURATIONS <UNSET> # was not present
+   arg_my_special_install_UNPARSED_ARGUMENTS <UNSET>
+   arg_my_special_install_KEYWORDS_MISSING_VALUES = "RENAME"
 
 Keywords terminate lists of values. If a keyword is given directly after a
 ``<one_value_keyword>``, that preceding ``<one_value_keyword>`` receives no
 value and the keyword is added to the ``<prefix>_KEYWORDS_MISSING_VALUES``
-variable. For the above example, the call
-``my_install(TARGETS foo DESTINATION OPTIONAL)`` would result in
-``MY_INSTALL_OPTIONAL`` being set to ``TRUE`` and ``MY_INSTALL_DESTINATION``
-being unset.  The ``MY_INSTALL_KEYWORDS_MISSING_VALUES`` variable would hold
-the value ``DESTINATION``.
+variable. In the above example, the call to ``my_special_install()`` contains
+the ``RENAME`` keyword immediately followed by the ``FAST`` keyword.
+In this case, ``FAST`` terminates processing of the ``RENAME`` keyword.
+``arg_my_special_install_FAST`` is set to ``TRUE``,
+``arg_my_special_install_RENAME`` is unset, and
+``arg_my_special_install_KEYWORDS_MISSING_VALUES`` contains the value
+``RENAME``.
 
 See Also
 ^^^^^^^^