summaryrefslogtreecommitdiff
path: root/Source/cmVariableWatchCommand.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmVariableWatchCommand.cxx')
-rw-r--r--Source/cmVariableWatchCommand.cxx78
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;
}