summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2021-05-20 13:19:06 (GMT)
committerKitware Robot <kwrobot@kitware.com>2021-05-20 13:19:14 (GMT)
commit35ea23a618a83902a83659a1f422a0f3af90c249 (patch)
tree397a5ca2ce7a44cf9e623d9c9945587a817982b0
parent34f9a551ce5631baef159076c697dd8f86daa8b8 (diff)
parent396e0a840e75afb3f5ed7b50892b93ce946fac2e (diff)
downloadCMake-35ea23a618a83902a83659a1f422a0f3af90c249.zip
CMake-35ea23a618a83902a83659a1f422a0f3af90c249.tar.gz
CMake-35ea23a618a83902a83659a1f422a0f3af90c249.tar.bz2
Merge topic 'cmCommandLineArgument_understands_exact_versus_matching_variables'
396e0a840e cmCommandLineArgument: OneOrMore mode supports `=` separator 372bf1bcc4 cmCommandLineArgument: Understands which commands require partial matching Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !6142
-rw-r--r--Source/cmCommandLineArgument.h111
-rw-r--r--Source/cmake.cxx66
-rw-r--r--Source/cmakemain.cxx6
-rw-r--r--Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt3
-rw-r--r--Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt2
5 files changed, 133 insertions, 55 deletions
diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h
index 5031c65..72ab045 100644
--- a/Source/cmCommandLineArgument.h
+++ b/Source/cmCommandLineArgument.h
@@ -17,10 +17,25 @@ struct cmCommandLineArgument
OneOrMore
};
+ enum class RequiresSeparator
+ {
+ Yes,
+ No
+ };
+
+ enum class ParseMode
+ {
+ Valid,
+ Invalid,
+ SyntaxError,
+ ValueError
+ };
+
std::string InvalidSyntaxMessage;
std::string InvalidValueMessage;
std::string Name;
Values Type;
+ RequiresSeparator SeparatorNeeded;
std::function<FunctionSignature> StoreCall;
template <typename FunctionType>
@@ -29,6 +44,19 @@ struct cmCommandLineArgument
, InvalidValueMessage(cmStrCat("Invalid value used with ", n))
, Name(std::move(n))
, Type(t)
+ , SeparatorNeeded(RequiresSeparator::Yes)
+ , StoreCall(std::forward<FunctionType>(func))
+ {
+ }
+
+ template <typename FunctionType>
+ cmCommandLineArgument(std::string n, Values t, RequiresSeparator s,
+ FunctionType&& func)
+ : InvalidSyntaxMessage(cmStrCat(" is invalid syntax for ", n))
+ , InvalidValueMessage(cmStrCat("Invalid value used with ", n))
+ , Name(std::move(n))
+ , Type(t)
+ , SeparatorNeeded(s)
, StoreCall(std::forward<FunctionType>(func))
{
}
@@ -40,14 +68,39 @@ struct cmCommandLineArgument
, InvalidValueMessage(std::move(failedMsg))
, Name(std::move(n))
, Type(t)
+ , SeparatorNeeded(RequiresSeparator::Yes)
+ , StoreCall(std::forward<FunctionType>(func))
+ {
+ }
+
+ template <typename FunctionType>
+ cmCommandLineArgument(std::string n, std::string failedMsg, Values t,
+ RequiresSeparator s, FunctionType&& func)
+ : InvalidSyntaxMessage(cmStrCat(" is invalid syntax for ", n))
+ , InvalidValueMessage(std::move(failedMsg))
+ , Name(std::move(n))
+ , Type(t)
+ , SeparatorNeeded(s)
, StoreCall(std::forward<FunctionType>(func))
{
}
bool matches(std::string const& input) const
{
- return (this->Type == Values::Zero) ? (input == this->Name)
- : cmHasPrefix(input, this->Name);
+ bool matched = false;
+ if (this->Type == Values::Zero) {
+ matched = (input == this->Name);
+ } else if (this->SeparatorNeeded == RequiresSeparator::No) {
+ matched = cmHasPrefix(input, this->Name);
+ } else if (cmHasPrefix(input, this->Name)) {
+ if (input.size() == this->Name.size()) {
+ matched = true;
+ } else {
+ matched =
+ (input[this->Name.size()] == '=' || input[this->Name.size()] == ' ');
+ }
+ }
+ return matched;
}
template <typename T, typename... CallState>
@@ -55,13 +108,6 @@ struct cmCommandLineArgument
std::vector<std::string> const& allArgs,
CallState&&... state) const
{
- enum class ParseMode
- {
- Valid,
- Invalid,
- SyntaxError,
- ValueError
- };
ParseMode parseState = ParseMode::Valid;
if (this->Type == Values::Zero) {
@@ -95,23 +141,10 @@ struct cmCommandLineArgument
index = nextValueIndex;
}
} else {
- // parse the string to get the value
- auto possible_value = cm::string_view(input).substr(this->Name.size());
- if (possible_value.empty()) {
- parseState = ParseMode::ValueError;
- } else if (possible_value[0] == '=') {
- possible_value.remove_prefix(1);
- if (possible_value.empty()) {
- parseState = ParseMode::ValueError;
- }
- }
+ auto value = this->extract_single_value(input, parseState);
if (parseState == ParseMode::Valid) {
- if (possible_value[0] == ' ') {
- possible_value.remove_prefix(1);
- }
-
- parseState = this->StoreCall(std::string(possible_value),
- std::forward<CallState>(state)...)
+ parseState =
+ this->StoreCall(value, std::forward<CallState>(state)...)
? ParseMode::Valid
: ParseMode::Invalid;
}
@@ -149,7 +182,13 @@ struct cmCommandLineArgument
index = (nextValueIndex - 1);
}
} else {
- parseState = ParseMode::SyntaxError;
+ auto value = this->extract_single_value(input, parseState);
+ if (parseState == ParseMode::Valid) {
+ parseState =
+ this->StoreCall(value, std::forward<CallState>(state)...)
+ ? ParseMode::Valid
+ : ParseMode::Invalid;
+ }
}
}
@@ -161,4 +200,24 @@ struct cmCommandLineArgument
}
return (parseState == ParseMode::Valid);
}
+
+private:
+ std::string extract_single_value(std::string const& input,
+ ParseMode& parseState) const
+ {
+ // parse the string to get the value
+ auto possible_value = cm::string_view(input).substr(this->Name.size());
+ if (possible_value.empty()) {
+ parseState = ParseMode::ValueError;
+ } else if (possible_value[0] == '=') {
+ possible_value.remove_prefix(1);
+ if (possible_value.empty()) {
+ parseState = ParseMode::ValueError;
+ }
+ }
+ if (parseState == ParseMode::Valid && possible_value[0] == ' ') {
+ possible_value.remove_prefix(1);
+ }
+ return std::string(possible_value);
+ }
};
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 5440984..315bd20 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -529,25 +529,29 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
std::vector<CommandArgument> arguments = {
CommandArgument{ "-D", "-D must be followed with VAR=VALUE.",
- CommandArgument::Values::One, DefineLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, DefineLambda },
CommandArgument{ "-W", "-W must be followed with [no-]<name>.",
- CommandArgument::Values::One, WarningLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, WarningLambda },
CommandArgument{ "-U", "-U must be followed with VAR.",
- CommandArgument::Values::One, UnSetLambda },
- CommandArgument{ "-C", "-C must be followed by a file name.",
CommandArgument::Values::One,
- [&](std::string const& value, cmake* state) -> bool {
- cmSystemTools::Stdout("loading initial cache file " +
- value + "\n");
- // Resolve script path specified on command line
- // relative to $PWD.
- auto path = cmSystemTools::CollapseFullPath(value);
- state->ReadListFile(args, path);
- return true;
- } },
+ CommandArgument::RequiresSeparator::No, UnSetLambda },
+ CommandArgument{
+ "-C", "-C must be followed by a file name.",
+ CommandArgument::Values::One, CommandArgument::RequiresSeparator::No,
+ [&](std::string const& value, cmake* state) -> bool {
+ cmSystemTools::Stdout("loading initial cache file " + value + "\n");
+ // Resolve script path specified on command line
+ // relative to $PWD.
+ auto path = cmSystemTools::CollapseFullPath(value);
+ state->ReadListFile(args, path);
+ return true;
+ } },
CommandArgument{ "-P", "-P must be followed by a file name.",
- CommandArgument::Values::One, ScriptLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, ScriptLambda },
CommandArgument{ "--toolchain", "No file specified for --toolchain",
CommandArgument::Values::One, ToolchainLambda },
CommandArgument{ "--install-prefix",
@@ -830,31 +834,44 @@ void cmake::SetArgs(const std::vector<std::string>& args)
std::vector<CommandArgument> arguments = {
CommandArgument{ "-S", "No source directory specified for -S",
- CommandArgument::Values::One, SourceArgLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, SourceArgLambda },
CommandArgument{ "-H", "No source directory specified for -H",
- CommandArgument::Values::One, SourceArgLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, SourceArgLambda },
CommandArgument{ "-O", CommandArgument::Values::Zero,
IgnoreAndTrueLambda },
CommandArgument{ "-B", "No build directory specified for -B",
- CommandArgument::Values::One, BuildArgLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, BuildArgLambda },
CommandArgument{ "-P", "-P must be followed by a file name.",
CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
[&](std::string const&, cmake*) -> bool {
scriptMode = true;
return true;
} },
CommandArgument{ "-D", "-D must be followed with VAR=VALUE.",
- CommandArgument::Values::One, IgnoreAndTrueLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
+ IgnoreAndTrueLambda },
CommandArgument{ "-C", "-C must be followed by a file name.",
- CommandArgument::Values::One, IgnoreAndTrueLambda },
- CommandArgument{ "-U", "-U must be followed with VAR.",
- CommandArgument::Values::One, IgnoreAndTrueLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
+ IgnoreAndTrueLambda },
+ CommandArgument{
+ "-U", "-U must be followed with VAR.", CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, IgnoreAndTrueLambda },
CommandArgument{ "-W", "-W must be followed with [no-]<name>.",
- CommandArgument::Values::One, IgnoreAndTrueLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
+ IgnoreAndTrueLambda },
CommandArgument{ "-A", "No platform specified for -A",
- CommandArgument::Values::One, PlatformLambda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, PlatformLambda },
CommandArgument{ "-T", "No toolset specified for -T",
- CommandArgument::Values::One, ToolsetLamda },
+ CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No, ToolsetLamda },
CommandArgument{ "--toolchain", "No file specified for --toolchain",
CommandArgument::Values::One, IgnoreAndTrueLambda },
CommandArgument{ "--install-prefix",
@@ -1079,6 +1096,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
bool badGeneratorName = false;
CommandArgument generatorCommand(
"-G", "No generator specified for -G", CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
[&](std::string const& value, cmake* state) -> bool {
bool valid = state->CreateAndSetGlobalGenerator(value, true);
badGeneratorName = !valid;
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index ad64818..997d855 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -271,6 +271,7 @@ int do_cmake(int ac, char const* const* av)
} },
CommandArgument{ "-P", "No script specified for argument -P",
CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::No,
[&](std::string const& value) -> bool {
workingMode = cmake::SCRIPT_MODE;
parsedArgs.emplace_back("-P");
@@ -476,9 +477,10 @@ int do_build(int ac, char const* const* av)
listPresets = true;
return true;
} },
- CommandArgument{ "-j", CommandArgument::Values::ZeroOrOne, jLambda },
+ CommandArgument{ "-j", CommandArgument::Values::ZeroOrOne,
+ CommandArgument::RequiresSeparator::No, jLambda },
CommandArgument{ "--parallel", CommandArgument::Values::ZeroOrOne,
- parallelLambda },
+ CommandArgument::RequiresSeparator::No, parallelLambda },
CommandArgument{ "-t", CommandArgument::Values::OneOrMore, targetLambda },
CommandArgument{ "--target", CommandArgument::Values::OneOrMore,
targetLambda },
diff --git a/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt b/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt
index 5fe2539..fa3adc8 100644
--- a/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt
+++ b/Tests/RunCMake/CommandLine/build-invalid-target-syntax-stderr.txt
@@ -1,2 +1 @@
-^CMake Error: '--target=invalid' is invalid syntax for --target
-Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]
+^Error: could not load cache
diff --git a/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt
index d69338a..e4ad6b2 100644
--- a/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt
+++ b/Tests/RunCMake/CommandLine/build-unknown-command-partial-match-stderr.txt
@@ -1,2 +1,2 @@
-^CMake Error: '--targetinvalid' is invalid syntax for --target
+^Unknown argument --targetinvalid
Usage: cmake --build \[<dir> \| --preset <preset>\] \[options\] \[-- \[native-options\]\]