123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
- #include "cmVariableWatchCommand.h"
- #include <sstream>
- #include "cmExecutionStatus.h"
- #include "cmListFileCache.h"
- #include "cmMakefile.h"
- #include "cmSystemTools.h"
- #include "cmVariableWatch.h"
- #include "cmake.h"
- struct cmVariableWatchCallbackData
- {
- bool InCallback;
- std::string Command;
- };
- static void cmVariableWatchCommandVariableAccessed(const std::string& variable,
- int access_type,
- void* client_data,
- const char* newValue,
- const cmMakefile* mf)
- {
- cmVariableWatchCallbackData* data =
- static_cast<cmVariableWatchCallbackData*>(client_data);
- if (data->InCallback) {
- return;
- }
- 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");
- if (!data->Command.empty()) {
- newLFF.Arguments.clear();
- newLFF.Arguments.emplace_back(variable, cmListFileArgument::Quoted, 9999);
- newLFF.Arguments.emplace_back(accessString, cmListFileArgument::Quoted,
- 9999);
- newLFF.Arguments.emplace_back(newValue ? newValue : "",
- cmListFileArgument::Quoted, 9999);
- newLFF.Arguments.emplace_back(currentListFile, cmListFileArgument::Quoted,
- 9999);
- newLFF.Arguments.emplace_back(stack, cmListFileArgument::Quoted, 9999);
- newLFF.Name = data->Command;
- newLFF.Line = 9999;
- cmExecutionStatus status;
- 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().c_str());
- data->InCallback = false;
- return;
- }
- processed = true;
- }
- if (!processed) {
- std::ostringstream msg;
- msg << "Variable \"" << variable << "\" was accessed using "
- << accessString << " with value \"" << (newValue ? newValue : "")
- << "\".";
- makefile->IssueMessage(cmake::LOG, msg.str());
- }
- data->InCallback = false;
- }
- static void deleteVariableWatchCallbackData(void* client_data)
- {
- cmVariableWatchCallbackData* data =
- static_cast<cmVariableWatchCallbackData*>(client_data);
- delete data;
- }
- cmVariableWatchCommand::cmVariableWatchCommand()
- {
- }
- cmVariableWatchCommand::~cmVariableWatchCommand()
- {
- for (std::string const& wv : this->WatchedVariables) {
- this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch(
- wv, cmVariableWatchCommandVariableAccessed);
- }
- }
- bool cmVariableWatchCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
- {
- if (args.empty()) {
- this->SetError("must be called with at least one argument.");
- return false;
- }
- std::string const& variable = args[0];
- std::string command;
- if (args.size() > 1) {
- command = args[1];
- }
- if (variable == "CMAKE_CURRENT_LIST_FILE") {
- std::ostringstream ostr;
- ostr << "cannot be set on the variable: " << variable;
- this->SetError(ostr.str());
- return false;
- }
- cmVariableWatchCallbackData* data = new cmVariableWatchCallbackData;
- data->InCallback = false;
- data->Command = command;
- this->WatchedVariables.insert(variable);
- if (!this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch(
- variable, cmVariableWatchCommandVariableAccessed, data,
- deleteVariableWatchCallbackData)) {
- deleteVariableWatchCallbackData(data);
- return false;
- }
- return true;
- }
|