This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake".
The branch, master has been updated via 18b0329a8165c92cf94b5b97c2425df090c877f0 (commit) via 5228432b45b7ce740b93f2c80c8c7ce6987d4bf1 (commit) via 8e746db6e11f9e017cd04552efaf40235d50363d (commit) from 89ca5d7fdce7730f38a719683059bbe02e6fb19d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=18b0329a8165c92cf94b5b97c2425df090c877f0 commit 18b0329a8165c92cf94b5b97c2425df090c877f0 Merge: 89ca5d7 5228432 Author: Kyle Edwards <kyle.edwa...@kitware.com> AuthorDate: Fri Feb 8 17:14:36 2019 +0000 Commit: Kitware Robot <kwro...@kitware.com> CommitDate: Fri Feb 8 12:14:46 2019 -0500 Merge topic 'cmake_parse_arguments-keywords_missing_values' 5228432b45 cmake_parse_arguments: add KEYWORDS_MISSING_VALUES 8e746db6e1 cmake_parse_arguments: Factor out part of implementation for re-use Acked-by: Kitware Robot <kwro...@kitware.com> Merge-request: !2910 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5228432b45b7ce740b93f2c80c8c7ce6987d4bf1 commit 5228432b45b7ce740b93f2c80c8c7ce6987d4bf1 Author: Torsten Robitzki <tors...@robitzki.de> AuthorDate: Mon Feb 4 20:39:25 2019 +0100 Commit: Kyle Edwards <kyle.edwa...@kitware.com> CommitDate: Thu Feb 7 12:59:10 2019 -0500 cmake_parse_arguments: add KEYWORDS_MISSING_VALUES Add KEYWORDS_MISSING_VALUES output variable to cmake_parse_arguments() to allow to detect keywords that received no values. Fixes: #18706 diff --git a/Help/command/cmake_parse_arguments.rst b/Help/command/cmake_parse_arguments.rst index c8327e2..196d90f 100644 --- a/Help/command/cmake_parse_arguments.rst +++ b/Help/command/cmake_parse_arguments.rst @@ -59,6 +59,11 @@ All remaining arguments are collected in a variable where recognized. This can be checked afterwards to see whether your macro was called with unrecognized parameters. +``<one_value_keywords>`` and ``<multi_value_keywords>`` that where given no +values at all are collected in a variable ``<prefix>_KEYWORDS_MISSING_VALUES`` +that will be undefined if all keywords received values. This can be checked +to see if there where keywords without any values given. + As an example here a ``my_install()`` macro, which takes similar arguments as the real :command:`install` command: @@ -77,7 +82,7 @@ Assume ``my_install()`` has been called like this: .. code-block:: cmake - my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub) + 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:: @@ -89,6 +94,8 @@ the following variables:: 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. @@ -97,5 +104,6 @@ one_value_keyword another recognized keyword follows, this is interpreted as the beginning of the new option. E.g. ``my_install(TARGETS foo DESTINATION OPTIONAL)`` would result in ``MY_INSTALL_DESTINATION`` set to ``"OPTIONAL"``, but as ``OPTIONAL`` -is a keyword itself ``MY_INSTALL_DESTINATION`` will be empty and -``MY_INSTALL_OPTIONAL`` will therefore be set to ``TRUE``. +is a keyword itself ``MY_INSTALL_DESTINATION`` will be empty (but added +to ``MY_INSTALL_KEYWORDS_MISSING_VALUES``) and ``MY_INSTALL_OPTIONAL`` will +therefore be set to ``TRUE``. diff --git a/Help/release/dev/cmake_parse_arguments-keywords_missing_values.rst b/Help/release/dev/cmake_parse_arguments-keywords_missing_values.rst new file mode 100644 index 0000000..c7fe96b --- /dev/null +++ b/Help/release/dev/cmake_parse_arguments-keywords_missing_values.rst @@ -0,0 +1,6 @@ +cmake_parse_arguments-keywords_missing_values +--------------------------------------------- + +* The :command:`cmake_parse_arguments` command gained an additional + ``<prefix>_KEYWORDS_MISSING_VALUES`` output variable to report + keyword arguments that were given by the caller with no values. diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx index cef0704..6231aab 100644 --- a/Source/cmParseArgumentsCommand.cxx +++ b/Source/cmParseArgumentsCommand.cxx @@ -14,7 +14,7 @@ class cmExecutionStatus; -static std::string escape_arg(const std::string& arg) +static std::string EscapeArg(const std::string& arg) { // replace ";" with "\;" so output argument lists will split correctly std::string escapedArg; @@ -28,7 +28,7 @@ static std::string escape_arg(const std::string& arg) } namespace { -enum InsideValues +enum insideValues { NONE, SINGLE, @@ -38,6 +38,22 @@ enum InsideValues typedef std::map<std::string, bool> options_map; typedef std::map<std::string, std::string> single_map; typedef std::map<std::string, std::vector<std::string>> multi_map; +typedef std::set<std::string> options_set; +} + +// function to be called every time, a new key word was parsed or all +// parameters where parsed. +static void DetectKeywordsMissingValues(insideValues currentState, + const std::string& currentArgName, + int& argumentsFound, + options_set& keywordsMissingValues) +{ + if (currentState == SINGLE || + (currentState == MULTI && argumentsFound == 0)) { + keywordsMissingValues.insert(currentArgName); + } + + argumentsFound = 0; } static void PassParsedArguments(const std::string& prefix, @@ -45,7 +61,8 @@ static void PassParsedArguments(const std::string& prefix, const options_map& options, const single_map& singleValArgs, const multi_map& multiValArgs, - const std::vector<std::string>& unparsed) + const std::vector<std::string>& unparsed, + const options_set& keywordsMissingValues) { for (auto const& iter : options) { makefile.AddDefinition(prefix + iter.first, @@ -75,6 +92,14 @@ static void PassParsedArguments(const std::string& prefix, } else { makefile.RemoveDefinition(prefix + "UNPARSED_ARGUMENTS"); } + + if (!keywordsMissingValues.empty()) { + makefile.AddDefinition( + prefix + "KEYWORDS_MISSING_VALUES", + cmJoin(cmMakeRange(keywordsMissingValues), ";").c_str()); + } else { + makefile.RemoveDefinition(prefix + "KEYWORDS_MISSING_VALUES"); + } } bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, @@ -161,7 +186,7 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, multiValArgs[iter]; // default initialize } - InsideValues insideValues = NONE; + insideValues insideValues = NONE; std::string currentArgName; list.clear(); @@ -197,10 +222,15 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, } } + options_set keywordsMissingValues; + int multiArgumentsFound = 0; + // iterate over the arguments list and fill in the values where applicable for (std::string const& arg : list) { const options_map::iterator optIter = options.find(arg); if (optIter != options.end()) { + DetectKeywordsMissingValues(insideValues, currentArgName, + multiArgumentsFound, keywordsMissingValues); insideValues = NONE; optIter->second = true; continue; @@ -208,6 +238,8 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, const single_map::iterator singleIter = singleValArgs.find(arg); if (singleIter != singleValArgs.end()) { + DetectKeywordsMissingValues(insideValues, currentArgName, + multiArgumentsFound, keywordsMissingValues); insideValues = SINGLE; currentArgName = arg; continue; @@ -215,6 +247,8 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, const multi_map::iterator multiIter = multiValArgs.find(arg); if (multiIter != multiValArgs.end()) { + DetectKeywordsMissingValues(insideValues, currentArgName, + multiArgumentsFound, keywordsMissingValues); insideValues = MULTI; currentArgName = arg; continue; @@ -226,15 +260,18 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, insideValues = NONE; break; case MULTI: + ++multiArgumentsFound; if (parseFromArgV) { - multiValArgs[currentArgName].push_back(escape_arg(arg)); + multiValArgs[currentArgName].push_back(EscapeArg(arg)); } else { multiValArgs[currentArgName].push_back(arg); } break; default: + multiArgumentsFound = 0; + if (parseFromArgV) { - unparsed.push_back(escape_arg(arg)); + unparsed.push_back(EscapeArg(arg)); } else { unparsed.push_back(arg); } @@ -242,8 +279,11 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, } } + DetectKeywordsMissingValues(insideValues, currentArgName, + multiArgumentsFound, keywordsMissingValues); + PassParsedArguments(prefix, *this->Makefile, options, singleValArgs, - multiValArgs, unparsed); + multiValArgs, unparsed, keywordsMissingValues); return true; } diff --git a/Tests/RunCMake/cmake_parse_arguments/KeyWordsMissingValues.cmake b/Tests/RunCMake/cmake_parse_arguments/KeyWordsMissingValues.cmake new file mode 100644 index 0000000..561f9c0 --- /dev/null +++ b/Tests/RunCMake/cmake_parse_arguments/KeyWordsMissingValues.cmake @@ -0,0 +1,133 @@ +include(${CMAKE_CURRENT_LIST_DIR}/test_utils.cmake) + +# No keywords that miss any values, _KEYWORDS_MISSING_VALUES should not be defined +cmake_parse_arguments(PREF "" "P1" "P2" P1 p1 P2 p2_a p2_b) + +TEST(PREF_KEYWORDS_MISSING_VALUES "UNDEFINED") + +# Keyword should even be deleted from the actual scope +set(PREF_KEYWORDS_MISSING_VALUES "What ever") +cmake_parse_arguments(PREF "" "" "") + +TEST(PREF_KEYWORDS_MISSING_VALUES "UNDEFINED") + +# Given missing keywords as only option +cmake_parse_arguments(PREF "" "P1" "P2" P1) + +TEST(PREF_KEYWORDS_MISSING_VALUES "P1") +TEST(PREF_P1 "UNDEFINED") +TEST(PREF_UNPARSED_ARGUMENTS "UNDEFINED") + +# Mixed with unparsed arguments +cmake_parse_arguments(UPREF "" "P1" "P2" A B P2 C P1) +TEST(UPREF_KEYWORDS_MISSING_VALUES "P1") +TEST(UPREF_UNPARSED_ARGUMENTS A B) + +# one_value_keyword followed by option +cmake_parse_arguments(REF "OP" "P1" "" P1 OP) +TEST(REF_KEYWORDS_MISSING_VALUES "P1") +TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED") +TEST(REF_OP "TRUE") + +# Counter Test +cmake_parse_arguments(REF "OP" "P1" "" P1 p1 OP) +TEST(REF_KEYWORDS_MISSING_VALUES "UNDEFINED") +TEST(REF_P1 "p1") +TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED") +TEST(REF_OP "TRUE") + +# one_value_keyword followed by a one_value_keyword +cmake_parse_arguments(REF "" "P1;P2" "" P1 P2 p2) +TEST(REF_KEYWORDS_MISSING_VALUES "P1") +TEST(REF_P1 "UNDEFINED") +TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED") +TEST(REF_P2 "p2") + +# Counter Test +cmake_parse_arguments(REF "" "P1;P2" "" P1 p1 P2 p2) +TEST(REF_KEYWORDS_MISSING_VALUES "UNDEFINED") +TEST(REF_P1 "p1") +TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED") +TEST(REF_P2 "p2") + +# one_value_keyword followed by a multi_value_keywords +cmake_parse_arguments(REF "" "P1" "P2" P1 P2 p1 p2) +TEST(REF_KEYWORDS_MISSING_VALUES "P1") +TEST(REF_P1 "UNDEFINED") +TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED") +TEST(REF_P2 p1 p2) + +# Counter Examples +cmake_parse_arguments(REF "" "P1" "P2" P1 p1 P2 p1 p2) +TEST(REF_KEYWORDS_MISSING_VALUES "UNDEFINED") +TEST(REF_P1 "p1") +TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED") +TEST(REF_P2 p1 p2) + +# multi_value_keywords as only option +cmake_parse_arguments(REF "" "P1" "P2" P2) +TEST(REF_KEYWORDS_MISSING_VALUES "P2") +TEST(REF_P1 "UNDEFINED") +TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED") +TEST(REF_P2 "UNDEFINED") + +# multi_value_keywords followed by option +cmake_parse_arguments(REF "O1" "" "P1" P1 O1) +TEST(REF_KEYWORDS_MISSING_VALUES "P1") +TEST(REF_P1 "UNDEFINED") +TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED") +TEST(REF_O1 "TRUE") + +# counter test +cmake_parse_arguments(REF "O1" "" "P1" P1 p1 p2 O1) +TEST(REF_KEYWORDS_MISSING_VALUES "UNDEFINED") +TEST(REF_P1 "p1;p2") +TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED") +TEST(REF_O1 "TRUE") + +# multi_value_keywords followed by one_value_keyword +cmake_parse_arguments(REF "" "P1" "P2" P2 P1 p1) +TEST(REF_KEYWORDS_MISSING_VALUES "P2") +TEST(REF_P1 "p1") +TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED") +TEST(REF_P2 "UNDEFINED") + +# counter test +cmake_parse_arguments(REF "" "P1" "P2" P2 p2 P1 p1) +TEST(REF_KEYWORDS_MISSING_VALUES "UNDEFINED") +TEST(REF_P1 "p1") +TEST(REF_UNPARSED_ARGUMENTS "UNDEFINED") +TEST(REF_P2 "p2") + +# one_value_keyword as last argument +cmake_parse_arguments(REF "" "P1" "P2" A P2 p2 P1) +TEST(REF_KEYWORDS_MISSING_VALUES "P1") +TEST(REF_P1 "UNDEFINED") +TEST(REF_UNPARSED_ARGUMENTS "A") +TEST(REF_P2 "p2") + +# multi_value_keywords as last argument +cmake_parse_arguments(REF "" "P1" "P2" P1 p1 P2) +TEST(REF_KEYWORDS_MISSING_VALUES "P2") +TEST(REF_P1 "p1") +TEST(REF_P2 "UNDEFINED") + +# Multiple one_value_keyword and multi_value_keywords at different places +cmake_parse_arguments(REF "O1;O2" "P1" "P2" P1 O1 P2 O2) +TEST(REF_KEYWORDS_MISSING_VALUES P1 P2) +TEST(REF_P1 "UNDEFINED") +TEST(REF_P2 "UNDEFINED") + +# Duplicated missing keywords +cmake_parse_arguments(REF "O1;O2" "P1" "P2" P1 O1 P2 O2 P1 P2) +TEST(REF_KEYWORDS_MISSING_VALUES P1 P2) +TEST(REF_P1 "UNDEFINED") +TEST(REF_P2 "UNDEFINED") + +# make sure keywords that are never used, don't get added to KEYWORDS_MISSING_VALUES +cmake_parse_arguments(REF "O1;O2" "P1" "P2") +TEST(REF_KEYWORDS_MISSING_VALUES "UNDEFINED") +TEST(REF_O1 FALSE) +TEST(REF_O2 FALSE) +TEST(REF_P1 UNDEFINED) +TEST(REF_P2 UNDEFINED) diff --git a/Tests/RunCMake/cmake_parse_arguments/RunCMakeTest.cmake b/Tests/RunCMake/cmake_parse_arguments/RunCMakeTest.cmake index 1e15b3b..505840d 100644 --- a/Tests/RunCMake/cmake_parse_arguments/RunCMakeTest.cmake +++ b/Tests/RunCMake/cmake_parse_arguments/RunCMakeTest.cmake @@ -11,3 +11,4 @@ run_cmake(BadArgvN2) run_cmake(BadArgvN3) run_cmake(BadArgvN4) run_cmake(CornerCasesArgvN) +run_cmake(KeyWordsMissingValues) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8e746db6e11f9e017cd04552efaf40235d50363d commit 8e746db6e11f9e017cd04552efaf40235d50363d Author: Torsten Robitzki <tors...@robitzki.de> AuthorDate: Mon Feb 4 20:29:41 2019 +0100 Commit: Brad King <brad.k...@kitware.com> CommitDate: Wed Feb 6 14:46:52 2019 -0500 cmake_parse_arguments: Factor out part of implementation for re-use diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx index 796974c..cef0704 100644 --- a/Source/cmParseArgumentsCommand.cxx +++ b/Source/cmParseArgumentsCommand.cxx @@ -27,6 +27,56 @@ static std::string escape_arg(const std::string& arg) return escapedArg; } +namespace { +enum InsideValues +{ + NONE, + SINGLE, + MULTI +}; + +typedef std::map<std::string, bool> options_map; +typedef std::map<std::string, std::string> single_map; +typedef std::map<std::string, std::vector<std::string>> multi_map; +} + +static void PassParsedArguments(const std::string& prefix, + cmMakefile& makefile, + const options_map& options, + const single_map& singleValArgs, + const multi_map& multiValArgs, + const std::vector<std::string>& unparsed) +{ + for (auto const& iter : options) { + makefile.AddDefinition(prefix + iter.first, + iter.second ? "TRUE" : "FALSE"); + } + + for (auto const& iter : singleValArgs) { + if (!iter.second.empty()) { + makefile.AddDefinition(prefix + iter.first, iter.second.c_str()); + } else { + makefile.RemoveDefinition(prefix + iter.first); + } + } + + for (auto const& iter : multiValArgs) { + if (!iter.second.empty()) { + makefile.AddDefinition(prefix + iter.first, + cmJoin(cmMakeRange(iter.second), ";").c_str()); + } else { + makefile.RemoveDefinition(prefix + iter.first); + } + } + + if (!unparsed.empty()) { + makefile.AddDefinition(prefix + "UNPARSED_ARGUMENTS", + cmJoin(cmMakeRange(unparsed), ";").c_str()); + } else { + makefile.RemoveDefinition(prefix + "UNPARSED_ARGUMENTS"); + } +} + bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus&) { @@ -67,9 +117,6 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, // define the result maps holding key/value pairs for // options, single values and multi values - typedef std::map<std::string, bool> options_map; - typedef std::map<std::string, std::string> single_map; - typedef std::map<std::string, std::vector<std::string>> multi_map; options_map options; single_map singleValArgs; multi_map multiValArgs; @@ -114,12 +161,7 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, multiValArgs[iter]; // default initialize } - enum insideValues - { - NONE, - SINGLE, - MULTI - } insideValues = NONE; + InsideValues insideValues = NONE; std::string currentArgName; list.clear(); @@ -200,36 +242,8 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, } } - // now iterate over the collected values and update their definition - // within the current scope. undefine if necessary. - - for (auto const& iter : options) { - this->Makefile->AddDefinition(prefix + iter.first, - iter.second ? "TRUE" : "FALSE"); - } - for (auto const& iter : singleValArgs) { - if (!iter.second.empty()) { - this->Makefile->AddDefinition(prefix + iter.first, iter.second.c_str()); - } else { - this->Makefile->RemoveDefinition(prefix + iter.first); - } - } - - for (auto const& iter : multiValArgs) { - if (!iter.second.empty()) { - this->Makefile->AddDefinition( - prefix + iter.first, cmJoin(cmMakeRange(iter.second), ";").c_str()); - } else { - this->Makefile->RemoveDefinition(prefix + iter.first); - } - } - - if (!unparsed.empty()) { - this->Makefile->AddDefinition(prefix + "UNPARSED_ARGUMENTS", - cmJoin(cmMakeRange(unparsed), ";").c_str()); - } else { - this->Makefile->RemoveDefinition(prefix + "UNPARSED_ARGUMENTS"); - } + PassParsedArguments(prefix, *this->Makefile, options, singleValArgs, + multiValArgs, unparsed); return true; } ----------------------------------------------------------------------- Summary of changes: Help/command/cmake_parse_arguments.rst | 14 ++- ...ake_parse_arguments-keywords_missing_values.rst | 6 + Source/cmParseArgumentsCommand.cxx | 136 ++++++++++++++------- .../KeyWordsMissingValues.cmake | 133 ++++++++++++++++++++ .../cmake_parse_arguments/RunCMakeTest.cmake | 1 + 5 files changed, 246 insertions(+), 44 deletions(-) create mode 100644 Help/release/dev/cmake_parse_arguments-keywords_missing_values.rst create mode 100644 Tests/RunCMake/cmake_parse_arguments/KeyWordsMissingValues.cmake hooks/post-receive -- CMake _______________________________________________ Cmake-commits mailing list Cmake-commits@cmake.org https://cmake.org/mailman/listinfo/cmake-commits