|
|
|
/*============================================================================
|
|
|
|
CMake - Cross Platform Makefile Generator
|
|
|
|
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
|
|
|
|
|
|
|
|
Distributed under the OSI-approved BSD License (the "License");
|
|
|
|
see accompanying file Copyright.txt for details.
|
|
|
|
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
|
|
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the License for more information.
|
|
|
|
============================================================================*/
|
|
|
|
#include "cmVariableWatchCommand.h"
|
|
|
|
|
|
|
|
#include "cmVariableWatch.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.push_back(
|
|
|
|
cmListFileArgument(variable, cmListFileArgument::Quoted,
|
|
|
|
9999));
|
|
|
|
newLFF.Arguments.push_back(
|
|
|
|
cmListFileArgument(accessString, cmListFileArgument::Quoted,
|
|
|
|
9999));
|
|
|
|
newLFF.Arguments.push_back(
|
|
|
|
cmListFileArgument(newValue?newValue:"", cmListFileArgument::Quoted,
|
|
|
|
9999));
|
|
|
|
newLFF.Arguments.push_back(
|
|
|
|
cmListFileArgument(currentListFile, cmListFileArgument::Quoted,
|
|
|
|
9999));
|
|
|
|
newLFF.Arguments.push_back(
|
|
|
|
cmListFileArgument(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()
|
|
|
|
{
|
|
|
|
std::set<std::string>::const_iterator it;
|
|
|
|
for ( it = this->WatchedVariables.begin();
|
|
|
|
it != this->WatchedVariables.end();
|
|
|
|
++it )
|
|
|
|
{
|
|
|
|
this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch(
|
|
|
|
*it, cmVariableWatchCommandVariableAccessed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmVariableWatchCommand
|
|
|
|
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
|
|
|
|
{
|
|
|
|
if ( args.size() < 1 )
|
|
|
|
{
|
|
|
|
this->SetError("must be called with at least one argument.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
std::string 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;
|
|
|
|
}
|