Merge topic 'revert-vs-ZERO_CHECK-proj'
26b724cf2b Merge branch 'backport-3.24-revert-vs-ZERO_CHECK-proj'
289932ded0 VS: Revert "Write ZERO_CHECK.proj for VS19 and above"
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !7499
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index 9949772..7a6188a 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -521,7 +521,7 @@
See :ref:`cmake_path(REMOVE_EXTENSION) <REMOVE_EXTENSION>` for more details.
-.. genex:: $<PATH:REPLACE_EXTENSION[,LAST_ONLY],path>
+.. genex:: $<PATH:REPLACE_EXTENSION[,LAST_ONLY],path,input>
.. versionadded:: 3.24
diff --git a/Help/policy/CMP0097.rst b/Help/policy/CMP0097.rst
index 2240874..24957d0 100644
--- a/Help/policy/CMP0097.rst
+++ b/Help/policy/CMP0097.rst
@@ -4,9 +4,11 @@
.. versionadded:: 3.16
:command:`ExternalProject_Add` with ``GIT_SUBMODULES ""`` initializes no
-submodules.
+submodules. The policy also applies to :command:`FetchContent_Declare`,
+which uses the same download and update features as
+:command:`ExternalProject_Add`.
-The module provides a ``GIT_SUBMODULES`` option which controls what submodules
+The commands provide a ``GIT_SUBMODULES`` option which controls what submodules
to initialize and update. Starting with CMake 3.16, explicitly setting
``GIT_SUBMODULES`` to an empty string means no submodules will be initialized
or updated.
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index b4b53c0..c5024a5 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 24)
-set(CMake_VERSION_PATCH 20220722)
+set(CMake_VERSION_PATCH 20220725)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/cmArgumentParser.cxx b/Source/cmArgumentParser.cxx
index f0c4cfc..25d5c68 100644
--- a/Source/cmArgumentParser.cxx
+++ b/Source/cmArgumentParser.cxx
@@ -5,10 +5,13 @@
#include <algorithm>
#include "cmArgumentParserTypes.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
namespace ArgumentParser {
-auto ActionMap::Emplace(cm::string_view name, Action action)
+auto KeywordActionMap::Emplace(cm::string_view name, KeywordAction action)
-> std::pair<iterator, bool>
{
auto const it =
@@ -21,7 +24,7 @@
: std::make_pair(this->emplace(it, name, std::move(action)), true);
}
-auto ActionMap::Find(cm::string_view name) const -> const_iterator
+auto KeywordActionMap::Find(cm::string_view name) const -> const_iterator
{
auto const it =
std::lower_bound(this->begin(), this->end(), name,
@@ -74,20 +77,16 @@
this->ExpectValue = false;
}
-void Instance::Consume(cm::string_view arg, void* result,
- std::vector<std::string>* unparsedArguments,
- std::vector<cm::string_view>* keywordsMissingValue,
- std::vector<cm::string_view>* parsedKeywords)
+void Instance::Consume(cm::string_view arg)
{
- auto const it = this->Bindings.Find(arg);
- if (it != this->Bindings.end()) {
- if (parsedKeywords != nullptr) {
- parsedKeywords->emplace_back(it->first);
+ auto const it = this->Bindings.Keywords.Find(arg);
+ if (it != this->Bindings.Keywords.end()) {
+ this->FinishKeyword();
+ this->Keyword = it->first;
+ if (this->ParsedKeywords != nullptr) {
+ this->ParsedKeywords->emplace_back(it->first);
}
- it->second(*this, result);
- if (this->ExpectValue && keywordsMissingValue != nullptr) {
- keywordsMissingValue->emplace_back(it->first);
- }
+ it->second(*this);
return;
}
@@ -97,16 +96,40 @@
this->CurrentList = nullptr;
} else if (this->CurrentList != nullptr) {
this->CurrentList->emplace_back(arg);
- } else if (unparsedArguments != nullptr) {
- unparsedArguments->emplace_back(arg);
+ } else if (this->UnparsedArguments != nullptr) {
+ this->UnparsedArguments->emplace_back(arg);
}
- if (this->ExpectValue) {
- if (keywordsMissingValue != nullptr) {
- keywordsMissingValue->pop_back();
- }
- this->ExpectValue = false;
+ this->ExpectValue = false;
+}
+
+void Instance::FinishKeyword()
+{
+ if (this->Keyword.empty()) {
+ return;
}
+ if (this->ExpectValue) {
+ if (this->ParseResults != nullptr) {
+ this->ParseResults->AddKeywordError(this->Keyword,
+ " missing required value\n");
+ }
+ if (this->KeywordsMissingValue != nullptr) {
+ this->KeywordsMissingValue->emplace_back(this->Keyword);
+ }
+ }
+}
+
+bool ParseResult::MaybeReportError(cmMakefile& mf) const
+{
+ if (*this) {
+ return false;
+ }
+ std::string e;
+ for (auto const& ke : this->KeywordErrors) {
+ e = cmStrCat(e, "Error after keyword \"", ke.first, "\":\n", ke.second);
+ }
+ mf.IssueMessage(MessageType::FATAL_ERROR, e);
+ return true;
}
} // namespace ArgumentParser
diff --git a/Source/cmArgumentParser.h b/Source/cmArgumentParser.h
index 26148d9..8fda8b7 100644
--- a/Source/cmArgumentParser.h
+++ b/Source/cmArgumentParser.h
@@ -6,34 +6,116 @@
#include <cassert>
#include <functional>
+#include <map>
#include <string>
#include <utility>
#include <vector>
#include <cm/optional>
#include <cm/string_view>
+#include <cm/type_traits>
#include <cmext/string_view>
#include "cmArgumentParserTypes.h" // IWYU pragma: keep
+template <typename Result>
+class cmArgumentParser; // IWYU pragma: keep
+
+class cmMakefile;
+
namespace ArgumentParser {
-class Instance;
-using Action = std::function<void(Instance&, void*)>;
+class ParseResult
+{
+ std::map<cm::string_view, std::string> KeywordErrors;
-// using ActionMap = cm::flat_map<cm::string_view, Action>;
-class ActionMap : public std::vector<std::pair<cm::string_view, Action>>
+public:
+ explicit operator bool() const { return this->KeywordErrors.empty(); }
+
+ void AddKeywordError(cm::string_view key, cm::string_view text)
+
+ {
+ this->KeywordErrors[key] += text;
+ }
+
+ std::map<cm::string_view, std::string> const& GetKeywordErrors() const
+ {
+ return this->KeywordErrors;
+ }
+
+ bool MaybeReportError(cmMakefile& mf) const;
+};
+
+template <typename Result>
+typename std::enable_if<std::is_base_of<ParseResult, Result>::value,
+ ParseResult*>::type
+AsParseResultPtr(Result& result)
+{
+ return &result;
+}
+
+template <typename Result>
+typename std::enable_if<!std::is_base_of<ParseResult, Result>::value,
+ ParseResult*>::type
+AsParseResultPtr(Result&)
+{
+ return nullptr;
+}
+
+class Instance;
+using KeywordAction = std::function<void(Instance&)>;
+
+// using KeywordActionMap = cm::flat_map<cm::string_view, KeywordAction>;
+class KeywordActionMap
+ : public std::vector<std::pair<cm::string_view, KeywordAction>>
{
public:
- std::pair<iterator, bool> Emplace(cm::string_view name, Action action);
+ std::pair<iterator, bool> Emplace(cm::string_view name,
+ KeywordAction action);
const_iterator Find(cm::string_view name) const;
};
+class ActionMap
+{
+public:
+ KeywordActionMap Keywords;
+};
+
+class Base
+{
+public:
+ using Instance = ArgumentParser::Instance;
+ using ParseResult = ArgumentParser::ParseResult;
+
+ ArgumentParser::ActionMap Bindings;
+
+ bool MaybeBind(cm::string_view name, KeywordAction action)
+ {
+ return this->Bindings.Keywords.Emplace(name, std::move(action)).second;
+ }
+
+ void Bind(cm::string_view name, KeywordAction action)
+ {
+ bool const inserted = this->MaybeBind(name, std::move(action));
+ assert(inserted);
+ static_cast<void>(inserted);
+ }
+};
+
class Instance
{
public:
- Instance(ActionMap const& bindings)
+ Instance(ActionMap const& bindings, ParseResult* parseResult,
+ std::vector<std::string>* unparsedArguments,
+ std::vector<cm::string_view>* keywordsMissingValue,
+ std::vector<cm::string_view>* parsedKeywords,
+ void* result = nullptr)
: Bindings(bindings)
+ , ParseResults(parseResult)
+ , UnparsedArguments(unparsedArguments)
+ , KeywordsMissingValue(keywordsMissingValue)
+ , ParsedKeywords(parsedKeywords)
+ , Result(result)
{
}
@@ -54,22 +136,39 @@
this->Bind(*optVal);
}
- void Consume(cm::string_view arg, void* result,
- std::vector<std::string>* unparsedArguments,
- std::vector<cm::string_view>* keywordsMissingValue,
- std::vector<cm::string_view>* parsedKeywords);
+ template <typename Range>
+ void Parse(Range const& args)
+ {
+ for (cm::string_view arg : args) {
+ this->Consume(arg);
+ }
+ this->FinishKeyword();
+ }
private:
ActionMap const& Bindings;
+ ParseResult* ParseResults = nullptr;
+ std::vector<std::string>* UnparsedArguments = nullptr;
+ std::vector<cm::string_view>* KeywordsMissingValue = nullptr;
+ std::vector<cm::string_view>* ParsedKeywords = nullptr;
+ void* Result = nullptr;
+
+ cm::string_view Keyword;
std::string* CurrentString = nullptr;
std::vector<std::string>* CurrentList = nullptr;
bool ExpectValue = false;
+
+ void Consume(cm::string_view arg);
+ void FinishKeyword();
+
+ template <typename Result>
+ friend class ::cmArgumentParser;
};
} // namespace ArgumentParser
template <typename Result>
-class cmArgumentParser
+class cmArgumentParser : private ArgumentParser::Base
{
public:
// I *think* this function could be made `constexpr` when the code is
@@ -77,28 +176,24 @@
template <typename T>
cmArgumentParser& Bind(cm::static_string_view name, T Result::*member)
{
- bool const inserted =
- this->Bindings
- .Emplace(name,
- [member](ArgumentParser::Instance& instance, void* result) {
- instance.Bind(static_cast<Result*>(result)->*member);
- })
- .second;
- assert(inserted), (void)inserted;
+ this->Base::Bind(name, [member](Instance& instance) {
+ instance.Bind(static_cast<Result*>(instance.Result)->*member);
+ });
return *this;
}
template <typename Range>
- void Parse(Result& result, Range const& args,
+ bool Parse(Result& result, 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) {
- instance.Consume(arg, &result, unparsedArguments, keywordsMissingValue,
- parsedKeywords);
- }
+ using ArgumentParser::AsParseResultPtr;
+ ParseResult* parseResultPtr = AsParseResultPtr(result);
+ Instance instance(this->Bindings, parseResultPtr, unparsedArguments,
+ keywordsMissingValue, parsedKeywords, &result);
+ instance.Parse(args);
+ return parseResultPtr ? static_cast<bool>(*parseResultPtr) : true;
}
template <typename Range>
@@ -111,47 +206,37 @@
parsedKeywords);
return result;
}
-
-private:
- ArgumentParser::ActionMap Bindings;
};
template <>
-class cmArgumentParser<void>
+class cmArgumentParser<void> : private ArgumentParser::Base
{
public:
template <typename T>
cmArgumentParser& Bind(cm::static_string_view name, T& ref)
{
- bool const inserted = this->Bind(cm::string_view(name), ref);
- assert(inserted), (void)inserted;
+ this->Base::Bind(name, [&ref](Instance& instance) { instance.Bind(ref); });
return *this;
}
template <typename Range>
- 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
+ ParseResult 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) {
- instance.Consume(arg, nullptr, unparsedArguments, keywordsMissingValue,
- parsedKeywords);
- }
+ ParseResult parseResult;
+ Instance instance(this->Bindings, &parseResult, unparsedArguments,
+ keywordsMissingValue, parsedKeywords);
+ instance.Parse(args);
+ return parseResult;
}
protected:
template <typename T>
bool Bind(cm::string_view name, T& ref)
{
- return this->Bindings
- .Emplace(name,
- [&ref](ArgumentParser::Instance& instance, void*) {
- instance.Bind(ref);
- })
- .second;
+ return this->MaybeBind(name,
+ [&ref](Instance& instance) { instance.Bind(ref); });
}
-
-private:
- ArgumentParser::ActionMap Bindings;
};
diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
index 033dd6d..58129a0 100644
--- a/Source/cmCMakeHostSystemInformationCommand.cxx
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -474,7 +474,7 @@
}
std::string const& key = *args.begin();
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
std::string ValueName;
bool ValueNames = false;
@@ -491,19 +491,15 @@
.Bind("SEPARATOR"_s, &Arguments::Separator)
.Bind("ERROR_VARIABLE"_s, &Arguments::ErrorVariable);
std::vector<std::string> invalidArgs;
- std::vector<cm::string_view> keywordsMissingValue;
- Arguments const arguments =
- parser.Parse(args.advance(1), &invalidArgs, &keywordsMissingValue);
+ Arguments const arguments = parser.Parse(args.advance(1), &invalidArgs);
if (!invalidArgs.empty()) {
status.SetError(cmStrCat("given invalid argument(s) \"",
cmJoin(invalidArgs, ", "_s), "\"."));
return false;
}
- if (!keywordsMissingValue.empty()) {
- status.SetError(cmStrCat("missing expected value for argument(s) \"",
- cmJoin(keywordsMissingValue, ", "_s), "\"."));
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if ((!arguments.ValueName.empty() &&
(arguments.ValueNames || arguments.SubKeys)) ||
diff --git a/Source/cmCMakePathCommand.cxx b/Source/cmCMakePathCommand.cxx
index adcffa9..b955bcf 100644
--- a/Source/cmCMakePathCommand.cxx
+++ b/Source/cmCMakePathCommand.cxx
@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCMakePathCommand.h"
-#include <algorithm>
#include <functional>
#include <iomanip>
#include <map>
@@ -11,6 +10,7 @@
#include <utility>
#include <vector>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/string_view>
@@ -43,15 +43,12 @@
}
template <int Advance = 2>
- Result Parse(std::vector<std::string> const& args,
- std::vector<cm::string_view>* keywordsMissingValue = nullptr,
- std::vector<cm::string_view>* parsedKeywords = nullptr) const
+ Result Parse(std::vector<std::string> const& args) const
{
this->Inputs.clear();
return this->cmArgumentParser<Result>::Parse(
- cmMakeRange(args).advance(Advance), &this->Inputs, keywordsMissingValue,
- parsedKeywords);
+ cmMakeRange(args).advance(Advance), &this->Inputs);
}
const std::vector<std::string>& GetInputs() const { return this->Inputs; }
@@ -82,52 +79,25 @@
template <int Advance = 2>
Result Parse(std::vector<std::string> const& args) const
{
- this->KeywordsMissingValue.clear();
- this->ParsedKeywords.clear();
-
return this->CMakePathArgumentParser<Result>::template Parse<Advance>(
- args, &this->KeywordsMissingValue, &this->ParsedKeywords);
- }
-
- const std::vector<cm::string_view>& GetKeywordsMissingValue() const
- {
- return this->KeywordsMissingValue;
- }
- const std::vector<cm::string_view>& GetParsedKeywords() const
- {
- return this->ParsedKeywords;
+ args);
}
bool checkOutputVariable(const Result& arguments,
cmExecutionStatus& status) const
{
- if (std::find(this->GetKeywordsMissingValue().begin(),
- this->GetKeywordsMissingValue().end(),
- "OUTPUT_VARIABLE"_s) !=
- this->GetKeywordsMissingValue().end()) {
- status.SetError("OUTPUT_VARIABLE requires an argument.");
- return false;
- }
-
- if (std::find(this->GetParsedKeywords().begin(),
- this->GetParsedKeywords().end(),
- "OUTPUT_VARIABLE"_s) != this->GetParsedKeywords().end() &&
- arguments.Output.empty()) {
+ if (arguments.Output && arguments.Output->empty()) {
status.SetError("Invalid name for output variable.");
return false;
}
return true;
}
-
-private:
- mutable std::vector<cm::string_view> KeywordsMissingValue;
- mutable std::vector<cm::string_view> ParsedKeywords;
};
-struct OutputVariable
+struct OutputVariable : public ArgumentParser::ParseResult
{
- std::string Output;
+ cm::optional<std::string> Output;
};
// Usable when OUTPUT_VARIABLE is the only option
class OutputVariableParser
@@ -297,6 +267,9 @@
const auto arguments = parser.Parse(args);
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
+ }
if (!parser.checkOutputVariable(arguments, status)) {
return false;
}
@@ -307,7 +280,7 @@
}
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
@@ -319,6 +292,9 @@
const auto arguments = parser.Parse(args);
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
+ }
if (!parser.checkOutputVariable(arguments, status)) {
return false;
}
@@ -334,7 +310,7 @@
}
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
@@ -346,6 +322,9 @@
const auto arguments = parser.Parse(args);
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
+ }
if (!parser.checkOutputVariable(arguments, status)) {
return false;
}
@@ -364,7 +343,7 @@
path.RemoveFileName();
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
@@ -376,6 +355,9 @@
const auto arguments = parser.Parse(args);
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
+ }
if (!parser.checkOutputVariable(arguments, status)) {
return false;
}
@@ -395,7 +377,7 @@
parser.GetInputs().empty() ? "" : parser.GetInputs().front());
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
@@ -403,9 +385,9 @@
bool HandleRemoveExtensionCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
- std::string Output;
+ cm::optional<std::string> Output;
bool LastOnly = false;
};
@@ -415,6 +397,9 @@
Arguments const arguments = parser.Parse(args);
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
+ }
if (!parser.checkOutputVariable(arguments, status)) {
return false;
}
@@ -438,7 +423,7 @@
}
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
@@ -446,9 +431,9 @@
bool HandleReplaceExtensionCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
- std::string Output;
+ cm::optional<std::string> Output;
bool LastOnly = false;
};
@@ -458,6 +443,9 @@
Arguments const arguments = parser.Parse(args);
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
+ }
if (!parser.checkOutputVariable(arguments, status)) {
return false;
}
@@ -483,7 +471,7 @@
}
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
@@ -495,6 +483,9 @@
const auto arguments = parser.Parse(args);
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
+ }
if (!parser.checkOutputVariable(arguments, status)) {
return false;
}
@@ -512,7 +503,7 @@
auto path = cmCMakePath(inputPath).Normal();
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
@@ -523,10 +514,10 @@
const std::string& base)>& transform,
bool normalizeOption = false)
{
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
- std::string Output;
- std::string BaseDirectory;
+ cm::optional<std::string> Output;
+ cm::optional<std::string> BaseDirectory;
bool Normalize = false;
};
@@ -538,6 +529,9 @@
Arguments arguments = parser.Parse(args);
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
+ }
if (!parser.checkOutputVariable(arguments, status)) {
return false;
}
@@ -547,17 +541,11 @@
return false;
}
- if (std::find(parser.GetKeywordsMissingValue().begin(),
- parser.GetKeywordsMissingValue().end(), "BASE_DIRECTORY"_s) !=
- parser.GetKeywordsMissingValue().end()) {
- status.SetError("BASE_DIRECTORY requires an argument.");
- return false;
- }
-
- if (std::find(parser.GetParsedKeywords().begin(),
- parser.GetParsedKeywords().end(),
- "BASE_DIRECTORY"_s) == parser.GetParsedKeywords().end()) {
- arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory();
+ std::string baseDirectory;
+ if (arguments.BaseDirectory) {
+ baseDirectory = *arguments.BaseDirectory;
+ } else {
+ baseDirectory = status.GetMakefile().GetCurrentSourceDirectory();
}
std::string inputPath;
@@ -565,13 +553,13 @@
return false;
}
- auto path = transform(cmCMakePath(inputPath), arguments.BaseDirectory);
+ auto path = transform(cmCMakePath(inputPath), baseDirectory);
if (arguments.Normalize) {
path = path.Normal();
}
status.GetMakefile().AddDefinition(
- arguments.Output.empty() ? args[1] : arguments.Output, path.String());
+ arguments.Output ? *arguments.Output : args[1], path.String());
return true;
}
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index af56e2d..7fbd826 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -47,7 +47,7 @@
return false;
}
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
std::vector<std::vector<std::string>> Commands;
std::string OutputVariable;
@@ -95,14 +95,10 @@
.Bind("COMMAND_ERROR_IS_FATAL"_s, &Arguments::CommandErrorIsFatal);
std::vector<std::string> unparsedArguments;
- std::vector<cm::string_view> keywordsMissingValue;
- Arguments const arguments =
- parser.Parse(args, &unparsedArguments, &keywordsMissingValue);
+ Arguments const arguments = parser.Parse(args, &unparsedArguments);
- if (!keywordsMissingValue.empty()) {
- status.SetError(cmStrCat(" called with no value for ",
- keywordsMissingValue.front(), "."));
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (!unparsedArguments.empty()) {
status.SetError(" given unknown argument \"" + unparsedArguments.front() +
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index d2aa63c..c7ba424 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -954,42 +954,34 @@
{
// Evaluate arguments.
std::string file;
- std::string oldRPath;
- std::string newRPath;
+ cm::optional<std::string> oldRPath;
+ cm::optional<std::string> newRPath;
bool removeEnvironmentRPath = false;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- 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)
.Bind("INSTALL_REMOVE_ENVIRONMENT_RPATH"_s, removeEnvironmentRPath);
- parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs,
- &parsedArgs);
+ ArgumentParser::ParseResult parseResult =
+ parser.Parse(cmMakeRange(args).advance(1), &unknownArgs);
if (!unknownArgs.empty()) {
status.SetError(
cmStrCat("RPATH_CHANGE given unknown argument ", unknownArgs.front()));
return false;
}
- if (!missingArgs.empty()) {
- status.SetError(cmStrCat("RPATH_CHANGE \"", missingArgs.front(),
- "\" argument not given value."));
- return false;
+ if (parseResult.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (file.empty()) {
status.SetError("RPATH_CHANGE not given FILE option.");
return false;
}
- if (oldRPath.empty() &&
- std::find(parsedArgs.begin(), parsedArgs.end(), "OLD_RPATH") ==
- parsedArgs.end()) {
+ if (!oldRPath) {
status.SetError("RPATH_CHANGE not given OLD_RPATH option.");
return false;
}
- if (newRPath.empty() &&
- std::find(parsedArgs.begin(), parsedArgs.end(), "NEW_RPATH") ==
- parsedArgs.end()) {
+ if (!newRPath) {
status.SetError("RPATH_CHANGE not given NEW_RPATH option.");
return false;
}
@@ -1003,17 +995,17 @@
std::string emsg;
bool changed;
- if (!cmSystemTools::ChangeRPath(file, oldRPath, newRPath,
+ if (!cmSystemTools::ChangeRPath(file, *oldRPath, *newRPath,
removeEnvironmentRPath, &emsg, &changed)) {
status.SetError(cmStrCat("RPATH_CHANGE could not write new RPATH:\n ",
- newRPath, "\nto the file:\n ", file, "\n",
+ *newRPath, "\nto the file:\n ", file, "\n",
emsg));
success = false;
}
if (success) {
if (changed) {
std::string message =
- cmStrCat("Set runtime path of \"", file, "\" to \"", newRPath, '"');
+ cmStrCat("Set runtime path of \"", file, "\" to \"", *newRPath, '"');
status.GetMakefile().DisplayStatus(message, -1);
}
ft.Store(file);
@@ -1026,31 +1018,25 @@
{
// Evaluate arguments.
std::string file;
- std::string newRPath;
+ cm::optional<std::string> newRPath;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- 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);
+ ArgumentParser::ParseResult parseResult =
+ parser.Parse(cmMakeRange(args).advance(1), &unknownArgs);
if (!unknownArgs.empty()) {
status.SetError(cmStrCat("RPATH_SET given unrecognized argument \"",
unknownArgs.front(), "\"."));
return false;
}
- if (!missingArgs.empty()) {
- status.SetError(cmStrCat("RPATH_SET \"", missingArgs.front(),
- "\" argument not given value."));
- return false;
+ if (parseResult.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (file.empty()) {
status.SetError("RPATH_SET not given FILE option.");
return false;
}
- if (newRPath.empty() &&
- std::find(parsedArgs.begin(), parsedArgs.end(), "NEW_RPATH") ==
- parsedArgs.end()) {
+ if (!newRPath) {
status.SetError("RPATH_SET not given NEW_RPATH option.");
return false;
}
@@ -1064,16 +1050,16 @@
std::string emsg;
bool changed;
- if (!cmSystemTools::SetRPath(file, newRPath, &emsg, &changed)) {
+ if (!cmSystemTools::SetRPath(file, *newRPath, &emsg, &changed)) {
status.SetError(cmStrCat("RPATH_SET could not write new RPATH:\n ",
- newRPath, "\nto the file:\n ", file, "\n",
+ *newRPath, "\nto the file:\n ", file, "\n",
emsg));
success = false;
}
if (success) {
if (changed) {
std::string message =
- cmStrCat("Set runtime path of \"", file, "\" to \"", newRPath, '"');
+ cmStrCat("Set runtime path of \"", file, "\" to \"", *newRPath, '"');
status.GetMakefile().DisplayStatus(message, -1);
}
ft.Store(file);
@@ -1088,18 +1074,16 @@
std::string file;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- std::vector<cm::string_view> missingArgs;
parser.Bind("FILE"_s, file);
- parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs);
+ ArgumentParser::ParseResult parseResult =
+ parser.Parse(cmMakeRange(args).advance(1), &unknownArgs);
if (!unknownArgs.empty()) {
status.SetError(
cmStrCat("RPATH_REMOVE given unknown argument ", unknownArgs.front()));
return false;
}
- if (!missingArgs.empty()) {
- status.SetError(cmStrCat("RPATH_REMOVE \"", missingArgs.front(),
- "\" argument not given value."));
- return false;
+ if (parseResult.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (file.empty()) {
status.SetError("RPATH_REMOVE not given FILE option.");
@@ -1136,31 +1120,25 @@
{
// Evaluate arguments.
std::string file;
- std::string rpath;
+ cm::optional<std::string> rpath;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- 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);
+ ArgumentParser::ParseResult parseResult =
+ parser.Parse(cmMakeRange(args).advance(1), &unknownArgs);
if (!unknownArgs.empty()) {
status.SetError(
cmStrCat("RPATH_CHECK given unknown argument ", unknownArgs.front()));
return false;
}
- if (!missingArgs.empty()) {
- status.SetError(cmStrCat("RPATH_CHECK \"", missingArgs.front(),
- "\" argument not given value."));
- return false;
+ if (parseResult.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (file.empty()) {
status.SetError("RPATH_CHECK not given FILE option.");
return false;
}
- if (rpath.empty() &&
- std::find(parsedArgs.begin(), parsedArgs.end(), "RPATH") ==
- parsedArgs.end()) {
+ if (!rpath) {
status.SetError("RPATH_CHECK not given RPATH option.");
return false;
}
@@ -1169,7 +1147,7 @@
// delete it. This is used during installation to re-install a file
// if its RPath will change.
if (cmSystemTools::FileExists(file, true) &&
- !cmSystemTools::CheckRPath(file, rpath)) {
+ !cmSystemTools::CheckRPath(file, *rpath)) {
cmSystemTools::RemoveFile(file);
}
@@ -1252,7 +1230,7 @@
return false;
}
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
cm::optional<std::string> BaseDirectory;
bool ExpandTilde = false;
@@ -1263,17 +1241,15 @@
.Bind("EXPAND_TILDE"_s, &Arguments::ExpandTilde);
std::vector<std::string> unparsedArguments;
- std::vector<cm::string_view> keywordsMissingValue;
- auto arguments = parser.Parse(cmMakeRange(args).advance(3),
- &unparsedArguments, &keywordsMissingValue);
+ auto arguments =
+ parser.Parse(cmMakeRange(args).advance(3), &unparsedArguments);
if (!unparsedArguments.empty()) {
status.SetError("REAL_PATH called with unexpected arguments");
return false;
}
- if (!keywordsMissingValue.empty()) {
- status.SetError("BASE_DIRECTORY requires a value");
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (!arguments.BaseDirectory) {
@@ -2495,7 +2471,7 @@
return false;
}
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
cm::optional<std::string> Output;
cm::optional<std::string> Input;
@@ -2521,17 +2497,13 @@
.Bind("NEWLINE_STYLE"_s, &Arguments::NewLineStyle);
std::vector<std::string> unparsedArguments;
- std::vector<cm::string_view> keywordsMissingValues;
std::vector<cm::string_view> parsedKeywords;
Arguments const arguments =
parser.Parse(cmMakeRange(args).advance(1), &unparsedArguments,
- &keywordsMissingValues, &parsedKeywords);
+ /*keywordsMissingValue=*/nullptr, &parsedKeywords);
- if (!keywordsMissingValues.empty()) {
- status.SetError(
- cmStrCat("GENERATE keywords missing values:\n ",
- cmJoin(cmMakeRange(keywordsMissingValues), "\n ")));
- return false;
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
}
if (!unparsedArguments.empty()) {
@@ -3045,7 +3017,7 @@
"\n ]])");
}
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
std::string ResolvedDependenciesVar;
std::string UnresolvedDependenciesVar;
@@ -3088,10 +3060,8 @@
.Bind("POST_EXCLUDE_FILES_STRICT"_s, &Arguments::PostExcludeFilesStrict);
std::vector<std::string> unrecognizedArguments;
- std::vector<cm::string_view> keywordsMissingValues;
auto parsedArgs =
- parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
- &keywordsMissingValues);
+ parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments);
auto argIt = unrecognizedArguments.begin();
if (argIt != unrecognizedArguments.end()) {
status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\""));
@@ -3099,12 +3069,9 @@
return false;
}
- if (!keywordsMissingValues.empty()) {
- status.SetError(
- cmStrCat("Keywords missing values:\n ",
- cmJoin(cmMakeRange(keywordsMissingValues), "\n ")));
+ if (parsedArgs.MaybeReportError(status.GetMakefile())) {
cmSystemTools::SetFatalErrorOccurred();
- return false;
+ return true;
}
cmRuntimeDependencyArchive archive(
@@ -3204,7 +3171,7 @@
bool HandleConfigureCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
cm::optional<std::string> Output;
cm::optional<std::string> Content;
@@ -3223,10 +3190,8 @@
.Bind("NEWLINE_STYLE"_s, &Arguments::NewlineStyle);
std::vector<std::string> unrecognizedArguments;
- std::vector<cm::string_view> keywordsMissingValues;
auto parsedArgs =
- parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
- &keywordsMissingValues);
+ parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments);
auto argIt = unrecognizedArguments.begin();
if (argIt != unrecognizedArguments.end()) {
@@ -3236,12 +3201,9 @@
return false;
}
- if (!keywordsMissingValues.empty()) {
- status.SetError(
- cmStrCat("CONFIGURE keywords missing values:\n ",
- cmJoin(cmMakeRange(keywordsMissingValues), "\n ")));
+ if (parsedArgs.MaybeReportError(status.GetMakefile())) {
cmSystemTools::SetFatalErrorOccurred();
- return false;
+ return true;
}
if (!parsedArgs.Output) {
@@ -3336,7 +3298,7 @@
bool HandleArchiveCreateCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
std::string Output;
std::string Format;
@@ -3362,10 +3324,8 @@
.Bind("PATHS"_s, &Arguments::Paths);
std::vector<std::string> unrecognizedArguments;
- std::vector<cm::string_view> keywordsMissingValues;
auto parsedArgs =
- parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
- &keywordsMissingValues);
+ parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments);
auto argIt = unrecognizedArguments.begin();
if (argIt != unrecognizedArguments.end()) {
status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\""));
@@ -3373,12 +3333,9 @@
return false;
}
- if (!keywordsMissingValues.empty()) {
- status.SetError(
- cmStrCat("Keywords missing values:\n ",
- cmJoin(cmMakeRange(keywordsMissingValues), "\n ")));
+ if (parsedArgs.MaybeReportError(status.GetMakefile())) {
cmSystemTools::SetFatalErrorOccurred();
- return false;
+ return true;
}
const char* knownFormats[] = {
@@ -3467,7 +3424,7 @@
bool HandleArchiveExtractCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
std::string Input;
bool Verbose = false;
@@ -3486,10 +3443,8 @@
.Bind("TOUCH"_s, &Arguments::Touch);
std::vector<std::string> unrecognizedArguments;
- std::vector<cm::string_view> keywordsMissingValues;
auto parsedArgs =
- parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
- &keywordsMissingValues);
+ parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments);
auto argIt = unrecognizedArguments.begin();
if (argIt != unrecognizedArguments.end()) {
status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\""));
@@ -3497,12 +3452,9 @@
return false;
}
- if (!keywordsMissingValues.empty()) {
- status.SetError(
- cmStrCat("Keywords missing values:\n ",
- cmJoin(cmMakeRange(keywordsMissingValues), "\n ")));
+ if (parsedArgs.MaybeReportError(status.GetMakefile())) {
cmSystemTools::SetFatalErrorOccurred();
- return false;
+ return true;
}
std::string inFile = parsedArgs.Input;
@@ -3557,10 +3509,15 @@
return true;
}
-bool ValidateAndConvertPermissions(const std::vector<std::string>& permissions,
- mode_t& perms, cmExecutionStatus& status)
+bool ValidateAndConvertPermissions(
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> const&
+ permissions,
+ mode_t& perms, cmExecutionStatus& status)
{
- for (const auto& i : permissions) {
+ if (!permissions) {
+ return true;
+ }
+ for (const auto& i : *permissions) {
if (!cmFSPermissions::stringToModeT(i, perms)) {
status.SetError(i + " is an invalid permission specifier");
cmSystemTools::SetFatalErrorOccurred();
@@ -3592,11 +3549,14 @@
globber.SetRecurse(recurse);
globber.SetRecurseListDirs(recurse);
- struct Arguments
+ struct Arguments : public ArgumentParser::ParseResult
{
- ArgumentParser::NonEmpty<std::vector<std::string>> Permissions;
- ArgumentParser::NonEmpty<std::vector<std::string>> FilePermissions;
- ArgumentParser::NonEmpty<std::vector<std::string>> DirectoryPermissions;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>>
+ Permissions;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>>
+ FilePermissions;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>>
+ DirectoryPermissions;
};
static auto const parser =
@@ -3606,21 +3566,20 @@
.Bind("DIRECTORY_PERMISSIONS"_s, &Arguments::DirectoryPermissions);
std::vector<std::string> pathEntries;
- std::vector<cm::string_view> keywordsMissingValues;
- Arguments parsedArgs = parser.Parse(cmMakeRange(args).advance(1),
- &pathEntries, &keywordsMissingValues);
+ Arguments parsedArgs =
+ parser.Parse(cmMakeRange(args).advance(1), &pathEntries);
// check validity of arguments
- if (parsedArgs.Permissions.empty() && parsedArgs.FilePermissions.empty() &&
- parsedArgs.DirectoryPermissions.empty()) // no permissions given
+ if (!parsedArgs.Permissions && !parsedArgs.FilePermissions &&
+ !parsedArgs.DirectoryPermissions) // no permissions given
{
status.SetError("No permissions given");
cmSystemTools::SetFatalErrorOccurred();
return false;
}
- if (!parsedArgs.Permissions.empty() && !parsedArgs.FilePermissions.empty() &&
- !parsedArgs.DirectoryPermissions.empty()) // all keywords are used
+ if (parsedArgs.Permissions && parsedArgs.FilePermissions &&
+ parsedArgs.DirectoryPermissions) // all keywords are used
{
status.SetError("Remove either PERMISSIONS or FILE_PERMISSIONS or "
"DIRECTORY_PERMISSIONS from the invocation");
@@ -3628,12 +3587,9 @@
return false;
}
- if (!keywordsMissingValues.empty()) {
- for (const auto& i : keywordsMissingValues) {
- status.SetError(cmStrCat(i, " is not given any arguments"));
- cmSystemTools::SetFatalErrorOccurred();
- }
- return false;
+ if (parsedArgs.MaybeReportError(status.GetMakefile())) {
+ cmSystemTools::SetFatalErrorOccurred();
+ return true;
}
// validate permissions
@@ -3677,7 +3633,7 @@
if (cmSystemTools::FileExists(i, true)) {
bool success = true;
const mode_t& filePermissions =
- parsedArgs.FilePermissions.empty() ? perms : fperms;
+ parsedArgs.FilePermissions ? fperms : perms;
if (filePermissions) {
success = SetPermissions(i, filePermissions, status);
}
@@ -3689,7 +3645,7 @@
else if (cmSystemTools::FileIsDirectory(i)) {
bool success = true;
const mode_t& directoryPermissions =
- parsedArgs.DirectoryPermissions.empty() ? perms : dperms;
+ parsedArgs.DirectoryPermissions ? dperms : perms;
if (directoryPermissions) {
success = SetPermissions(i, directoryPermissions, status);
}
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index b1044a8..82adca8 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -2160,11 +2160,9 @@
// These generic args also contain the runtime dependency set
std::string runtimeDependencySetArg;
std::vector<std::string> runtimeDependencyArgVector;
- std::vector<cm::string_view> parsedArgs;
cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
- genericArgs.Parse(genericArgVector, &runtimeDependencyArgVector, nullptr,
- &parsedArgs);
+ genericArgs.Parse(genericArgVector, &runtimeDependencyArgVector);
bool success = genericArgs.Finalize();
cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 1514a8a..40f3ab5 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -909,7 +909,6 @@
// The reason is that their file names might be discovered from source files
// at generation time.
if (this->MocOrUicEnabled()) {
- std::unordered_set<std::string> addedFiles;
for (const auto& sf : this->Makefile->GetSourceFiles()) {
// sf->GetExtension() is only valid after sf->ResolveFullPath() ...
// Since we're iterating over source files that might be not in the
@@ -951,28 +950,25 @@
cmExpandedList(uicOpts));
}
- auto uiHeaderFileName = cmStrCat(
- "ui_"_s, cmSystemTools::GetFilenameWithoutLastExtension(fullPath),
- ".h"_s);
+ auto uiHeaderRelativePath = cmSystemTools::RelativePath(
+ this->LocalGen->GetCurrentSourceDirectory(),
+ cmSystemTools::GetFilenamePath(fullPath));
- // .ui files with the same base name will conflict. Yield an error.
- {
- auto insertResult = addedFiles.insert(uiHeaderFileName);
- if (!insertResult.second) {
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("More than one .ui file with the name "_s,
- cmSystemTools::GetFilenameName(fullPath),
- " was found in the sources for target "_s,
- this->GenTarget->GetName(), "."));
- }
+ // Avoid creating a path containing adjacent slashes
+ if (!uiHeaderRelativePath.empty() &&
+ uiHeaderRelativePath.back() != '/') {
+ uiHeaderRelativePath += '/';
}
+ auto uiHeaderFilePath = cmStrCat(
+ '/', uiHeaderRelativePath, "ui_"_s,
+ cmSystemTools::GetFilenameWithoutLastExtension(fullPath), ".h"_s);
+
ConfigString uiHeader;
std::string uiHeaderGenex;
this->ConfigFileNamesAndGenex(
uiHeader, uiHeaderGenex, cmStrCat(this->Dir.Build, "/include"_s),
- cmStrCat("/"_s, uiHeaderFileName));
+ uiHeaderFilePath);
this->Uic.UiHeaders.emplace_back(
std::make_pair(uiHeader, uiHeaderGenex));
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
index d520c14..f239576 100644
--- a/Source/kwsys/Directory.cxx
+++ b/Source/kwsys/Directory.cxx
@@ -43,12 +43,12 @@
{
std::string Name;
#if defined(_WIN32) && !defined(__CYGWIN__)
- _wfinddata_t FindData;
+ WIN32_FIND_DATAW FindData;
#endif
FileData(std::string name
#if defined(_WIN32) && !defined(__CYGWIN__)
,
- _wfinddata_t data
+ WIN32_FIND_DATAW data
#endif
)
: Name(std::move(name))
@@ -115,8 +115,8 @@
bool Directory::FileIsDirectory(std::size_t i) const
{
#if defined(_WIN32) && !defined(__CYGWIN__)
- _wfinddata_t const& data = this->Internal->Files[i].FindData;
- return (data.attrib & FILE_ATTRIBUTE_DIRECTORY) != 0;
+ auto const& data = this->Internal->Files[i].FindData;
+ return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
#else
std::string const& path = this->GetFilePath(i);
return kwsys::SystemTools::FileIsDirectory(path);
@@ -127,9 +127,9 @@
{
std::string const& path = this->GetFilePath(i);
#if defined(_WIN32) && !defined(__CYGWIN__)
- _wfinddata_t const& data = this->Internal->Files[i].FindData;
+ auto const& data = this->Internal->Files[i].FindData;
return kwsys::SystemTools::FileIsSymlinkWithAttr(
- Encoding::ToWindowsExtendedPath(path), data.attrib);
+ Encoding::ToWindowsExtendedPath(path), data.dwFileAttributes);
#else
return kwsys::SystemTools::FileIsSymlink(path);
#endif
@@ -157,7 +157,7 @@
Status Directory::Load(std::string const& name, std::string* errorMessage)
{
this->Clear();
- intptr_t srchHandle;
+ HANDLE srchHandle;
char* buf;
size_t bufLength;
size_t n = name.size();
@@ -176,14 +176,14 @@
snprintf(buf, bufLength, "%s/*", name.c_str());
}
}
- struct _wfinddata_t data; // data of current file
+ WIN32_FIND_DATAW data; // data of current file
// Now put them into the file array
srchHandle =
- _wfindfirst((wchar_t*)Encoding::ToWindowsExtendedPath(buf).c_str(), &data);
+ FindFirstFileW(Encoding::ToWindowsExtendedPath(buf).c_str(), &data);
delete[] buf;
- if (srchHandle == -1) {
+ if (srchHandle == INVALID_HANDLE_VALUE) {
Status status = Status::POSIX_errno();
if (errorMessage) {
*errorMessage = status.GetString();
@@ -193,10 +193,11 @@
// Loop through names
do {
- this->Internal->Files.emplace_back(Encoding::ToNarrow(data.name), data);
- } while (_wfindnext(srchHandle, &data) != -1);
+ this->Internal->Files.emplace_back(Encoding::ToNarrow(data.cFileName),
+ data);
+ } while (FindNextFileW(srchHandle, &data));
this->Internal->Path = name;
- if (_findclose(srchHandle) == -1) {
+ if (!FindClose(srchHandle)) {
Status status = Status::POSIX_errno();
if (errorMessage) {
*errorMessage = status.GetString();
@@ -209,7 +210,7 @@
unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
std::string* errorMessage)
{
- intptr_t srchHandle;
+ HANDLE srchHandle;
char* buf;
size_t bufLength;
size_t n = name.size();
@@ -222,13 +223,13 @@
buf = new char[n + 2 + 1];
snprintf(buf, bufLength, "%s/*", name.c_str());
}
- struct _wfinddata_t data; // data of current file
+ WIN32_FIND_DATAW data; // data of current file
// Now put them into the file array
- srchHandle = _wfindfirst((wchar_t*)Encoding::ToWide(buf).c_str(), &data);
+ srchHandle = FindFirstFileW(Encoding::ToWide(buf).c_str(), &data);
delete[] buf;
- if (srchHandle == -1) {
+ if (srchHandle == INVALID_HANDLE_VALUE) {
if (errorMessage) {
if (unsigned int errorId = GetLastError()) {
LPSTR message = nullptr;
@@ -250,8 +251,8 @@
unsigned long count = 0;
do {
count++;
- } while (_wfindnext(srchHandle, &data) != -1);
- _findclose(srchHandle);
+ } while (FindNextFileW(srchHandle, &data));
+ FindClose(srchHandle);
return count;
}
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 89a3cc7..a20901c 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -536,9 +536,11 @@
StringMap TranslationMap;
#endif
#ifdef _WIN32
- static std::string GetCasePathName(std::string const& pathIn);
+ static std::string GetCasePathName(std::string const& pathIn,
+ bool const cache);
static std::string GetActualCaseForPathCached(std::string const& path);
static const char* GetEnvBuffered(const char* key);
+ std::map<std::string, std::string, SystemToolsPathCaseCmp> FindFileMap;
std::map<std::string, std::string, SystemToolsPathCaseCmp> PathCaseMap;
std::map<std::string, std::string> EnvMap;
#endif
@@ -571,7 +573,8 @@
static SystemToolsStatic* SystemToolsStatics;
#ifdef _WIN32
-std::string SystemToolsStatic::GetCasePathName(std::string const& pathIn)
+std::string SystemToolsStatic::GetCasePathName(std::string const& pathIn,
+ bool const cache)
{
std::string casePath;
@@ -623,14 +626,31 @@
} else {
std::string test_str = casePath;
test_str += path_components[idx];
- WIN32_FIND_DATAW findData;
- HANDLE hFind =
- ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), &findData);
- if (INVALID_HANDLE_VALUE != hFind) {
- path_components[idx] = Encoding::ToNarrow(findData.cFileName);
- ::FindClose(hFind);
- } else {
- converting = false;
+
+ bool found_in_cache = false;
+ if (cache) {
+ auto const it = SystemToolsStatics->FindFileMap.find(test_str);
+ if (it != SystemToolsStatics->FindFileMap.end()) {
+ path_components[idx] = it->second;
+ found_in_cache = true;
+ }
+ }
+
+ if (!found_in_cache) {
+ WIN32_FIND_DATAW findData;
+ HANDLE hFind =
+ ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), &findData);
+ if (INVALID_HANDLE_VALUE != hFind) {
+ auto case_file_name = Encoding::ToNarrow(findData.cFileName);
+ if (cache) {
+ SystemToolsStatics->FindFileMap.emplace(test_str,
+ case_file_name);
+ }
+ path_components[idx] = std::move(case_file_name);
+ ::FindClose(hFind);
+ } else {
+ converting = false;
+ }
}
}
}
@@ -642,19 +662,16 @@
std::string SystemToolsStatic::GetActualCaseForPathCached(std::string const& p)
{
- // Check to see if actual case has already been called
- // for this path, and the result is stored in the PathCaseMap
- auto& pcm = SystemToolsStatics->PathCaseMap;
- {
- auto itr = pcm.find(p);
- if (itr != pcm.end()) {
- return itr->second;
- }
+ std::string casePath;
+
+ auto it = SystemToolsStatics->PathCaseMap.find(p);
+ if (it != SystemToolsStatics->PathCaseMap.end()) {
+ casePath = it->second;
+ } else {
+ casePath = SystemToolsStatic::GetCasePathName(p, true);
+ SystemToolsStatics->PathCaseMap.emplace(p, casePath);
}
- std::string casePath = SystemToolsStatic::GetCasePathName(p);
- if (casePath.size() <= MAX_PATH) {
- pcm[p] = casePath;
- }
+
return casePath;
}
#endif
@@ -3677,7 +3694,7 @@
std::string SystemTools::GetActualCaseForPath(const std::string& p)
{
#ifdef _WIN32
- return SystemToolsStatic::GetCasePathName(p);
+ return SystemToolsStatic::GetCasePathName(p, false);
#else
return p;
#endif
diff --git a/Tests/CMakeLib/testArgumentParser.cxx b/Tests/CMakeLib/testArgumentParser.cxx
index ecfc5fc..f0ace50 100644
--- a/Tests/CMakeLib/testArgumentParser.cxx
+++ b/Tests/CMakeLib/testArgumentParser.cxx
@@ -3,7 +3,9 @@
#include <initializer_list>
#include <iostream>
+#include <map>
#include <string>
+#include <utility>
#include <vector>
#include <cm/optional>
@@ -15,7 +17,7 @@
namespace {
-struct Result
+struct Result : public ArgumentParser::ParseResult
{
bool Option1 = false;
bool Option2 = false;
@@ -69,6 +71,11 @@
static std::vector<cm::string_view> const missing = { "STRING_1"_s,
"LIST_1"_s,
"LIST_4"_s };
+ static std::map<cm::string_view, std::string> const keywordErrors = {
+ { "STRING_1"_s, " missing required value\n" },
+ { "LIST_1"_s, " missing required value\n" },
+ { "LIST_4"_s, " missing required value\n" }
+ };
#define ASSERT_TRUE(x) \
do { \
@@ -78,6 +85,8 @@
} \
} while (false)
+ ASSERT_TRUE(!result);
+
ASSERT_TRUE(result.Option1);
ASSERT_TRUE(!result.Option2);
@@ -110,6 +119,13 @@
ASSERT_TRUE(unparsedArguments[0] == "bar");
ASSERT_TRUE(keywordsMissingValue == missing);
+ ASSERT_TRUE(result.GetKeywordErrors().size() == keywordErrors.size());
+ for (auto const& ke : result.GetKeywordErrors()) {
+ auto const ki = keywordErrors.find(ke.first);
+ ASSERT_TRUE(ki != keywordErrors.end());
+ ASSERT_TRUE(ke.second == ki->second);
+ }
+
return true;
}
@@ -119,54 +135,65 @@
std::vector<std::string> unparsedArguments;
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("STRING_4"_s, result.String4)
- .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("LIST_6"_s, result.List6)
- .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);
+ static_cast<ArgumentParser::ParseResult&>(result) =
+ 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("STRING_4"_s, result.String4)
+ .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("LIST_6"_s, result.List6)
+ .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);
}
+static auto const parserStatic = //
+ cmArgumentParser<Result>{}
+ .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("STRING_4"_s, &Result::String4)
+ .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("LIST_6"_s, &Result::List6)
+ .Bind("MULTI_1"_s, &Result::Multi1)
+ .Bind("MULTI_2"_s, &Result::Multi2)
+ .Bind("MULTI_3"_s, &Result::Multi3)
+ .Bind("MULTI_4"_s, &Result::Multi4)
+ /* keep semicolon on own line */;
+
bool testArgumentParserStatic()
{
- static auto const parser = //
- cmArgumentParser<Result>{}
- .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("STRING_4"_s, &Result::String4)
- .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("LIST_6"_s, &Result::List6)
- .Bind("MULTI_1"_s, &Result::Multi1)
- .Bind("MULTI_2"_s, &Result::Multi2)
- .Bind("MULTI_3"_s, &Result::Multi3)
- .Bind("MULTI_4"_s, &Result::Multi4);
-
std::vector<std::string> unparsedArguments;
std::vector<cm::string_view> keywordsMissingValue;
Result const result =
- parser.Parse(args, &unparsedArguments, &keywordsMissingValue);
+ parserStatic.Parse(args, &unparsedArguments, &keywordsMissingValue);
+ return verifyResult(result, unparsedArguments, keywordsMissingValue);
+}
+bool testArgumentParserStaticBool()
+{
+ std::vector<std::string> unparsedArguments;
+ std::vector<cm::string_view> keywordsMissingValue;
+ Result result;
+ ASSERT_TRUE(parserStatic.Parse(result, args, &unparsedArguments,
+ &keywordsMissingValue) == false);
return verifyResult(result, unparsedArguments, keywordsMissingValue);
}
@@ -184,5 +211,10 @@
return -1;
}
+ if (!testArgumentParserStaticBool()) {
+ std::cout << "While executing testArgumentParserStaticBool().\n";
+ return -1;
+ }
+
return 0;
}
diff --git a/Tests/RunCMake/File_Archive/create-missing-args-stderr.txt b/Tests/RunCMake/File_Archive/create-missing-args-stderr.txt
index ecfe401..fd026f9 100644
--- a/Tests/RunCMake/File_Archive/create-missing-args-stderr.txt
+++ b/Tests/RunCMake/File_Archive/create-missing-args-stderr.txt
@@ -1,9 +1,19 @@
^CMake Error at create-missing-args.cmake:[0-9]+ \(file\):
- file Keywords missing values:
+ Error after keyword "COMPRESSION":
- OUTPUT
- FORMAT
- COMPRESSION
- COMPRESSION_LEVEL
+ missing required value
+
+ Error after keyword "COMPRESSION_LEVEL":
+
+ missing required value
+
+ Error after keyword "FORMAT":
+
+ missing required value
+
+ Error after keyword "OUTPUT":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/File_Archive/extract-missing-args-stderr.txt b/Tests/RunCMake/File_Archive/extract-missing-args-stderr.txt
index 96c779f..0c93ece 100644
--- a/Tests/RunCMake/File_Archive/extract-missing-args-stderr.txt
+++ b/Tests/RunCMake/File_Archive/extract-missing-args-stderr.txt
@@ -1,7 +1,11 @@
^CMake Error at extract-missing-args.cmake:[0-9]+ \(file\):
- file Keywords missing values:
+ Error after keyword "DESTINATION":
- INPUT
- DESTINATION
+ missing required value
+
+ Error after keyword "INPUT":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt b/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt
index dd6a2e7..72292f9 100644
--- a/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt
+++ b/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt
@@ -1,6 +1,7 @@
CMake Error at BadArgContent.cmake:[0-9]+ \(file\):
- file CONFIGURE keywords missing values:
+ Error after keyword "CONTENT":
- CONTENT
+ missing required value
+
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 e1bf7b4..d793f48 100644
--- a/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt
+++ b/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt
@@ -1,6 +1,7 @@
CMake Error at BadArgOutput.cmake:[0-9]+ \(file\):
- file CONFIGURE keywords missing values:
+ Error after keyword "OUTPUT":
- OUTPUT
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt b/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt
index 4278bce..708e6be 100644
--- a/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt
+++ b/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt
@@ -1,6 +1,7 @@
CMake Error at EmptyCondition1.cmake:2 \(file\):
- file GENERATE keywords missing values:
+ Error after keyword "CONDITION":
- CONDITION
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt
index 4059bf8..b1b7f80 100644
--- a/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt
+++ b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt
@@ -1,6 +1,7 @@
CMake Error at NewLineStyle-NoArg.cmake:[0-9]+ \(file\):
- file GENERATE keywords missing values:
+ Error after keyword "NEWLINE_STYLE":
- NEWLINE_STYLE
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt
index 6a430f1..ea1566d 100644
--- a/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt
+++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt
@@ -1,5 +1,7 @@
CMake Error at Registry_BadQuery2.cmake:[0-9]+ \(cmake_host_system_information\):
- cmake_host_system_information missing expected value for argument\(s\)
- "VALUE".
+ Error after keyword "VALUE":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt
index 5eda4ff..f8c96d8 100644
--- a/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt
+++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt
@@ -1,5 +1,7 @@
CMake Error at Registry_BadView1.cmake:[0-9]+ \(cmake_host_system_information\):
- cmake_host_system_information missing expected value for argument\(s\)
- "VIEW".
+ Error after keyword "VIEW":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/cmake_path/BASE_DIRECTORY-no-arg-stderr.txt b/Tests/RunCMake/cmake_path/BASE_DIRECTORY-no-arg-stderr.txt
new file mode 100644
index 0000000..ad7d134
--- /dev/null
+++ b/Tests/RunCMake/cmake_path/BASE_DIRECTORY-no-arg-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at .+/cmake_path/call-cmake_path.cmake:[0-9]+ \(cmake_path\):
+ Error after keyword "BASE_DIRECTORY":
+
+ missing required value
diff --git a/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-no-arg-stderr.txt b/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-no-arg-stderr.txt
index e1d6592..63289ef 100644
--- a/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-no-arg-stderr.txt
+++ b/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-no-arg-stderr.txt
@@ -1,2 +1,4 @@
CMake Error at .+/cmake_path/call-cmake_path.cmake:[0-9]+ \(cmake_path\):
- cmake_path OUTPUT_VARIABLE requires an argument.
+ Error after keyword "OUTPUT_VARIABLE":
+
+ missing required value
diff --git a/Tests/RunCMake/cmake_path/RunCMakeTest.cmake b/Tests/RunCMake/cmake_path/RunCMakeTest.cmake
index 991f46b..8a2dd95 100644
--- a/Tests/RunCMake/cmake_path/RunCMakeTest.cmake
+++ b/Tests/RunCMake/cmake_path/RunCMakeTest.cmake
@@ -74,6 +74,14 @@
endforeach()
+## BASE_DIRECTORY without argument
+set (RunCMake-stderr-file "BASE_DIRECTORY-no-arg-stderr.txt")
+
+foreach (command IN ITEMS RELATIVE_PATH ABSOLUTE_PATH)
+ run_cmake_command (${command}-OUTPUT_VARIABLE-no-arg "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=${command} path BASE_DIRECTORY" -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake")
+endforeach()
+
+
## Invalid output variable
set (RunCMake-stderr-file "invalid-output-var-stderr.txt")
diff --git a/Tests/RunCMake/execute_process/EchoCommand3-stderr.txt b/Tests/RunCMake/execute_process/EchoCommand3-stderr.txt
index e27f1e6..62cad52 100644
--- a/Tests/RunCMake/execute_process/EchoCommand3-stderr.txt
+++ b/Tests/RunCMake/execute_process/EchoCommand3-stderr.txt
@@ -1,2 +1,4 @@
CMake Error at .*EchoCommand.cmake:.*\(execute_process\):
- execute_process called with no value for COMMAND_ECHO.
+ Error after keyword "COMMAND_ECHO":
+
+ missing required value
diff --git a/Tests/RunCMake/execute_process/EncodingMissing-stderr.txt b/Tests/RunCMake/execute_process/EncodingMissing-stderr.txt
index 1a69579..7f85654 100644
--- a/Tests/RunCMake/execute_process/EncodingMissing-stderr.txt
+++ b/Tests/RunCMake/execute_process/EncodingMissing-stderr.txt
@@ -1,4 +1,7 @@
^CMake Error at EncodingMissing.cmake:[0-9]+ \(execute_process\):
- execute_process called with no value for ENCODING.
+ Error after keyword "ENCODING":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-stderr.txt
deleted file mode 100644
index b22387b..0000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-stderr.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-CMake Error at CHMOD-all-perms\.cmake:[0-9]+ \(file\):
- file Remove either PERMISSIONS or FILE_PERMISSIONS or DIRECTORY_PERMISSIONS
- from the invocation
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-all-perms.cmake
deleted file mode 100644
index b49583d..0000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms.cmake
+++ /dev/null
@@ -1,6 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a)
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS OWNER_READ
- FILE_PERMISSIONS OWNER_READ DIRECTORY_PERMISSIONS OWNER_READ)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-stderr.txt
deleted file mode 100644
index 8d09e35..0000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-stderr.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-CMake Error at CHMOD-invalid-path\.cmake:[0-9]+ \(file\):
- file does not exist:
-
- .*/chmod-tests/I_dont_exist
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path.cmake
deleted file mode 100644
index 36915c1..0000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/I_dont_exist PERMISSIONS OWNER_READ)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-stderr.txt
deleted file mode 100644
index 84ba2a2..0000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-CMake Error at CHMOD-invalid-perms\.cmake:[0-9]+ \(file\):
- file INVALID_PERMISSION is an invalid permission specifier
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms.cmake
deleted file mode 100644
index 22cab0b..0000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a)
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS INVALID_PERMISSION)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-result.txt b/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-stderr.txt
deleted file mode 100644
index 2c248f8..0000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-CMake Error at CHMOD-no-keyword\.cmake:[0-9]+ \(file\):
- file No permissions given
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword.cmake
deleted file mode 100644
index 8b62106..0000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a)
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-no-perms-stderr.txt
deleted file mode 100644
index a18609f..0000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-CMake Error at CHMOD-no-perms\.cmake:[0-9]+ \(file\):
- file No permissions given
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-no-perms.cmake
deleted file mode 100644
index 9fbd359..0000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a)
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-ok.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-ok.cmake
deleted file mode 100644
index 87e3e57..0000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-ok.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a)
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS OWNER_READ)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-override.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-override.cmake
deleted file mode 100644
index d9226b8..0000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-override.cmake
+++ /dev/null
@@ -1,6 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a)
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS OWNER_READ
- FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-write-only-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-write-only-stderr.txt
deleted file mode 100644
index 1c87a59..0000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-write-only-stderr.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-CMake Error at CHMOD-write-only\.cmake:[0-9]+ \(file\):
- file failed to open for reading \(Permission denied\):
-
- .*/chmod-tests/a
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-write-only.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-write-only.cmake
deleted file mode 100644
index 1289efc..0000000
--- a/Tests/RunCMake/file-CHMOD/CHMOD-write-only.cmake
+++ /dev/null
@@ -1,6 +0,0 @@
-file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests)
-
-file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a "CONTENT")
-file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS OWNER_WRITE)
-file(READ ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a content)
diff --git a/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake b/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake
index 18deb89..e6b1169 100644
--- a/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake
@@ -1,12 +1,14 @@
include(RunCMake)
-run_cmake(CHMOD-no-perms)
-run_cmake(CHMOD-no-keyword)
-run_cmake(CHMOD-all-perms)
-run_cmake(CHMOD-invalid-perms)
-run_cmake(CHMOD-invalid-path)
-run_cmake(CHMOD-ok)
-run_cmake(CHMOD-override)
+run_cmake_script(no-perms)
+run_cmake_script(missing-perms)
+run_cmake_script(missing-file-perms)
+run_cmake_script(missing-dir-perms)
+run_cmake_script(all-perms)
+run_cmake_script(invalid-perms)
+run_cmake_script(invalid-path)
+run_cmake_script(ok)
+run_cmake_script(override)
if(UNIX)
execute_process(COMMAND id -u $ENV{USER}
@@ -15,5 +17,5 @@
endif()
if(NOT WIN32 AND NOT MSYS AND NOT "${uid}" STREQUAL "0")
- run_cmake(CHMOD-write-only)
+ run_cmake_script(write-only)
endif()
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-result.txt b/Tests/RunCMake/file-CHMOD/all-perms-result.txt
similarity index 100%
rename from Tests/RunCMake/file-CHMOD/CHMOD-all-perms-result.txt
rename to Tests/RunCMake/file-CHMOD/all-perms-result.txt
diff --git a/Tests/RunCMake/file-CHMOD/all-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/all-perms-stderr.txt
new file mode 100644
index 0000000..6932a1f
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/all-perms-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at [^
+]*/all-perms\.cmake:[0-9]+ \(file\):
+ file Remove either PERMISSIONS or FILE_PERMISSIONS or DIRECTORY_PERMISSIONS
+ from the invocation$
diff --git a/Tests/RunCMake/file-CHMOD/all-perms.cmake b/Tests/RunCMake/file-CHMOD/all-perms.cmake
new file mode 100644
index 0000000..5ff81b8
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/all-perms.cmake
@@ -0,0 +1,3 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_READ
+ FILE_PERMISSIONS OWNER_READ DIRECTORY_PERMISSIONS OWNER_READ)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-result.txt b/Tests/RunCMake/file-CHMOD/invalid-path-result.txt
similarity index 100%
rename from Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-result.txt
rename to Tests/RunCMake/file-CHMOD/invalid-path-result.txt
diff --git a/Tests/RunCMake/file-CHMOD/invalid-path-stderr.txt b/Tests/RunCMake/file-CHMOD/invalid-path-stderr.txt
new file mode 100644
index 0000000..eb5fb31
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/invalid-path-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at [^
+]*/invalid-path\.cmake:[0-9]+ \(file\):
+ file does not exist:
+
+ [^
+]*/Tests/RunCMake/file-CHMOD/invalid-path-build/I_dont_exist$
diff --git a/Tests/RunCMake/file-CHMOD/invalid-path.cmake b/Tests/RunCMake/file-CHMOD/invalid-path.cmake
new file mode 100644
index 0000000..e8b0313
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/invalid-path.cmake
@@ -0,0 +1 @@
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/I_dont_exist PERMISSIONS OWNER_READ)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-result.txt b/Tests/RunCMake/file-CHMOD/invalid-perms-result.txt
similarity index 100%
rename from Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-result.txt
rename to Tests/RunCMake/file-CHMOD/invalid-perms-result.txt
diff --git a/Tests/RunCMake/file-CHMOD/invalid-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/invalid-perms-stderr.txt
new file mode 100644
index 0000000..daab22e
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/invalid-perms-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error at [^
+]*/invalid-perms\.cmake:[0-9]+ \(file\):
+ file INVALID_PERMISSION is an invalid permission specifier$
diff --git a/Tests/RunCMake/file-CHMOD/invalid-perms.cmake b/Tests/RunCMake/file-CHMOD/invalid-perms.cmake
new file mode 100644
index 0000000..42129b9
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/invalid-perms.cmake
@@ -0,0 +1,2 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS INVALID_PERMISSION)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-result.txt b/Tests/RunCMake/file-CHMOD/missing-dir-perms-result.txt
similarity index 100%
copy from Tests/RunCMake/file-CHMOD/CHMOD-all-perms-result.txt
copy to Tests/RunCMake/file-CHMOD/missing-dir-perms-result.txt
diff --git a/Tests/RunCMake/file-CHMOD/missing-dir-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/missing-dir-perms-stderr.txt
new file mode 100644
index 0000000..c05bb2d
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/missing-dir-perms-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at [^
+]*/missing-dir-perms.cmake:[0-9]+ \(file\):
+ Error after keyword "DIRECTORY_PERMISSIONS":
+
+ missing required value$
diff --git a/Tests/RunCMake/file-CHMOD/missing-dir-perms.cmake b/Tests/RunCMake/file-CHMOD/missing-dir-perms.cmake
new file mode 100644
index 0000000..9d0fdad
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/missing-dir-perms.cmake
@@ -0,0 +1,2 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_READ DIRECTORY_PERMISSIONS)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-result.txt b/Tests/RunCMake/file-CHMOD/missing-file-perms-result.txt
similarity index 100%
copy from Tests/RunCMake/file-CHMOD/CHMOD-all-perms-result.txt
copy to Tests/RunCMake/file-CHMOD/missing-file-perms-result.txt
diff --git a/Tests/RunCMake/file-CHMOD/missing-file-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/missing-file-perms-stderr.txt
new file mode 100644
index 0000000..c3f4f0f
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/missing-file-perms-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at [^
+]*/missing-file-perms.cmake:[0-9]+ \(file\):
+ Error after keyword "FILE_PERMISSIONS":
+
+ missing required value$
diff --git a/Tests/RunCMake/file-CHMOD/missing-file-perms.cmake b/Tests/RunCMake/file-CHMOD/missing-file-perms.cmake
new file mode 100644
index 0000000..bcf35aa
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/missing-file-perms.cmake
@@ -0,0 +1,2 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_READ FILE_PERMISSIONS)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms-result.txt b/Tests/RunCMake/file-CHMOD/missing-perms-result.txt
similarity index 100%
copy from Tests/RunCMake/file-CHMOD/CHMOD-no-perms-result.txt
copy to Tests/RunCMake/file-CHMOD/missing-perms-result.txt
diff --git a/Tests/RunCMake/file-CHMOD/missing-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/missing-perms-stderr.txt
new file mode 100644
index 0000000..1508b13
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/missing-perms-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at [^
+]*/missing-perms.cmake:[0-9]+ \(file\):
+ Error after keyword "PERMISSIONS":
+
+ missing required value$
diff --git a/Tests/RunCMake/file-CHMOD/missing-perms.cmake b/Tests/RunCMake/file-CHMOD/missing-perms.cmake
new file mode 100644
index 0000000..da9f182
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/missing-perms.cmake
@@ -0,0 +1,2 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a FILE_PERMISSIONS OWNER_READ PERMISSIONS)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms-result.txt b/Tests/RunCMake/file-CHMOD/no-perms-result.txt
similarity index 100%
rename from Tests/RunCMake/file-CHMOD/CHMOD-no-perms-result.txt
rename to Tests/RunCMake/file-CHMOD/no-perms-result.txt
diff --git a/Tests/RunCMake/file-CHMOD/no-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/no-perms-stderr.txt
new file mode 100644
index 0000000..4c5a139
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/no-perms-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error at [^
+]*/no-perms\.cmake:[0-9]+ \(file\):
+ file No permissions given$
diff --git a/Tests/RunCMake/file-CHMOD/no-perms.cmake b/Tests/RunCMake/file-CHMOD/no-perms.cmake
new file mode 100644
index 0000000..602cfc2
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/no-perms.cmake
@@ -0,0 +1,2 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a)
diff --git a/Tests/RunCMake/file-CHMOD/ok.cmake b/Tests/RunCMake/file-CHMOD/ok.cmake
new file mode 100644
index 0000000..7c74d27
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/ok.cmake
@@ -0,0 +1,2 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_READ)
diff --git a/Tests/RunCMake/file-CHMOD/override.cmake b/Tests/RunCMake/file-CHMOD/override.cmake
new file mode 100644
index 0000000..67e5a23
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/override.cmake
@@ -0,0 +1,3 @@
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a)
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_READ
+ FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-write-only-result.txt b/Tests/RunCMake/file-CHMOD/write-only-result.txt
similarity index 100%
rename from Tests/RunCMake/file-CHMOD/CHMOD-write-only-result.txt
rename to Tests/RunCMake/file-CHMOD/write-only-result.txt
diff --git a/Tests/RunCMake/file-CHMOD/write-only-stderr.txt b/Tests/RunCMake/file-CHMOD/write-only-stderr.txt
new file mode 100644
index 0000000..169a092
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/write-only-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at [^
+]*/write-only\.cmake:[0-9]+ \(file\):
+ file failed to open for reading \(Permission denied\):
+
+ [^
+]*/Tests/RunCMake/file-CHMOD/write-only-build/a$
diff --git a/Tests/RunCMake/file-CHMOD/write-only.cmake b/Tests/RunCMake/file-CHMOD/write-only.cmake
new file mode 100644
index 0000000..aa9d803
--- /dev/null
+++ b/Tests/RunCMake/file-CHMOD/write-only.cmake
@@ -0,0 +1,3 @@
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/a "CONTENT")
+file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_WRITE)
+file(READ ${CMAKE_CURRENT_BINARY_DIR}/a content)
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2-stderr.txt b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2-stderr.txt
index c6ad3d0..39f307d 100644
--- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2-stderr.txt
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2-stderr.txt
@@ -13,11 +13,21 @@
This warning is for project developers\. Use -Wno-dev to suppress it\.
CMake Error at badargs2\.cmake:[0-9]+ \(file\):
- file Keywords missing values:
+ Error after keyword "BUNDLE_EXECUTABLE":
- RESOLVED_DEPENDENCIES_VAR
- UNRESOLVED_DEPENDENCIES_VAR
- CONFLICTING_DEPENDENCIES_PREFIX
- BUNDLE_EXECUTABLE
+ missing required value
+
+ Error after keyword "CONFLICTING_DEPENDENCIES_PREFIX":
+
+ missing required value
+
+ Error after keyword "RESOLVED_DEPENDENCIES_VAR":
+
+ missing required value
+
+ Error after keyword "UNRESOLVED_DEPENDENCIES_VAR":
+
+ missing required value
+
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt b/Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt
index 7c58aeb..54a3e5a 100644
--- a/Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt
+++ b/Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt
@@ -1,2 +1,7 @@
-CMake Error at REAL_PATH-no-base-dir.cmake:[0-9]+ \(file\):
- file BASE_DIRECTORY requires a value
+^CMake Error at REAL_PATH-no-base-dir.cmake:[0-9]+ \(file\):
+ Error after keyword "BASE_DIRECTORY":
+
+ missing required value
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp
index b80fc22..b0ed911 100644
--- a/Utilities/IWYU/mapping.imp
+++ b/Utilities/IWYU/mapping.imp
@@ -91,7 +91,7 @@
{ symbol: [ "std::__decay_and_strip<cmFindPackageCommand::PathLabel &>::__type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "std::__decay_and_strip<cmGlobalNinjaGenerator::TargetAlias &>::__type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "std::__decay_and_strip<__gnu_cxx::__normal_iterator<const cmCTestTestHandler::cmCTestTestProperties *, std::vector<cmCTestTestHandler::cmCTestTestProperties, std::allocator<cmCTestTestHandler::cmCTestTestProperties> > > &>::__type", private, "\"cmConfigure.h\"", public ] },
- { symbol: [ "std::__decay_and_strip<const __gnu_cxx::__normal_iterator<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &, void *)> > *, std::vector<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &, void *)> >, std::allocator<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &, void *)> > > > > &>::__type", private, "\"cmConfigure.h\"", public ] },
+ { symbol: [ "std::__decay_and_strip<const __gnu_cxx::__normal_iterator<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &)> > *, std::vector<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &)> >, std::allocator<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &)> > > > > &>::__type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "std::__success_type<std::chrono::duration<double, std::ratio<1, 1> > >::type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "std::__success_type<std::chrono::duration<long, std::ratio<1, 1000000000> > >::type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "std::enable_if<true, std::chrono::duration<long, std::ratio<1, 1> > >::type", private, "\"cmConfigure.h\"", public ] },