cmake/Source/cmVariableWatchCommand.cxx

136 lines
4.2 KiB
C++
Raw Normal View History

2016-10-30 18:24:19 +01:00
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVariableWatchCommand.h"
2017-04-14 19:02:05 +02:00
#include <sstream>
#include "cmExecutionStatus.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmVariableWatch.h"
2017-04-14 19:02:05 +02:00
#include "cmake.h"
2013-11-03 12:27:13 +02:00
struct cmVariableWatchCallbackData
{
2013-11-03 12:27:13 +02:00
bool InCallback;
std::string Command;
};
2016-07-09 11:21:54 +02:00
static void cmVariableWatchCommandVariableAccessed(const std::string& variable,
int access_type,
void* client_data,
const char* newValue,
const cmMakefile* mf)
{
2016-07-09 11:21:54 +02:00
cmVariableWatchCallbackData* data =
static_cast<cmVariableWatchCallbackData*>(client_data);
2016-07-09 11:21:54 +02:00
if (data->InCallback) {
return;
2016-07-09 11:21:54 +02:00
}
2013-11-03 12:27:13 +02:00
data->InCallback = true;
cmListFileFunction newLFF;
cmListFileArgument arg;
bool processed = false;
const char* accessString = cmVariableWatch::GetAccessAsString(access_type);
const char* currentListFile = mf->GetDefinition("CMAKE_CURRENT_LIST_FILE");
/// Ultra bad!!
cmMakefile* makefile = const_cast<cmMakefile*>(mf);
std::string stack = makefile->GetProperty("LISTFILE_STACK");
2016-07-09 11:21:54 +02:00
if (!data->Command.empty()) {
newLFF.Arguments.clear();
newLFF.Arguments.push_back(
2016-07-09 11:21:54 +02:00
cmListFileArgument(variable, cmListFileArgument::Quoted, 9999));
newLFF.Arguments.push_back(
2016-07-09 11:21:54 +02:00
cmListFileArgument(accessString, cmListFileArgument::Quoted, 9999));
newLFF.Arguments.push_back(cmListFileArgument(
newValue ? newValue : "", cmListFileArgument::Quoted, 9999));
newLFF.Arguments.push_back(
2016-07-09 11:21:54 +02:00
cmListFileArgument(currentListFile, cmListFileArgument::Quoted, 9999));
newLFF.Arguments.push_back(
2016-07-09 11:21:54 +02:00
cmListFileArgument(stack, cmListFileArgument::Quoted, 9999));
2013-11-03 12:27:13 +02:00
newLFF.Name = data->Command;
newLFF.Line = 9999;
cmExecutionStatus status;
2016-07-09 11:21:54 +02:00
if (!makefile->ExecuteCommand(newLFF, status)) {
2015-04-27 22:25:09 +02:00
std::ostringstream error;
2015-11-17 17:22:37 +01:00
error << "Error in cmake code at\nUnknown:0:\n"
2016-07-09 11:21:54 +02:00
<< "A command failed during the invocation of callback \""
<< data->Command << "\".";
cmSystemTools::Error(error.str().c_str());
2013-11-03 12:27:13 +02:00
data->InCallback = false;
return;
}
2016-07-09 11:21:54 +02:00
processed = true;
}
if (!processed) {
2015-04-27 22:25:09 +02:00
std::ostringstream msg;
msg << "Variable \"" << variable << "\" was accessed using "
2016-07-09 11:21:54 +02:00
<< accessString << " with value \"" << (newValue ? newValue : "")
<< "\".";
2013-11-03 12:27:13 +02:00
makefile->IssueMessage(cmake::LOG, msg.str());
2016-07-09 11:21:54 +02:00
}
2013-11-03 12:27:13 +02:00
data->InCallback = false;
}
static void deleteVariableWatchCallbackData(void* client_data)
{
2016-07-09 11:21:54 +02:00
cmVariableWatchCallbackData* data =
static_cast<cmVariableWatchCallbackData*>(client_data);
2013-11-03 12:27:13 +02:00
delete data;
}
cmVariableWatchCommand::cmVariableWatchCommand()
{
}
cmVariableWatchCommand::~cmVariableWatchCommand()
{
std::set<std::string>::const_iterator it;
2016-07-09 11:21:54 +02:00
for (it = this->WatchedVariables.begin(); it != this->WatchedVariables.end();
++it) {
2013-11-03 12:27:13 +02:00
this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch(
*it, cmVariableWatchCommandVariableAccessed);
2016-07-09 11:21:54 +02:00
}
2013-11-03 12:27:13 +02:00
}
2016-07-09 11:21:54 +02:00
bool cmVariableWatchCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus&)
2013-11-03 12:27:13 +02:00
{
2016-10-30 18:24:19 +01:00
if (args.empty()) {
2013-11-03 12:27:13 +02:00
this->SetError("must be called with at least one argument.");
return false;
2016-07-09 11:21:54 +02:00
}
2017-07-20 19:35:53 +02:00
std::string const& variable = args[0];
2013-11-03 12:27:13 +02:00
std::string command;
2016-07-09 11:21:54 +02:00
if (args.size() > 1) {
2013-11-03 12:27:13 +02:00
command = args[1];
2016-07-09 11:21:54 +02:00
}
if (variable == "CMAKE_CURRENT_LIST_FILE") {
2015-04-27 22:25:09 +02:00
std::ostringstream ostr;
ostr << "cannot be set on the variable: " << variable;
this->SetError(ostr.str());
2013-11-03 12:27:13 +02:00
return false;
2016-07-09 11:21:54 +02:00
}
2013-11-03 12:27:13 +02:00
cmVariableWatchCallbackData* data = new cmVariableWatchCallbackData;
data->InCallback = false;
data->Command = command;
this->WatchedVariables.insert(variable);
2016-07-09 11:21:54 +02:00
if (!this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch(
variable, cmVariableWatchCommandVariableAccessed, data,
deleteVariableWatchCallbackData)) {
2013-11-03 12:27:13 +02:00
deleteVariableWatchCallbackData(data);
return false;
2016-07-09 11:21:54 +02:00
}
2013-11-03 12:27:13 +02:00
return true;
}