summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/CTest/cmCTestCoverageCommand.cxx12
-rw-r--r--Source/CTest/cmCTestCoverageCommand.h5
-rw-r--r--Source/CTest/cmCTestHandlerCommand.cxx10
-rw-r--r--Source/CTest/cmCTestHandlerCommand.h2
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx65
-rw-r--r--Source/CTest/cmCTestSubmitCommand.h10
-rw-r--r--Source/CTest/cmCTestUploadCommand.cxx2
-rw-r--r--Source/CTest/cmCTestUploadCommand.h2
-rw-r--r--Source/cmArgumentParser.cxx12
-rw-r--r--Source/cmArgumentParser.h44
-rw-r--r--Source/cmCMakeHostSystemInformationCommand.cxx2
-rw-r--r--Source/cmCMakePathCommand.cxx12
-rw-r--r--Source/cmExecuteProcessCommand.cxx6
-rw-r--r--Source/cmExportCommand.cxx13
-rw-r--r--Source/cmFileCommand.cxx218
-rw-r--r--Source/cmInstallCommand.cxx21
-rw-r--r--Source/cmParseArgumentsCommand.cxx4
-rw-r--r--Source/cmTargetSourcesCommand.cxx2
-rw-r--r--Tests/CMakeLib/testArgumentParser.cxx56
-rw-r--r--Tests/RunCMake/File_Configure/BadArgContent-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Configure/NoArgContent-result.txt1
-rw-r--r--Tests/RunCMake/File_Configure/NoArgContent-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Configure/NoArgContent.cmake1
-rw-r--r--Tests/RunCMake/File_Configure/NoArgOutput-result.txt1
-rw-r--r--Tests/RunCMake/File_Configure/NoArgOutput-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Configure/NoArgOutput.cmake1
-rw-r--r--Tests/RunCMake/File_Configure/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Generate/InputAndContent-check.cmake8
-rw-r--r--Tests/RunCMake/File_Generate/InputAndContent-input.txt1
-rw-r--r--Tests/RunCMake/File_Generate/InputAndContent.cmake10
-rw-r--r--Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Generate/RunCMakeTest.cmake1
34 files changed, 294 insertions, 254 deletions
diff --git a/Source/CTest/cmCTestCoverageCommand.cxx b/Source/CTest/cmCTestCoverageCommand.cxx
index 7432d08..97b0a89 100644
--- a/Source/CTest/cmCTestCoverageCommand.cxx
+++ b/Source/CTest/cmCTestCoverageCommand.cxx
@@ -4,7 +4,6 @@
#include <set>
-#include <cmext/algorithm>
#include <cmext/string_view>
#include "cmCTest.h"
@@ -18,13 +17,6 @@ void cmCTestCoverageCommand::BindArguments()
this->Bind("LABELS"_s, this->Labels);
}
-void cmCTestCoverageCommand::CheckArguments(
- std::vector<std::string> const& keywords)
-{
- this->LabelsMentioned =
- !this->Labels.empty() || cm::contains(keywords, "LABELS");
-}
-
cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
{
this->CTest->SetCTestConfigurationFromCMakeVariable(
@@ -36,9 +28,9 @@ cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
handler->Initialize();
// If a LABELS option was given, select only files with the labels.
- if (this->LabelsMentioned) {
+ if (this->Labels) {
handler->SetLabelFilter(
- std::set<std::string>(this->Labels.begin(), this->Labels.end()));
+ std::set<std::string>(this->Labels->begin(), this->Labels->end()));
}
handler->SetQuiet(this->Quiet);
diff --git a/Source/CTest/cmCTestCoverageCommand.h b/Source/CTest/cmCTestCoverageCommand.h
index 9344852..dc8f71e 100644
--- a/Source/CTest/cmCTestCoverageCommand.h
+++ b/Source/CTest/cmCTestCoverageCommand.h
@@ -9,6 +9,7 @@
#include <vector>
#include <cm/memory>
+#include <cm/optional>
#include "cmCTestHandlerCommand.h"
#include "cmCommand.h"
@@ -41,9 +42,7 @@ public:
protected:
void BindArguments() override;
- void CheckArguments(std::vector<std::string> const& keywords) override;
cmCTestGenericHandler* InitializeHandler() override;
- bool LabelsMentioned;
- std::vector<std::string> Labels;
+ cm::optional<std::vector<std::string>> Labels;
};
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index 5494d20..af365ad 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -7,6 +7,7 @@
#include <cstring>
#include <sstream>
+#include <cm/string_view>
#include <cmext/string_view>
#include "cmCTest.h"
@@ -81,11 +82,10 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
// Process input arguments.
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
- std::vector<std::string> parsedKeywords;
- this->Parse(args, &unparsedArguments, &keywordsMissingValue,
+ std::vector<cm::string_view> parsedKeywords;
+ this->Parse(args, &unparsedArguments, /*keywordsMissingValue=*/nullptr,
&parsedKeywords);
- this->CheckArguments(keywordsMissingValue);
+ this->CheckArguments();
std::sort(parsedKeywords.begin(), parsedKeywords.end());
auto it = std::adjacent_find(parsedKeywords.begin(), parsedKeywords.end());
@@ -242,6 +242,6 @@ void cmCTestHandlerCommand::BindArguments()
this->Bind("SUBMIT_INDEX"_s, this->SubmitIndex);
}
-void cmCTestHandlerCommand::CheckArguments(std::vector<std::string> const&)
+void cmCTestHandlerCommand::CheckArguments()
{
}
diff --git a/Source/CTest/cmCTestHandlerCommand.h b/Source/CTest/cmCTestHandlerCommand.h
index 756952d..31942c8 100644
--- a/Source/CTest/cmCTestHandlerCommand.h
+++ b/Source/CTest/cmCTestHandlerCommand.h
@@ -42,7 +42,7 @@ protected:
// Command argument handling.
virtual void BindArguments();
- virtual void CheckArguments(std::vector<std::string> const& keywords);
+ virtual void CheckArguments();
bool Append = false;
bool Quiet = false;
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index a2dc615..a1933cc 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -8,7 +8,6 @@
#include <cm/memory>
#include <cm/vector>
-#include <cmext/algorithm>
#include <cmext/string_view>
#include "cmCTest.h"
@@ -87,7 +86,7 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
// If FILES are given, but not PARTS, only the FILES are submitted
// and *no* PARTS are submitted.
// (This is why we select the empty "noParts" set in the
- // FilesMentioned block below...)
+ // if(this->Files) block below...)
//
// If PARTS are given, only the selected PARTS are submitted.
//
@@ -96,7 +95,7 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
// If given explicit FILES to submit, pass them to the handler.
//
- if (this->FilesMentioned) {
+ if (this->Files) {
// Intentionally select *no* PARTS. (Pass an empty set.) If PARTS
// were also explicitly mentioned, they will be selected below...
// But FILES with no PARTS mentioned should just submit the FILES
@@ -104,14 +103,14 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
//
handler->SelectParts(std::set<cmCTest::Part>());
handler->SelectFiles(
- std::set<std::string>(this->Files.begin(), this->Files.end()));
+ std::set<std::string>(this->Files->begin(), this->Files->end()));
}
// If a PARTS option was given, select only the named parts for submission.
//
- if (this->PartsMentioned) {
+ if (this->Parts) {
auto parts =
- cmMakeRange(this->Parts).transform([this](std::string const& arg) {
+ cmMakeRange(*(this->Parts)).transform([this](std::string const& arg) {
return this->CTest->GetPartFromName(arg);
});
handler->SelectParts(std::set<cmCTest::Part>(parts.begin(), parts.end()));
@@ -172,33 +171,31 @@ void cmCTestSubmitCommand::BindArguments()
this->cmCTestHandlerCommand::BindArguments();
}
-void cmCTestSubmitCommand::CheckArguments(
- std::vector<std::string> const& keywords)
+void cmCTestSubmitCommand::CheckArguments()
{
- this->PartsMentioned =
- !this->Parts.empty() || cm::contains(keywords, "PARTS");
- this->FilesMentioned =
- !this->Files.empty() || cm::contains(keywords, "FILES");
-
- cm::erase_if(this->Parts, [this](std::string const& arg) -> bool {
- cmCTest::Part p = this->CTest->GetPartFromName(arg);
- if (p == cmCTest::PartCount) {
- std::ostringstream e;
- e << "Part name \"" << arg << "\" is invalid.";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return true;
- }
- return false;
- });
-
- cm::erase_if(this->Files, [this](std::string const& arg) -> bool {
- if (!cmSystemTools::FileExists(arg)) {
- std::ostringstream e;
- e << "File \"" << arg << "\" does not exist. Cannot submit "
- << "a non-existent file.";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return true;
- }
- return false;
- });
+ if (this->Parts) {
+ cm::erase_if(*(this->Parts), [this](std::string const& arg) -> bool {
+ cmCTest::Part p = this->CTest->GetPartFromName(arg);
+ if (p == cmCTest::PartCount) {
+ std::ostringstream e;
+ e << "Part name \"" << arg << "\" is invalid.";
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return true;
+ }
+ return false;
+ });
+ }
+
+ if (this->Files) {
+ cm::erase_if(*(this->Files), [this](std::string const& arg) -> bool {
+ if (!cmSystemTools::FileExists(arg)) {
+ std::ostringstream e;
+ e << "File \"" << arg << "\" does not exist. Cannot submit "
+ << "a non-existent file.";
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return true;
+ }
+ return false;
+ });
+ }
}
diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h
index c5d11df..903bb64 100644
--- a/Source/CTest/cmCTestSubmitCommand.h
+++ b/Source/CTest/cmCTestSubmitCommand.h
@@ -8,6 +8,8 @@
#include <string>
#include <vector>
+#include <cm/optional>
+
#include "cmCTestHandlerCommand.h"
class cmCommand;
@@ -35,13 +37,11 @@ public:
protected:
void BindArguments() override;
- void CheckArguments(std::vector<std::string> const& keywords) override;
+ void CheckArguments() override;
cmCTestGenericHandler* InitializeHandler() override;
bool CDashUpload = false;
- bool FilesMentioned = false;
bool InternalTest = false;
- bool PartsMentioned = false;
std::string BuildID;
std::string CDashUploadFile;
@@ -50,7 +50,7 @@ protected:
std::string RetryDelay;
std::string SubmitURL;
- std::vector<std::string> Files;
+ cm::optional<std::vector<std::string>> Files;
std::vector<std::string> HttpHeaders;
- std::vector<std::string> Parts;
+ cm::optional<std::vector<std::string>> Parts;
};
diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx
index f86ee0d..2ed671c 100644
--- a/Source/CTest/cmCTestUploadCommand.cxx
+++ b/Source/CTest/cmCTestUploadCommand.cxx
@@ -21,7 +21,7 @@ void cmCTestUploadCommand::BindArguments()
this->Bind("CAPTURE_CMAKE_ERROR"_s, this->CaptureCMakeError);
}
-void cmCTestUploadCommand::CheckArguments(std::vector<std::string> const&)
+void cmCTestUploadCommand::CheckArguments()
{
cm::erase_if(this->Files, [this](std::string const& arg) -> bool {
if (!cmSystemTools::FileExists(arg)) {
diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h
index fe155f6..0dad2bf 100644
--- a/Source/CTest/cmCTestUploadCommand.h
+++ b/Source/CTest/cmCTestUploadCommand.h
@@ -42,7 +42,7 @@ public:
protected:
void BindArguments() override;
- void CheckArguments(std::vector<std::string> const&) override;
+ void CheckArguments() override;
cmCTestGenericHandler* InitializeHandler() override;
std::vector<std::string> Files;
diff --git a/Source/cmArgumentParser.cxx b/Source/cmArgumentParser.cxx
index 4624f1c..1a05dbc 100644
--- a/Source/cmArgumentParser.cxx
+++ b/Source/cmArgumentParser.cxx
@@ -44,14 +44,14 @@ void Instance::Bind(std::string& val)
this->ExpectValue = true;
}
-void Instance::Bind(StringList& val)
+void Instance::Bind(std::vector<std::string>& val)
{
this->CurrentString = nullptr;
this->CurrentList = &val;
this->ExpectValue = true;
}
-void Instance::Bind(MultiStringList& val)
+void Instance::Bind(std::vector<std::vector<std::string>>& val)
{
this->CurrentString = nullptr;
this->CurrentList = (static_cast<void>(val.emplace_back()), &val.back());
@@ -60,17 +60,17 @@ void Instance::Bind(MultiStringList& val)
void Instance::Consume(cm::string_view arg, void* result,
std::vector<std::string>* unparsedArguments,
- std::vector<std::string>* keywordsMissingValue,
- std::vector<std::string>* parsedKeywords)
+ std::vector<cm::string_view>* keywordsMissingValue,
+ std::vector<cm::string_view>* parsedKeywords)
{
auto const it = this->Bindings.Find(arg);
if (it != this->Bindings.end()) {
if (parsedKeywords != nullptr) {
- parsedKeywords->emplace_back(arg);
+ parsedKeywords->emplace_back(it->first);
}
it->second(*this, result);
if (this->ExpectValue && keywordsMissingValue != nullptr) {
- keywordsMissingValue->emplace_back(arg);
+ keywordsMissingValue->emplace_back(it->first);
}
return;
}
diff --git a/Source/cmArgumentParser.h b/Source/cmArgumentParser.h
index 71ed844..8be5a9c 100644
--- a/Source/cmArgumentParser.h
+++ b/Source/cmArgumentParser.h
@@ -10,14 +10,12 @@
#include <utility>
#include <vector>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/string_view>
namespace ArgumentParser {
-using StringList = std::vector<std::string>;
-using MultiStringList = std::vector<StringList>;
-
class Instance;
using Action = std::function<void(Instance&, void*)>;
@@ -39,18 +37,28 @@ public:
void Bind(bool& val);
void Bind(std::string& val);
- void Bind(StringList& val);
- void Bind(MultiStringList& val);
+ void Bind(std::vector<std::string>& val);
+ void Bind(std::vector<std::vector<std::string>>& val);
+
+ // cm::optional<> records the presence the keyword to which it binds.
+ template <typename T>
+ void Bind(cm::optional<T>& optVal)
+ {
+ if (!optVal) {
+ optVal.emplace();
+ }
+ this->Bind(*optVal);
+ }
void Consume(cm::string_view arg, void* result,
std::vector<std::string>* unparsedArguments,
- std::vector<std::string>* keywordsMissingValue,
- std::vector<std::string>* parsedKeywords);
+ std::vector<cm::string_view>* keywordsMissingValue,
+ std::vector<cm::string_view>* parsedKeywords);
private:
ActionMap const& Bindings;
std::string* CurrentString = nullptr;
- StringList* CurrentList = nullptr;
+ std::vector<std::string>* CurrentList = nullptr;
bool ExpectValue = false;
};
@@ -78,9 +86,9 @@ public:
template <typename Range>
void Parse(Result& result, Range const& args,
- std::vector<std::string>* unparsedArguments = nullptr,
- std::vector<std::string>* keywordsMissingValue = nullptr,
- std::vector<std::string>* parsedKeywords = nullptr) const
+ std::vector<std::string>* unparsedArguments,
+ std::vector<cm::string_view>* keywordsMissingValue = nullptr,
+ std::vector<cm::string_view>* parsedKeywords = nullptr) const
{
ArgumentParser::Instance instance(this->Bindings);
for (cm::string_view arg : args) {
@@ -90,10 +98,9 @@ public:
}
template <typename Range>
- Result Parse(Range const& args,
- std::vector<std::string>* unparsedArguments = nullptr,
- std::vector<std::string>* keywordsMissingValue = nullptr,
- std::vector<std::string>* parsedKeywords = nullptr) const
+ Result Parse(Range const& args, std::vector<std::string>* unparsedArguments,
+ std::vector<cm::string_view>* keywordsMissingValue = nullptr,
+ std::vector<cm::string_view>* parsedKeywords = nullptr) const
{
Result result;
this->Parse(result, args, unparsedArguments, keywordsMissingValue,
@@ -118,10 +125,9 @@ public:
}
template <typename Range>
- void Parse(Range const& args,
- std::vector<std::string>* unparsedArguments = nullptr,
- std::vector<std::string>* keywordsMissingValue = nullptr,
- std::vector<std::string>* parsedKeywords = nullptr) const
+ void Parse(Range const& args, std::vector<std::string>* unparsedArguments,
+ std::vector<cm::string_view>* keywordsMissingValue = nullptr,
+ std::vector<cm::string_view>* parsedKeywords = nullptr) const
{
ArgumentParser::Instance instance(this->Bindings);
for (cm::string_view arg : args) {
diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
index 0750eea..033dd6d 100644
--- a/Source/cmCMakeHostSystemInformationCommand.cxx
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -491,7 +491,7 @@ bool QueryWindowsRegistry(Range args, cmExecutionStatus& status,
.Bind("SEPARATOR"_s, &Arguments::Separator)
.Bind("ERROR_VARIABLE"_s, &Arguments::ErrorVariable);
std::vector<std::string> invalidArgs;
- std::vector<std::string> keywordsMissingValue;
+ std::vector<cm::string_view> keywordsMissingValue;
Arguments const arguments =
parser.Parse(args.advance(1), &invalidArgs, &keywordsMissingValue);
diff --git a/Source/cmCMakePathCommand.cxx b/Source/cmCMakePathCommand.cxx
index bf94c2d..adcffa9 100644
--- a/Source/cmCMakePathCommand.cxx
+++ b/Source/cmCMakePathCommand.cxx
@@ -44,8 +44,8 @@ public:
template <int Advance = 2>
Result Parse(std::vector<std::string> const& args,
- std::vector<std::string>* keywordsMissingValue = nullptr,
- std::vector<std::string>* parsedKeywords = nullptr) const
+ std::vector<cm::string_view>* keywordsMissingValue = nullptr,
+ std::vector<cm::string_view>* parsedKeywords = nullptr) const
{
this->Inputs.clear();
@@ -89,11 +89,11 @@ public:
args, &this->KeywordsMissingValue, &this->ParsedKeywords);
}
- const std::vector<std::string>& GetKeywordsMissingValue() const
+ const std::vector<cm::string_view>& GetKeywordsMissingValue() const
{
return this->KeywordsMissingValue;
}
- const std::vector<std::string>& GetParsedKeywords() const
+ const std::vector<cm::string_view>& GetParsedKeywords() const
{
return this->ParsedKeywords;
}
@@ -121,8 +121,8 @@ public:
}
private:
- mutable std::vector<std::string> KeywordsMissingValue;
- mutable std::vector<std::string> ParsedKeywords;
+ mutable std::vector<cm::string_view> KeywordsMissingValue;
+ mutable std::vector<cm::string_view> ParsedKeywords;
};
struct OutputVariable
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index 222ea80..af56e2d 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -95,13 +95,13 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
.Bind("COMMAND_ERROR_IS_FATAL"_s, &Arguments::CommandErrorIsFatal);
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
+ std::vector<cm::string_view> keywordsMissingValue;
Arguments const arguments =
parser.Parse(args, &unparsedArguments, &keywordsMissingValue);
if (!keywordsMissingValue.empty()) {
- status.SetError(" called with no value for " +
- keywordsMissingValue.front() + ".");
+ status.SetError(cmStrCat(" called with no value for ",
+ keywordsMissingValue.front(), "."));
return false;
}
if (!unparsedArguments.empty()) {
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 63440a3..198874e 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -7,7 +7,7 @@
#include <utility>
#include <cm/memory>
-#include <cmext/algorithm>
+#include <cm/optional>
#include <cmext/string_view>
#include "cmsys/RegularExpression.hxx"
@@ -57,7 +57,7 @@ bool cmExportCommand(std::vector<std::string> const& args,
struct Arguments
{
std::string ExportSetName;
- std::vector<std::string> Targets;
+ cm::optional<std::vector<std::string>> Targets;
std::string Namespace;
std::string Filename;
std::string AndroidMKFile;
@@ -79,9 +79,7 @@ bool cmExportCommand(std::vector<std::string> const& args,
}
std::vector<std::string> unknownArgs;
- std::vector<std::string> keywordsMissingValue;
- Arguments const arguments =
- parser.Parse(args, &unknownArgs, &keywordsMissingValue);
+ Arguments const arguments = parser.Parse(args, &unknownArgs);
if (!unknownArgs.empty()) {
status.SetError("Unknown argument: \"" + unknownArgs.front() + "\".");
@@ -145,9 +143,8 @@ bool cmExportCommand(std::vector<std::string> const& args,
return false;
}
exportSet = &it->second;
- } else if (!arguments.Targets.empty() ||
- cm::contains(keywordsMissingValue, "TARGETS")) {
- for (std::string const& currentTarget : arguments.Targets) {
+ } else if (arguments.Targets) {
+ for (std::string const& currentTarget : *arguments.Targets) {
if (mf.IsAlias(currentTarget)) {
std::ostringstream e;
e << "given ALIAS target \"" << currentTarget
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 1cfe29c..1082387 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -172,7 +172,8 @@ bool HandleReadCommand(std::vector<std::string> const& args,
.Bind("LIMIT"_s, &Arguments::Limit)
.Bind("HEX"_s, &Arguments::Hex);
- Arguments const arguments = parser.Parse(cmMakeRange(args).advance(3));
+ Arguments const arguments = parser.Parse(cmMakeRange(args).advance(3),
+ /*unparsedArguments=*/nullptr);
std::string fileName = fileNameArg;
if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
@@ -958,8 +959,8 @@ bool HandleRPathChangeCommand(std::vector<std::string> const& args,
bool removeEnvironmentRPath = false;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- std::vector<std::string> missingArgs;
- std::vector<std::string> parsedArgs;
+ std::vector<cm::string_view> missingArgs;
+ std::vector<cm::string_view> parsedArgs;
parser.Bind("FILE"_s, file)
.Bind("OLD_RPATH"_s, oldRPath)
.Bind("NEW_RPATH"_s, newRPath)
@@ -1028,8 +1029,8 @@ bool HandleRPathSetCommand(std::vector<std::string> const& args,
std::string newRPath;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- std::vector<std::string> missingArgs;
- std::vector<std::string> parsedArgs;
+ std::vector<cm::string_view> missingArgs;
+ std::vector<cm::string_view> parsedArgs;
parser.Bind("FILE"_s, file).Bind("NEW_RPATH"_s, newRPath);
parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs,
&parsedArgs);
@@ -1087,7 +1088,7 @@ bool HandleRPathRemoveCommand(std::vector<std::string> const& args,
std::string file;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- std::vector<std::string> missingArgs;
+ std::vector<cm::string_view> missingArgs;
parser.Bind("FILE"_s, file);
parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs);
if (!unknownArgs.empty()) {
@@ -1138,8 +1139,8 @@ bool HandleRPathCheckCommand(std::vector<std::string> const& args,
std::string rpath;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- std::vector<std::string> missingArgs;
- std::vector<std::string> parsedArgs;
+ std::vector<cm::string_view> missingArgs;
+ std::vector<cm::string_view> parsedArgs;
parser.Bind("FILE"_s, file).Bind("RPATH"_s, rpath);
parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs,
&parsedArgs);
@@ -1197,7 +1198,8 @@ bool HandleReadElfCommand(std::vector<std::string> const& args,
.Bind("RPATH"_s, &Arguments::RPath)
.Bind("RUNPATH"_s, &Arguments::RunPath)
.Bind("CAPTURE_ERROR"_s, &Arguments::Error);
- Arguments const arguments = parser.Parse(cmMakeRange(args).advance(2));
+ Arguments const arguments = parser.Parse(cmMakeRange(args).advance(2),
+ /*unparsedArguments=*/nullptr);
if (!cmSystemTools::FileExists(fileNameArg, true)) {
status.SetError(cmStrCat("READ_ELF given FILE \"", fileNameArg,
@@ -1252,7 +1254,7 @@ bool HandleRealPathCommand(std::vector<std::string> const& args,
struct Arguments
{
- std::string BaseDirectory;
+ cm::optional<std::string> BaseDirectory;
bool ExpandTilde = false;
};
static auto const parser =
@@ -1261,11 +1263,9 @@ bool HandleRealPathCommand(std::vector<std::string> const& args,
.Bind("EXPAND_TILDE"_s, &Arguments::ExpandTilde);
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
- std::vector<std::string> parsedKeywords;
- auto arguments =
- parser.Parse(cmMakeRange(args).advance(3), &unparsedArguments,
- &keywordsMissingValue, &parsedKeywords);
+ std::vector<cm::string_view> keywordsMissingValue;
+ auto arguments = parser.Parse(cmMakeRange(args).advance(3),
+ &unparsedArguments, &keywordsMissingValue);
if (!unparsedArguments.empty()) {
status.SetError("REAL_PATH called with unexpected arguments");
@@ -1276,7 +1276,7 @@ bool HandleRealPathCommand(std::vector<std::string> const& args,
return false;
}
- if (parsedKeywords.empty()) {
+ if (!arguments.BaseDirectory) {
arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory();
}
@@ -1295,7 +1295,7 @@ bool HandleRealPathCommand(std::vector<std::string> const& args,
}
cmCMakePath path(input, cmCMakePath::auto_format);
- path = path.Absolute(arguments.BaseDirectory).Normal();
+ path = path.Absolute(*arguments.BaseDirectory).Normal();
auto realPath = cmSystemTools::GetRealPath(path.GenericString());
status.GetMakefile().AddDefinition(args[2], realPath);
@@ -2497,12 +2497,12 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
struct Arguments
{
- std::string Output;
- std::string Input;
- std::string Content;
- std::string Condition;
- std::string Target;
- std::string NewLineStyle;
+ cm::optional<std::string> Output;
+ cm::optional<std::string> Input;
+ cm::optional<std::string> Content;
+ cm::optional<std::string> Condition;
+ cm::optional<std::string> Target;
+ cm::optional<std::string> NewLineStyle;
bool NoSourcePermissions = false;
bool UseSourcePermissions = false;
std::vector<std::string> FilePermissions;
@@ -2521,14 +2521,16 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
.Bind("NEWLINE_STYLE"_s, &Arguments::NewLineStyle);
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValues;
- std::vector<std::string> parsedKeywords;
+ std::vector<cm::string_view> keywordsMissingValues;
+ std::vector<cm::string_view> parsedKeywords;
Arguments const arguments =
parser.Parse(cmMakeRange(args).advance(1), &unparsedArguments,
&keywordsMissingValues, &parsedKeywords);
if (!keywordsMissingValues.empty()) {
- status.SetError("Incorrect arguments to GENERATE subcommand.");
+ status.SetError(
+ cmStrCat("GENERATE keywords missing values:\n ",
+ cmJoin(cmMakeRange(keywordsMissingValues), "\n ")));
return false;
}
@@ -2537,56 +2539,41 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
return false;
}
- bool mandatoryOptionsSpecified = false;
- if (parsedKeywords.size() > 1) {
- const bool outputOprionSpecified = parsedKeywords[0] == "OUTPUT"_s;
- const bool inputOrContentSpecified =
- parsedKeywords[1] == "INPUT"_s || parsedKeywords[1] == "CONTENT"_s;
- if (outputOprionSpecified && inputOrContentSpecified) {
- mandatoryOptionsSpecified = true;
- }
+ if (!arguments.Output || parsedKeywords[0] != "OUTPUT"_s) {
+ status.SetError("GENERATE requires OUTPUT as first option.");
+ return false;
}
- if (!mandatoryOptionsSpecified) {
- status.SetError("Incorrect arguments to GENERATE subcommand.");
+ std::string const& output = *arguments.Output;
+
+ if (!arguments.Input && !arguments.Content) {
+ status.SetError("GENERATE requires INPUT or CONTENT option.");
return false;
}
+ const bool inputIsContent = parsedKeywords[1] == "CONTENT"_s;
+ if (!inputIsContent && parsedKeywords[1] == "INPUT") {
+ status.SetError("Unknown argument to GENERATE subcommand.");
+ }
+ std::string const& input =
+ inputIsContent ? *arguments.Content : *arguments.Input;
- const bool conditionOptionSpecified =
- std::find(parsedKeywords.begin(), parsedKeywords.end(), "CONDITION"_s) !=
- parsedKeywords.end();
- if (conditionOptionSpecified && arguments.Condition.empty()) {
+ if (arguments.Condition && arguments.Condition->empty()) {
status.SetError("CONDITION of sub-command GENERATE must not be empty "
"if specified.");
return false;
}
+ std::string const& condition =
+ arguments.Condition ? *arguments.Condition : std::string();
- const bool targetOptionSpecified =
- std::find(parsedKeywords.begin(), parsedKeywords.end(), "TARGET"_s) !=
- parsedKeywords.end();
- if (targetOptionSpecified && arguments.Target.empty()) {
+ if (arguments.Target && arguments.Target->empty()) {
status.SetError("TARGET of sub-command GENERATE must not be empty "
"if specified.");
return false;
}
+ std::string const& target =
+ arguments.Target ? *arguments.Target : std::string();
- const bool outputOptionSpecified =
- std::find(parsedKeywords.begin(), parsedKeywords.end(), "OUTPUT"_s) !=
- parsedKeywords.end();
- if (outputOptionSpecified && parsedKeywords[0] != "OUTPUT"_s) {
- status.SetError("Incorrect arguments to GENERATE subcommand.");
- return false;
- }
-
- const bool inputIsContent = parsedKeywords[1] != "INPUT"_s;
- if (inputIsContent && parsedKeywords[1] != "CONTENT") {
- status.SetError("Unknown argument to GENERATE subcommand.");
- }
-
- const bool newLineStyleSpecified =
- std::find(parsedKeywords.begin(), parsedKeywords.end(),
- "NEWLINE_STYLE"_s) != parsedKeywords.end();
cmNewLineStyle newLineStyle;
- if (newLineStyleSpecified) {
+ if (arguments.NewLineStyle) {
std::string errorMessage;
if (!newLineStyle.ReadFromArguments(args, errorMessage)) {
status.SetError(cmStrCat("GENERATE ", errorMessage));
@@ -2594,11 +2581,6 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
}
}
- std::string input = arguments.Input;
- if (inputIsContent) {
- input = arguments.Content;
- }
-
if (arguments.NoSourcePermissions && arguments.UseSourcePermissions) {
status.SetError("given both NO_SOURCE_PERMISSIONS and "
"USE_SOURCE_PERMISSIONS. Only one option allowed.");
@@ -2656,8 +2638,7 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
}
}
- AddEvaluationFile(input, arguments.Target, arguments.Output,
- arguments.Condition, inputIsContent,
+ AddEvaluationFile(input, target, output, condition, inputIsContent,
newLineStyle.GetCharacters(), permissions, status);
return true;
}
@@ -3102,7 +3083,7 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
.Bind("POST_EXCLUDE_FILES_STRICT"_s, &Arguments::PostExcludeFilesStrict);
std::vector<std::string> unrecognizedArguments;
- std::vector<std::string> keywordsMissingValues;
+ std::vector<cm::string_view> keywordsMissingValues;
auto parsedArgs =
parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
&keywordsMissingValues);
@@ -3114,18 +3095,18 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
}
// Arguments that are allowed to be empty lists. Keep entries sorted!
- const std::vector<std::string> LIST_ARGS = {
- "DIRECTORIES",
- "EXECUTABLES",
- "LIBRARIES",
- "MODULES",
- "POST_EXCLUDE_FILES",
- "POST_EXCLUDE_FILES_STRICT",
- "POST_EXCLUDE_REGEXES",
- "POST_INCLUDE_FILES",
- "POST_INCLUDE_REGEXES",
- "PRE_EXCLUDE_REGEXES",
- "PRE_INCLUDE_REGEXES",
+ static const std::vector<cm::string_view> LIST_ARGS = {
+ "DIRECTORIES"_s,
+ "EXECUTABLES"_s,
+ "LIBRARIES"_s,
+ "MODULES"_s,
+ "POST_EXCLUDE_FILES"_s,
+ "POST_EXCLUDE_FILES_STRICT"_s,
+ "POST_EXCLUDE_REGEXES"_s,
+ "POST_INCLUDE_FILES"_s,
+ "POST_INCLUDE_REGEXES"_s,
+ "PRE_EXCLUDE_REGEXES"_s,
+ "PRE_INCLUDE_REGEXES"_s,
};
auto kwbegin = keywordsMissingValues.cbegin();
auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS);
@@ -3235,8 +3216,8 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
{
struct Arguments
{
- std::string Output;
- std::string Content;
+ cm::optional<std::string> Output;
+ cm::optional<std::string> Content;
bool EscapeQuotes = false;
bool AtOnly = false;
std::string NewlineStyle;
@@ -3251,11 +3232,10 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
.Bind("NEWLINE_STYLE"_s, &Arguments::NewlineStyle);
std::vector<std::string> unrecognizedArguments;
- std::vector<std::string> keywordsMissingArguments;
- std::vector<std::string> parsedKeywords;
+ std::vector<cm::string_view> keywordsMissingValues;
auto parsedArgs =
parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
- &keywordsMissingArguments, &parsedKeywords);
+ &keywordsMissingValues);
auto argIt = unrecognizedArguments.begin();
if (argIt != unrecognizedArguments.end()) {
@@ -3265,28 +3245,28 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
return false;
}
- std::vector<std::string> mandatoryOptions{ "OUTPUT", "CONTENT" };
- for (auto const& e : mandatoryOptions) {
- const bool optionHasNoValue =
- std::find(keywordsMissingArguments.begin(),
- keywordsMissingArguments.end(),
- e) != keywordsMissingArguments.end();
- if (optionHasNoValue) {
- status.SetError(cmStrCat("CONFIGURE ", e, " option needs a value."));
- cmSystemTools::SetFatalErrorOccurred();
- return false;
- }
+ // Arguments that are allowed to be empty lists. Keep entries sorted!
+ static const std::vector<cm::string_view> LIST_ARGS = {
+ "NEWLINE_STYLE"_s, // Filter here so we can issue a custom error below.
+ };
+ auto kwbegin = keywordsMissingValues.cbegin();
+ auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS);
+ if (kwend != kwbegin) {
+ status.SetError(cmStrCat("CONFIGURE keywords missing values:\n ",
+ cmJoin(cmMakeRange(kwbegin, kwend), "\n ")));
+ cmSystemTools::SetFatalErrorOccurred();
+ return false;
}
- for (auto const& e : mandatoryOptions) {
- const bool optionGiven =
- std::find(parsedKeywords.begin(), parsedKeywords.end(), e) !=
- parsedKeywords.end();
- if (!optionGiven) {
- status.SetError(cmStrCat("CONFIGURE ", e, " option is mandatory."));
- cmSystemTools::SetFatalErrorOccurred();
- return false;
- }
+ if (!parsedArgs.Output) {
+ status.SetError("CONFIGURE OUTPUT option is mandatory.");
+ cmSystemTools::SetFatalErrorOccurred();
+ return false;
+ }
+ if (!parsedArgs.Content) {
+ status.SetError("CONFIGURE CONTENT option is mandatory.");
+ cmSystemTools::SetFatalErrorOccurred();
+ return false;
}
std::string errorMessage;
@@ -3298,7 +3278,7 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
// Check for generator expressions
std::string outputFile = cmSystemTools::CollapseFullPath(
- parsedArgs.Output, status.GetMakefile().GetCurrentBinaryDirectory());
+ *parsedArgs.Output, status.GetMakefile().GetCurrentBinaryDirectory());
std::string::size_type pos = outputFile.find_first_of("<>");
if (pos != std::string::npos) {
@@ -3347,7 +3327,7 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
fout.SetCopyIfDifferent(true);
// copy input to output and expand variables from input at the same time
- std::stringstream sin(parsedArgs.Content, std::ios::in);
+ std::stringstream sin(*parsedArgs.Content, std::ios::in);
std::string inLine;
std::string outLine;
bool hasNewLine = false;
@@ -3392,7 +3372,7 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,
.Bind("PATHS"_s, &Arguments::Paths);
std::vector<std::string> unrecognizedArguments;
- std::vector<std::string> keywordsMissingValues;
+ std::vector<cm::string_view> keywordsMissingValues;
auto parsedArgs =
parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
&keywordsMissingValues);
@@ -3404,12 +3384,12 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,
}
// Arguments that are allowed to be empty lists. Keep entries sorted!
- const std::vector<std::string> LIST_ARGS = {
- "MTIME", // "MTIME" should not be in this list because it requires one
- // value, but it has long been accidentally accepted without
- // one and treated as if an empty value were given.
- // Fixing this would require a policy.
- "PATHS", // "PATHS" is here only so we can issue a custom error below.
+ static const std::vector<cm::string_view> LIST_ARGS = {
+ "MTIME"_s, // "MTIME" should not be in this list because it requires one
+ // value, but it has long been accidentally accepted without
+ // one and treated as if an empty value were given.
+ // Fixing this would require a policy.
+ "PATHS"_s, // "PATHS" is here only so we can issue a custom error below.
};
auto kwbegin = keywordsMissingValues.cbegin();
auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS);
@@ -3525,7 +3505,7 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,
.Bind("TOUCH"_s, &Arguments::Touch);
std::vector<std::string> unrecognizedArguments;
- std::vector<std::string> keywordsMissingValues;
+ std::vector<cm::string_view> keywordsMissingValues;
auto parsedArgs =
parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
&keywordsMissingValues);
@@ -3537,7 +3517,7 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,
}
// Arguments that are allowed to be empty lists. Keep entries sorted!
- const std::vector<std::string> LIST_ARGS = { "PATTERNS" };
+ static const std::vector<cm::string_view> LIST_ARGS = { "PATTERNS"_s };
auto kwbegin = keywordsMissingValues.cbegin();
auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS);
if (kwend != kwbegin) {
@@ -3648,7 +3628,7 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse,
.Bind("DIRECTORY_PERMISSIONS"_s, &Arguments::DirectoryPermissions);
std::vector<std::string> pathEntries;
- std::vector<std::string> keywordsMissingValues;
+ std::vector<cm::string_view> keywordsMissingValues;
Arguments parsedArgs = parser.Parse(cmMakeRange(args).advance(1),
&pathEntries, &keywordsMissingValues);
@@ -3672,7 +3652,7 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse,
if (!keywordsMissingValues.empty()) {
for (const auto& i : keywordsMissingValues) {
- status.SetError(i + " is not given any arguments");
+ status.SetError(cmStrCat(i, " is not given any arguments"));
cmSystemTools::SetFatalErrorOccurred();
}
return false;
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 7ca5b23..c03c205 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -12,6 +12,7 @@
#include <utility>
#include <cm/memory>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/string_view>
@@ -436,24 +437,22 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// These generic args also contain the targets and the export stuff
std::vector<std::string> targetList;
std::string exports;
- std::vector<std::string> runtimeDependenciesArgVector;
+ cm::optional<std::vector<std::string>> runtimeDependenciesArgVector;
std::string runtimeDependencySetArg;
std::vector<std::string> unknownArgs;
- std::vector<std::string> parsedArgs;
cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
genericArgs.Bind("TARGETS"_s, targetList);
genericArgs.Bind("EXPORT"_s, exports);
genericArgs.Bind("RUNTIME_DEPENDENCIES"_s, runtimeDependenciesArgVector);
genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
- genericArgs.Parse(genericArgVector, &unknownArgs, nullptr, &parsedArgs);
+ genericArgs.Parse(genericArgVector, &unknownArgs);
bool success = genericArgs.Finalize();
- bool withRuntimeDependencies =
- std::find(parsedArgs.begin(), parsedArgs.end(), "RUNTIME_DEPENDENCIES") !=
- parsedArgs.end();
RuntimeDependenciesArgs runtimeDependenciesArgs =
- RuntimeDependenciesArgHelper.Parse(runtimeDependenciesArgVector,
- &unknownArgs);
+ runtimeDependenciesArgVector
+ ? RuntimeDependenciesArgHelper.Parse(*runtimeDependenciesArgVector,
+ &unknownArgs)
+ : RuntimeDependenciesArgs();
cmInstallCommandArguments archiveArgs(helper.DefaultComponentName);
cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
@@ -597,7 +596,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
}
cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr;
- if (withRuntimeDependencies) {
+ if (runtimeDependenciesArgVector) {
if (!runtimeDependencySetArg.empty()) {
status.SetError("TARGETS cannot have both RUNTIME_DEPENDENCIES and "
"RUNTIME_DEPENDENCY_SET.");
@@ -1137,7 +1136,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
}
}
- if (withRuntimeDependencies && !runtimeDependencySet->Empty()) {
+ if (runtimeDependenciesArgVector && !runtimeDependencySet->Empty()) {
AddInstallRuntimeDependenciesGenerator(
helper, runtimeDependencySet, runtimeArgs, libraryArgs, frameworkArgs,
std::move(runtimeDependenciesArgs), installsRuntime, installsLibrary,
@@ -2106,7 +2105,7 @@ bool HandleRuntimeDependencySetMode(std::vector<std::string> const& args,
// These generic args also contain the runtime dependency set
std::string runtimeDependencySetArg;
std::vector<std::string> runtimeDependencyArgVector;
- std::vector<std::string> parsedArgs;
+ std::vector<cm::string_view> parsedArgs;
cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
genericArgs.Parse(genericArgVector, &runtimeDependencyArgVector, nullptr,
diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx
index 95f3e7e..5ea35e8 100644
--- a/Source/cmParseArgumentsCommand.cxx
+++ b/Source/cmParseArgumentsCommand.cxx
@@ -42,7 +42,7 @@ namespace {
using options_map = std::map<std::string, bool>;
using single_map = std::map<std::string, std::string>;
using multi_map = std::map<std::string, std::vector<std::string>>;
-using options_set = std::set<std::string>;
+using options_set = std::set<cm::string_view>;
struct UserArgumentParser : public cmArgumentParser<void>
{
@@ -208,7 +208,7 @@ bool cmParseArgumentsCommand(std::vector<std::string> const& args,
}
}
- std::vector<std::string> keywordsMissingValues;
+ std::vector<cm::string_view> keywordsMissingValues;
parser.Parse(list, &unparsed, &keywordsMissingValues);
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
index e4244a6..76b0384 100644
--- a/Source/cmTargetSourcesCommand.cxx
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -197,7 +197,7 @@ std::vector<std::string> TargetSourcesImpl::ConvertToAbsoluteContent(
bool TargetSourcesImpl::HandleFileSetMode(
const std::string& scope, const std::vector<std::string>& content)
{
- auto args = FileSetsArgsParser.Parse(content);
+ auto args = FileSetsArgsParser.Parse(content, /*unparsedArguments=*/nullptr);
for (auto& argList : args.FileSets) {
argList.emplace(argList.begin(), "FILE_SET"_s);
diff --git a/Tests/CMakeLib/testArgumentParser.cxx b/Tests/CMakeLib/testArgumentParser.cxx
index 965690c..52c5861 100644
--- a/Tests/CMakeLib/testArgumentParser.cxx
+++ b/Tests/CMakeLib/testArgumentParser.cxx
@@ -6,6 +6,7 @@
#include <string>
#include <vector>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/string_view>
@@ -19,39 +20,50 @@ struct Result
bool Option2 = false;
std::string String1;
- std::string String2;
+ cm::optional<std::string> String2;
+ cm::optional<std::string> String3;
std::vector<std::string> List1;
std::vector<std::string> List2;
- std::vector<std::string> List3;
+ cm::optional<std::vector<std::string>> List3;
+ cm::optional<std::vector<std::string>> List4;
+ cm::optional<std::vector<std::string>> List5;
std::vector<std::vector<std::string>> Multi1;
std::vector<std::vector<std::string>> Multi2;
- std::vector<std::vector<std::string>> Multi3;
+ cm::optional<std::vector<std::vector<std::string>>> Multi3;
+ cm::optional<std::vector<std::vector<std::string>>> Multi4;
};
std::initializer_list<cm::string_view> const args = {
/* clang-format off */
"OPTION_1", // option
+ // "OPTION_2", // option that is not present
"STRING_1", // string arg missing value
- "STRING_2", "foo", "bar", // string arg + unparsed value
+ "STRING_2", "foo", "bar", // string arg + unparsed value, presence captured
+ // "STRING_3", // string arg that is not present
"LIST_1", // list arg missing values
"LIST_2", "foo", "bar", // list arg with 2 elems
"LIST_3", "bar", // list arg ...
"LIST_3", "foo", // ... with continuation
+ "LIST_4", // list arg missing values, presence captured
+ // "LIST_5", // list arg that is not present
"MULTI_2", // multi list with 0 lists
"MULTI_3", "foo", "bar", // multi list with first list with two elems
"MULTI_3", "bar", "foo", // multi list with second list with two elems
+ // "MULTI_4", // multi list arg that is not present
/* clang-format on */
};
bool verifyResult(Result const& result,
std::vector<std::string> const& unparsedArguments,
- std::vector<std::string> const& keywordsMissingValue)
+ std::vector<cm::string_view> const& keywordsMissingValue)
{
static std::vector<std::string> const foobar = { "foo", "bar" };
static std::vector<std::string> const barfoo = { "bar", "foo" };
- static std::vector<std::string> const missing = { "STRING_1", "LIST_1" };
+ static std::vector<cm::string_view> const missing = { "STRING_1"_s,
+ "LIST_1"_s,
+ "LIST_4"_s };
#define ASSERT_TRUE(x) \
do { \
@@ -65,18 +77,26 @@ bool verifyResult(Result const& result,
ASSERT_TRUE(!result.Option2);
ASSERT_TRUE(result.String1.empty());
- ASSERT_TRUE(result.String2 == "foo");
+ ASSERT_TRUE(result.String2);
+ ASSERT_TRUE(*result.String2 == "foo");
+ ASSERT_TRUE(!result.String3);
ASSERT_TRUE(result.List1.empty());
ASSERT_TRUE(result.List2 == foobar);
- ASSERT_TRUE(result.List3 == barfoo);
+ ASSERT_TRUE(result.List3);
+ ASSERT_TRUE(*result.List3 == barfoo);
+ ASSERT_TRUE(result.List4);
+ ASSERT_TRUE(result.List4->empty());
+ ASSERT_TRUE(!result.List5);
ASSERT_TRUE(result.Multi1.empty());
ASSERT_TRUE(result.Multi2.size() == 1);
ASSERT_TRUE(result.Multi2[0].empty());
- ASSERT_TRUE(result.Multi3.size() == 2);
- ASSERT_TRUE(result.Multi3[0] == foobar);
- ASSERT_TRUE(result.Multi3[1] == barfoo);
+ ASSERT_TRUE(result.Multi3);
+ ASSERT_TRUE((*result.Multi3).size() == 2);
+ ASSERT_TRUE((*result.Multi3)[0] == foobar);
+ ASSERT_TRUE((*result.Multi3)[1] == barfoo);
+ ASSERT_TRUE(!result.Multi4);
ASSERT_TRUE(unparsedArguments.size() == 1);
ASSERT_TRUE(unparsedArguments[0] == "bar");
@@ -89,19 +109,23 @@ bool testArgumentParserDynamic()
{
Result result;
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
+ std::vector<cm::string_view> keywordsMissingValue;
cmArgumentParser<void>{}
.Bind("OPTION_1"_s, result.Option1)
.Bind("OPTION_2"_s, result.Option2)
.Bind("STRING_1"_s, result.String1)
.Bind("STRING_2"_s, result.String2)
+ .Bind("STRING_3"_s, result.String3)
.Bind("LIST_1"_s, result.List1)
.Bind("LIST_2"_s, result.List2)
.Bind("LIST_3"_s, result.List3)
+ .Bind("LIST_4"_s, result.List4)
+ .Bind("LIST_5"_s, result.List5)
.Bind("MULTI_1"_s, result.Multi1)
.Bind("MULTI_2"_s, result.Multi2)
.Bind("MULTI_3"_s, result.Multi3)
+ .Bind("MULTI_4"_s, result.Multi4)
.Parse(args, &unparsedArguments, &keywordsMissingValue);
return verifyResult(result, unparsedArguments, keywordsMissingValue);
@@ -115,15 +139,19 @@ bool testArgumentParserStatic()
.Bind("OPTION_2"_s, &Result::Option2)
.Bind("STRING_1"_s, &Result::String1)
.Bind("STRING_2"_s, &Result::String2)
+ .Bind("STRING_3"_s, &Result::String3)
.Bind("LIST_1"_s, &Result::List1)
.Bind("LIST_2"_s, &Result::List2)
.Bind("LIST_3"_s, &Result::List3)
+ .Bind("LIST_4"_s, &Result::List4)
+ .Bind("LIST_5"_s, &Result::List5)
.Bind("MULTI_1"_s, &Result::Multi1)
.Bind("MULTI_2"_s, &Result::Multi2)
- .Bind("MULTI_3"_s, &Result::Multi3);
+ .Bind("MULTI_3"_s, &Result::Multi3)
+ .Bind("MULTI_4"_s, &Result::Multi4);
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
+ std::vector<cm::string_view> keywordsMissingValue;
Result const result =
parser.Parse(args, &unparsedArguments, &keywordsMissingValue);
diff --git a/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt b/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt
index a6ea314..dd6a2e7 100644
--- a/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt
+++ b/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt
@@ -1,4 +1,6 @@
CMake Error at BadArgContent.cmake:[0-9]+ \(file\):
- file CONFIGURE CONTENT option needs a value.
+ file CONFIGURE keywords missing values:
+
+ CONTENT
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt b/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt
index b5a924c..e1bf7b4 100644
--- a/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt
+++ b/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt
@@ -1,4 +1,6 @@
CMake Error at BadArgOutput.cmake:[0-9]+ \(file\):
- file CONFIGURE OUTPUT option needs a value.
+ file CONFIGURE keywords missing values:
+
+ OUTPUT
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/File_Configure/NoArgContent-result.txt b/Tests/RunCMake/File_Configure/NoArgContent-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgContent-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Configure/NoArgContent-stderr.txt b/Tests/RunCMake/File_Configure/NoArgContent-stderr.txt
new file mode 100644
index 0000000..2e8dd9a
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgContent-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at NoArgContent.cmake:[0-9]+ \(file\):
+ file CONFIGURE CONTENT option is mandatory.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/File_Configure/NoArgContent.cmake b/Tests/RunCMake/File_Configure/NoArgContent.cmake
new file mode 100644
index 0000000..cf52c46
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgContent.cmake
@@ -0,0 +1 @@
+file(CONFIGURE OUTPUT "")
diff --git a/Tests/RunCMake/File_Configure/NoArgOutput-result.txt b/Tests/RunCMake/File_Configure/NoArgOutput-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgOutput-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Configure/NoArgOutput-stderr.txt b/Tests/RunCMake/File_Configure/NoArgOutput-stderr.txt
new file mode 100644
index 0000000..53de48b
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgOutput-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at NoArgOutput.cmake:[0-9]+ \(file\):
+ file CONFIGURE OUTPUT option is mandatory.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/File_Configure/NoArgOutput.cmake b/Tests/RunCMake/File_Configure/NoArgOutput.cmake
new file mode 100644
index 0000000..77e9cdc
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgOutput.cmake
@@ -0,0 +1 @@
+file(CONFIGURE CONTENT "")
diff --git a/Tests/RunCMake/File_Configure/RunCMakeTest.cmake b/Tests/RunCMake/File_Configure/RunCMakeTest.cmake
index 5022985..008ce67 100644
--- a/Tests/RunCMake/File_Configure/RunCMakeTest.cmake
+++ b/Tests/RunCMake/File_Configure/RunCMakeTest.cmake
@@ -9,6 +9,8 @@ run_cmake(DirOutput)
run_cmake(NewLineStyle-NoArg)
run_cmake(NewLineStyle-ValidArg)
run_cmake(NewLineStyle-WrongArg)
+run_cmake(NoArgOutput)
+run_cmake(NoArgContent)
run_cmake(SubDir)
run_cmake(AtOnly)
run_cmake(EscapeQuotes)
diff --git a/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt b/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt
index e823b25..4278bce 100644
--- a/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt
+++ b/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt
@@ -1,4 +1,6 @@
CMake Error at EmptyCondition1.cmake:2 \(file\):
- file Incorrect arguments to GENERATE subcommand.
+ file GENERATE keywords missing values:
+
+ CONDITION
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Generate/InputAndContent-check.cmake b/Tests/RunCMake/File_Generate/InputAndContent-check.cmake
new file mode 100644
index 0000000..5c9b803
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/InputAndContent-check.cmake
@@ -0,0 +1,8 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/output-INPUT.txt" input)
+if(NOT input MATCHES "INPUT file")
+ string(APPEND RunCMake_TEST_FAILED "INPUT incorrectly overridden by CONTENT")
+endif()
+file(READ "${RunCMake_TEST_BINARY_DIR}/output-CONTENT.txt" content)
+if(NOT content MATCHES "CONTENT argument")
+ string(APPEND RunCMake_TEST_FAILED "CONTENT incorrectly overridden by INPUT")
+endif()
diff --git a/Tests/RunCMake/File_Generate/InputAndContent-input.txt b/Tests/RunCMake/File_Generate/InputAndContent-input.txt
new file mode 100644
index 0000000..73f162b
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/InputAndContent-input.txt
@@ -0,0 +1 @@
+INPUT file
diff --git a/Tests/RunCMake/File_Generate/InputAndContent.cmake b/Tests/RunCMake/File_Generate/InputAndContent.cmake
new file mode 100644
index 0000000..9c3977a
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/InputAndContent.cmake
@@ -0,0 +1,10 @@
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output-INPUT.txt"
+ INPUT "${CMAKE_CURRENT_SOURCE_DIR}/InputAndContent-input.txt"
+ CONTENT "CONTENT argument"
+)
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output-CONTENT.txt"
+ CONTENT "CONTENT argument"
+ INPUT "${CMAKE_CURRENT_SOURCE_DIR}/InputAndContent-input.txt"
+)
diff --git a/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt
index bc71f2f..4059bf8 100644
--- a/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt
+++ b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt
@@ -1,4 +1,6 @@
CMake Error at NewLineStyle-NoArg.cmake:[0-9]+ \(file\):
- file Incorrect arguments to GENERATE subcommand.
+ file GENERATE keywords missing values:
+
+ NEWLINE_STYLE
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
index be3bf04..5a670ae 100644
--- a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
+++ b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
@@ -17,6 +17,7 @@ run_cmake(EmptyCondition2)
run_cmake(BadCondition)
run_cmake(DebugEvaluate)
run_cmake(GenerateSource)
+run_cmake(InputAndContent)
run_cmake(OutputNameMatchesSources)
run_cmake(OutputNameMatchesObjects)
run_cmake(OutputNameMatchesOtherSources)