cmServerProtocol.cxx 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2016 Tobias Hunger <[email protected]>
  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 "cmServerProtocol.h"
  11. #include "cmExternalMakefileProjectGenerator.h"
  12. #include "cmServer.h"
  13. #include "cmServerDictionary.h"
  14. #include "cmSystemTools.h"
  15. #include "cmake.h"
  16. #include "cmServerDictionary.h"
  17. #if defined(CMAKE_BUILD_WITH_CMAKE)
  18. #include "cm_jsoncpp_reader.h"
  19. #include "cm_jsoncpp_value.h"
  20. #endif
  21. cmServerRequest::cmServerRequest(cmServer* server, const std::string& t,
  22. const std::string& c, const Json::Value& d)
  23. : Type(t)
  24. , Cookie(c)
  25. , Data(d)
  26. , m_Server(server)
  27. {
  28. }
  29. void cmServerRequest::ReportProgress(int min, int current, int max,
  30. const std::string& message) const
  31. {
  32. this->m_Server->WriteProgress(*this, min, current, max, message);
  33. }
  34. void cmServerRequest::ReportMessage(const std::string& message,
  35. const std::string& title) const
  36. {
  37. m_Server->WriteMessage(*this, message, title);
  38. }
  39. cmServerResponse cmServerRequest::Reply(const Json::Value& data) const
  40. {
  41. cmServerResponse response(*this);
  42. response.SetData(data);
  43. return response;
  44. }
  45. cmServerResponse cmServerRequest::ReportError(const std::string& message) const
  46. {
  47. cmServerResponse response(*this);
  48. response.SetError(message);
  49. return response;
  50. }
  51. cmServerResponse::cmServerResponse(const cmServerRequest& request)
  52. : Type(request.Type)
  53. , Cookie(request.Cookie)
  54. {
  55. }
  56. void cmServerResponse::SetData(const Json::Value& data)
  57. {
  58. assert(this->m_Payload == PAYLOAD_UNKNOWN);
  59. if (!data[kCOOKIE_KEY].isNull() || !data[kTYPE_KEY].isNull()) {
  60. this->SetError("Response contains cookie or type field.");
  61. return;
  62. }
  63. this->m_Payload = PAYLOAD_DATA;
  64. this->m_Data = data;
  65. }
  66. void cmServerResponse::SetError(const std::string& message)
  67. {
  68. assert(this->m_Payload == PAYLOAD_UNKNOWN);
  69. this->m_Payload = PAYLOAD_ERROR;
  70. this->m_ErrorMessage = message;
  71. }
  72. bool cmServerResponse::IsComplete() const
  73. {
  74. return this->m_Payload != PAYLOAD_UNKNOWN;
  75. }
  76. bool cmServerResponse::IsError() const
  77. {
  78. assert(this->m_Payload != PAYLOAD_UNKNOWN);
  79. return this->m_Payload == PAYLOAD_ERROR;
  80. }
  81. std::string cmServerResponse::ErrorMessage() const
  82. {
  83. if (this->m_Payload == PAYLOAD_ERROR)
  84. return this->m_ErrorMessage;
  85. else
  86. return std::string();
  87. }
  88. Json::Value cmServerResponse::Data() const
  89. {
  90. assert(this->m_Payload != PAYLOAD_UNKNOWN);
  91. return this->m_Data;
  92. }
  93. bool cmServerProtocol::Activate(cmServer* server,
  94. const cmServerRequest& request,
  95. std::string* errorMessage)
  96. {
  97. assert(server);
  98. this->m_Server = server;
  99. this->m_CMakeInstance = std::make_unique<cmake>();
  100. const bool result = this->DoActivate(request, errorMessage);
  101. if (!result)
  102. this->m_CMakeInstance = CM_NULLPTR;
  103. return result;
  104. }
  105. void cmServerProtocol::SendSignal(const std::string& name,
  106. const Json::Value& data) const
  107. {
  108. if (this->m_Server)
  109. this->m_Server->WriteSignal(name, data);
  110. }
  111. cmake* cmServerProtocol::CMakeInstance() const
  112. {
  113. return this->m_CMakeInstance.get();
  114. }
  115. bool cmServerProtocol::DoActivate(const cmServerRequest& /*request*/,
  116. std::string* /*errorMessage*/)
  117. {
  118. return true;
  119. }
  120. std::pair<int, int> cmServerProtocol1_0::ProtocolVersion() const
  121. {
  122. return std::make_pair(1, 0);
  123. }
  124. bool cmServerProtocol1_0::DoActivate(const cmServerRequest& request,
  125. std::string* errorMessage)
  126. {
  127. std::string sourceDirectory = request.Data[kSOURCE_DIRECTORY_KEY].asString();
  128. const std::string buildDirectory =
  129. request.Data[kBUILD_DIRECTORY_KEY].asString();
  130. std::string generator = request.Data[kGENERATOR_KEY].asString();
  131. std::string extraGenerator = request.Data[kEXTRA_GENERATOR_KEY].asString();
  132. if (buildDirectory.empty()) {
  133. if (errorMessage)
  134. *errorMessage =
  135. std::string("\"") + kBUILD_DIRECTORY_KEY + "\" is missing.";
  136. return false;
  137. }
  138. cmake* cm = CMakeInstance();
  139. if (cmSystemTools::PathExists(buildDirectory)) {
  140. if (!cmSystemTools::FileIsDirectory(buildDirectory)) {
  141. if (errorMessage)
  142. *errorMessage = std::string("\"") + kBUILD_DIRECTORY_KEY +
  143. "\" exists but is not a directory.";
  144. return false;
  145. }
  146. const std::string cachePath = cm->FindCacheFile(buildDirectory);
  147. if (cm->LoadCache(cachePath)) {
  148. cmState* state = cm->GetState();
  149. // Check generator:
  150. const std::string cachedGenerator =
  151. std::string(state->GetCacheEntryValue("CMAKE_GENERATOR"));
  152. if (cachedGenerator.empty() && generator.empty()) {
  153. if (errorMessage)
  154. *errorMessage =
  155. std::string("\"") + kGENERATOR_KEY + "\" is required but unset.";
  156. return false;
  157. }
  158. if (generator.empty()) {
  159. generator = cachedGenerator;
  160. }
  161. if (generator != cachedGenerator) {
  162. if (errorMessage)
  163. *errorMessage = std::string("\"") + kGENERATOR_KEY +
  164. "\" set but incompatible with configured generator.";
  165. return false;
  166. }
  167. // check extra generator:
  168. const std::string cachedExtraGenerator =
  169. std::string(state->GetCacheEntryValue("CMAKE_EXTRA_GENERATOR"));
  170. if (!cachedExtraGenerator.empty() && !extraGenerator.empty() &&
  171. cachedExtraGenerator != extraGenerator) {
  172. if (errorMessage)
  173. *errorMessage = std::string("\"") + kEXTRA_GENERATOR_KEY +
  174. "\" is set but incompatible with configured extra generator.";
  175. return false;
  176. }
  177. if (extraGenerator.empty()) {
  178. extraGenerator = cachedExtraGenerator;
  179. }
  180. // check sourcedir:
  181. const std::string cachedSourceDirectory =
  182. std::string(state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY"));
  183. if (!cachedSourceDirectory.empty() && !sourceDirectory.empty() &&
  184. cachedSourceDirectory != sourceDirectory) {
  185. if (errorMessage)
  186. *errorMessage = std::string("\"") + kSOURCE_DIRECTORY_KEY +
  187. "\" is set but incompatible with configured source directory.";
  188. return false;
  189. }
  190. if (sourceDirectory.empty()) {
  191. sourceDirectory = cachedSourceDirectory;
  192. }
  193. }
  194. }
  195. if (sourceDirectory.empty()) {
  196. if (errorMessage)
  197. *errorMessage = std::string("\"") + kSOURCE_DIRECTORY_KEY +
  198. "\" is unset but required.";
  199. return false;
  200. }
  201. if (!cmSystemTools::FileIsDirectory(sourceDirectory)) {
  202. if (errorMessage)
  203. *errorMessage =
  204. std::string("\"") + kSOURCE_DIRECTORY_KEY + "\" is not a directory.";
  205. return false;
  206. }
  207. if (generator.empty()) {
  208. if (errorMessage)
  209. *errorMessage =
  210. std::string("\"") + kGENERATOR_KEY + "\" is unset but required.";
  211. return false;
  212. }
  213. const std::string fullGeneratorName =
  214. cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
  215. generator, extraGenerator);
  216. cmGlobalGenerator* gg = cm->CreateGlobalGenerator(fullGeneratorName);
  217. if (!gg) {
  218. if (errorMessage)
  219. *errorMessage =
  220. std::string("Could not set up the requested combination of \"") +
  221. kGENERATOR_KEY + "\" and \"" + kEXTRA_GENERATOR_KEY + "\"";
  222. return false;
  223. }
  224. cm->SetGlobalGenerator(gg);
  225. cm->SetHomeDirectory(sourceDirectory);
  226. cm->SetHomeOutputDirectory(buildDirectory);
  227. this->m_State = STATE_ACTIVE;
  228. return true;
  229. }
  230. const cmServerResponse cmServerProtocol1_0::Process(
  231. const cmServerRequest& request)
  232. {
  233. assert(this->m_State >= STATE_ACTIVE);
  234. return request.ReportError("Unknown command!");
  235. }
  236. bool cmServerProtocol1_0::IsExperimental() const
  237. {
  238. return true;
  239. }