cmServerProtocol.cxx 7.7 KB

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