diff options
Diffstat (limited to 'Source/cmVariableWatchCommand.cxx')
-rw-r--r-- | Source/cmVariableWatchCommand.cxx | 78 |
1 files changed, 51 insertions, 27 deletions
diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index 5fe55bd53..f2c8f3cdb 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -2,12 +2,14 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmVariableWatchCommand.h" -#include <sstream> +#include <memory> +#include <utility> #include "cmExecutionStatus.h" #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVariableWatch.h" #include "cmake.h" @@ -54,24 +56,22 @@ static void cmVariableWatchCommandVariableAccessed(const std::string& variable, newLFF.Arguments.emplace_back(stack, cmListFileArgument::Quoted, 9999); newLFF.Name = data->Command; newLFF.Line = 9999; - cmExecutionStatus status; + cmExecutionStatus status(*makefile); if (!makefile->ExecuteCommand(newLFF, status)) { - std::ostringstream error; - error << "Error in cmake code at\nUnknown:0:\n" - << "A command failed during the invocation of callback \"" - << data->Command << "\"."; - cmSystemTools::Error(error.str()); + cmSystemTools::Error( + cmStrCat("Error in cmake code at\nUnknown:0:\nA command failed " + "during the invocation of callback \"", + data->Command, "\".")); data->InCallback = false; return; } processed = true; } if (!processed) { - std::ostringstream msg; - msg << "Variable \"" << variable << "\" was accessed using " - << accessString << " with value \"" << (newValue ? newValue : "") - << "\"."; - makefile->IssueMessage(MessageType::LOG, msg.str()); + makefile->IssueMessage( + MessageType::LOG, + cmStrCat("Variable \"", variable, "\" was accessed using ", accessString, + " with value \"", (newValue ? newValue : ""), "\".")); } data->InCallback = false; @@ -84,21 +84,46 @@ static void deleteVariableWatchCallbackData(void* client_data) delete data; } -cmVariableWatchCommand::cmVariableWatchCommand() = default; - -cmVariableWatchCommand::~cmVariableWatchCommand() +/** This command does not really have a final pass but it needs to + stay alive since it owns variable watch callback information. */ +class FinalAction { - for (std::string const& wv : this->WatchedVariables) { - this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch( - wv, cmVariableWatchCommandVariableAccessed); +public: + /* NOLINTNEXTLINE(performance-unnecessary-value-param) */ + FinalAction(cmMakefile* makefile, std::string variable) + : Action(std::make_shared<Impl>(makefile, std::move(variable))) + { } -} -bool cmVariableWatchCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) + void operator()(cmMakefile&) const {} + +private: + struct Impl + { + Impl(cmMakefile* makefile, std::string variable) + : Makefile(makefile) + , Variable(std::move(variable)) + { + } + + ~Impl() + { + this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch( + this->Variable, cmVariableWatchCommandVariableAccessed); + } + + cmMakefile* Makefile; + std::string Variable; + }; + + std::shared_ptr<Impl const> Action; +}; + +bool cmVariableWatchCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("must be called with at least one argument."); + status.SetError("must be called with at least one argument."); return false; } std::string const& variable = args[0]; @@ -107,9 +132,7 @@ bool cmVariableWatchCommand::InitialPass(std::vector<std::string> const& args, command = args[1]; } if (variable == "CMAKE_CURRENT_LIST_FILE") { - std::ostringstream ostr; - ostr << "cannot be set on the variable: " << variable; - this->SetError(ostr.str()); + status.SetError(cmStrCat("cannot be set on the variable: ", variable)); return false; } @@ -118,13 +141,14 @@ bool cmVariableWatchCommand::InitialPass(std::vector<std::string> const& args, data->InCallback = false; data->Command = command; - this->WatchedVariables.insert(variable); - if (!this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch( + if (!status.GetMakefile().GetCMakeInstance()->GetVariableWatch()->AddWatch( variable, cmVariableWatchCommandVariableAccessed, data, deleteVariableWatchCallbackData)) { deleteVariableWatchCallbackData(data); return false; } + status.GetMakefile().AddFinalAction( + FinalAction(&status.GetMakefile(), variable)); return true; } |