cmServerProtocol.cxx 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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. cmake* cmServerProtocol::CMakeInstance() const
  106. {
  107. return this->m_CMakeInstance.get();
  108. }
  109. bool cmServerProtocol::DoActivate(const cmServerRequest& /*request*/,
  110. std::string* /*errorMessage*/)
  111. {
  112. return true;
  113. }
  114. std::pair<int, int> cmServerProtocol1_0::ProtocolVersion() const
  115. {
  116. return std::make_pair(1, 0);
  117. }
  118. bool cmServerProtocol1_0::DoActivate(const cmServerRequest& request,
  119. std::string* errorMessage)
  120. {
  121. std::string sourceDirectory = request.Data[kSOURCE_DIRECTORY_KEY].asString();
  122. const std::string buildDirectory =
  123. request.Data[kBUILD_DIRECTORY_KEY].asString();
  124. std::string generator = request.Data[kGENERATOR_KEY].asString();
  125. std::string extraGenerator = request.Data[kEXTRA_GENERATOR_KEY].asString();
  126. if (buildDirectory.empty()) {
  127. if (errorMessage)
  128. *errorMessage =
  129. std::string("\"") + kBUILD_DIRECTORY_KEY + "\" is missing.";
  130. return false;
  131. }
  132. cmake* cm = CMakeInstance();
  133. if (cmSystemTools::PathExists(buildDirectory)) {
  134. if (!cmSystemTools::FileIsDirectory(buildDirectory)) {
  135. if (errorMessage)
  136. *errorMessage = std::string("\"") + kBUILD_DIRECTORY_KEY +
  137. "\" exists but is not a directory.";
  138. return false;
  139. }
  140. const std::string cachePath = cm->FindCacheFile(buildDirectory);
  141. if (cm->LoadCache(cachePath)) {
  142. cmState* state = cm->GetState();
  143. // Check generator:
  144. const std::string cachedGenerator =
  145. std::string(state->GetCacheEntryValue("CMAKE_GENERATOR"));
  146. if (cachedGenerator.empty() && generator.empty()) {
  147. if (errorMessage)
  148. *errorMessage =
  149. std::string("\"") + kGENERATOR_KEY + "\" is required but unset.";
  150. return false;
  151. }
  152. if (generator.empty()) {
  153. generator = cachedGenerator;
  154. }
  155. if (generator != cachedGenerator) {
  156. if (errorMessage)
  157. *errorMessage = std::string("\"") + kGENERATOR_KEY +
  158. "\" set but incompatible with configured generator.";
  159. return false;
  160. }
  161. // check extra generator:
  162. const std::string cachedExtraGenerator =
  163. std::string(state->GetCacheEntryValue("CMAKE_EXTRA_GENERATOR"));
  164. if (!cachedExtraGenerator.empty() && !extraGenerator.empty() &&
  165. cachedExtraGenerator != extraGenerator) {
  166. if (errorMessage)
  167. *errorMessage = std::string("\"") + kEXTRA_GENERATOR_KEY +
  168. "\" is set but incompatible with configured extra generator.";
  169. return false;
  170. }
  171. if (extraGenerator.empty()) {
  172. extraGenerator = cachedExtraGenerator;
  173. }
  174. // check sourcedir:
  175. const std::string cachedSourceDirectory =
  176. std::string(state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY"));
  177. if (!cachedSourceDirectory.empty() && !sourceDirectory.empty() &&
  178. cachedSourceDirectory != sourceDirectory) {
  179. if (errorMessage)
  180. *errorMessage = std::string("\"") + kSOURCE_DIRECTORY_KEY +
  181. "\" is set but incompatible with configured source directory.";
  182. return false;
  183. }
  184. if (sourceDirectory.empty()) {
  185. sourceDirectory = cachedSourceDirectory;
  186. }
  187. }
  188. }
  189. if (sourceDirectory.empty()) {
  190. if (errorMessage)
  191. *errorMessage = std::string("\"") + kSOURCE_DIRECTORY_KEY +
  192. "\" is unset but required.";
  193. return false;
  194. }
  195. if (!cmSystemTools::FileIsDirectory(sourceDirectory)) {
  196. if (errorMessage)
  197. *errorMessage =
  198. std::string("\"") + kSOURCE_DIRECTORY_KEY + "\" is not a directory.";
  199. return false;
  200. }
  201. if (generator.empty()) {
  202. if (errorMessage)
  203. *errorMessage =
  204. std::string("\"") + kGENERATOR_KEY + "\" is unset but required.";
  205. return false;
  206. }
  207. const std::string fullGeneratorName =
  208. cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
  209. generator, extraGenerator);
  210. cmGlobalGenerator* gg = cm->CreateGlobalGenerator(fullGeneratorName);
  211. if (!gg) {
  212. if (errorMessage)
  213. *errorMessage =
  214. std::string("Could not set up the requested combination of \"") +
  215. kGENERATOR_KEY + "\" and \"" + kEXTRA_GENERATOR_KEY + "\"";
  216. return false;
  217. }
  218. cm->SetGlobalGenerator(gg);
  219. cm->SetHomeDirectory(sourceDirectory);
  220. cm->SetHomeOutputDirectory(buildDirectory);
  221. this->m_State = STATE_ACTIVE;
  222. return true;
  223. }
  224. const cmServerResponse cmServerProtocol1_0::Process(
  225. const cmServerRequest& request)
  226. {
  227. assert(this->m_State >= STATE_ACTIVE);
  228. return request.ReportError("Unknown command!");
  229. }
  230. bool cmServerProtocol1_0::IsExperimental() const
  231. {
  232. return true;
  233. }