cmVariableWatchCommand.cxx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmVariableWatchCommand.h"
  11. #include "cmVariableWatch.h"
  12. //----------------------------------------------------------------------------
  13. struct cmVariableWatchCallbackData
  14. {
  15. bool InCallback;
  16. std::string Command;
  17. };
  18. //----------------------------------------------------------------------------
  19. static void cmVariableWatchCommandVariableAccessed(
  20. const std::string& variable, int access_type, void* client_data,
  21. const char* newValue, const cmMakefile* mf)
  22. {
  23. cmVariableWatchCallbackData* data
  24. = static_cast<cmVariableWatchCallbackData*>(client_data);
  25. if ( data->InCallback )
  26. {
  27. return;
  28. }
  29. data->InCallback = true;
  30. cmListFileFunction newLFF;
  31. cmListFileArgument arg;
  32. bool processed = false;
  33. const char* accessString = cmVariableWatch::GetAccessAsString(access_type);
  34. const char* currentListFile = mf->GetDefinition("CMAKE_CURRENT_LIST_FILE");
  35. /// Ultra bad!!
  36. cmMakefile* makefile = const_cast<cmMakefile*>(mf);
  37. std::string stack = makefile->GetProperty("LISTFILE_STACK");
  38. if ( !data->Command.empty() )
  39. {
  40. newLFF.Arguments.clear();
  41. newLFF.Arguments.push_back(
  42. cmListFileArgument(variable, cmListFileArgument::Quoted,
  43. "unknown", 9999));
  44. newLFF.Arguments.push_back(
  45. cmListFileArgument(accessString, cmListFileArgument::Quoted,
  46. "unknown", 9999));
  47. newLFF.Arguments.push_back(
  48. cmListFileArgument(newValue?newValue:"", cmListFileArgument::Quoted,
  49. "unknown", 9999));
  50. newLFF.Arguments.push_back(
  51. cmListFileArgument(currentListFile, cmListFileArgument::Quoted,
  52. "unknown", 9999));
  53. newLFF.Arguments.push_back(
  54. cmListFileArgument(stack, cmListFileArgument::Quoted,
  55. "unknown", 9999));
  56. newLFF.Name = data->Command;
  57. newLFF.FilePath = "Some weird path";
  58. newLFF.Line = 9999;
  59. cmExecutionStatus status;
  60. if(!makefile->ExecuteCommand(newLFF,status))
  61. {
  62. arg.FilePath = "Unknown";
  63. arg.Line = 0;
  64. cmOStringStream error;
  65. error << "Error in cmake code at\n"
  66. << arg.FilePath << ":" << arg.Line << ":\n"
  67. << "A command failed during the invocation of callback \""
  68. << data->Command << "\".";
  69. cmSystemTools::Error(error.str().c_str());
  70. data->InCallback = false;
  71. return;
  72. }
  73. processed = true;
  74. }
  75. if ( !processed )
  76. {
  77. cmOStringStream msg;
  78. msg << "Variable \"" << variable.c_str() << "\" was accessed using "
  79. << accessString << " with value \"" << (newValue?newValue:"") << "\".";
  80. makefile->IssueMessage(cmake::LOG, msg.str());
  81. }
  82. data->InCallback = false;
  83. }
  84. //----------------------------------------------------------------------------
  85. static void deleteVariableWatchCallbackData(void* client_data)
  86. {
  87. cmVariableWatchCallbackData* data
  88. = static_cast<cmVariableWatchCallbackData*>(client_data);
  89. delete data;
  90. }
  91. //----------------------------------------------------------------------------
  92. cmVariableWatchCommand::cmVariableWatchCommand()
  93. {
  94. }
  95. //----------------------------------------------------------------------------
  96. cmVariableWatchCommand::~cmVariableWatchCommand()
  97. {
  98. std::set<std::string>::const_iterator it;
  99. for ( it = this->WatchedVariables.begin();
  100. it != this->WatchedVariables.end();
  101. ++it )
  102. {
  103. this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch(
  104. *it, cmVariableWatchCommandVariableAccessed);
  105. }
  106. }
  107. //----------------------------------------------------------------------------
  108. bool cmVariableWatchCommand
  109. ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
  110. {
  111. if ( args.size() < 1 )
  112. {
  113. this->SetError("must be called with at least one argument.");
  114. return false;
  115. }
  116. std::string variable = args[0];
  117. std::string command;
  118. if ( args.size() > 1 )
  119. {
  120. command = args[1];
  121. }
  122. if ( variable == "CMAKE_CURRENT_LIST_FILE" )
  123. {
  124. cmOStringStream ostr;
  125. ostr << "cannot be set on the variable: " << variable.c_str();
  126. this->SetError(ostr.str().c_str());
  127. return false;
  128. }
  129. cmVariableWatchCallbackData* data = new cmVariableWatchCallbackData;
  130. data->InCallback = false;
  131. data->Command = command;
  132. this->WatchedVariables.insert(variable);
  133. if ( !this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch(
  134. variable, cmVariableWatchCommandVariableAccessed,
  135. data, deleteVariableWatchCallbackData) )
  136. {
  137. deleteVariableWatchCallbackData(data);
  138. return false;
  139. }
  140. return true;
  141. }