diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx index 7643b4783..123b6a48e 100644 --- a/Source/cmServer.cxx +++ b/Source/cmServer.cxx @@ -87,6 +87,8 @@ void read_stdin(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) cmServer::cmServer() { + // Register supported protocols: + this->RegisterProtocol(new cmServerProtocol1_0); } cmServer::~cmServer() @@ -245,6 +247,7 @@ cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request) void cmServer::Serve() { + assert(!this->SupportedProtocols.empty()); assert(!this->Protocol); this->Loop = uv_default_loop(); diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 659aa0f00..c3a4d8e55 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -14,6 +14,7 @@ #include "cmExternalMakefileProjectGenerator.h" #include "cmServer.h" +#include "cmSystemTools.h" #include "cmake.h" #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -24,7 +25,11 @@ namespace { // Vocabulary: +const std::string kBUILD_DIRECTORY_KEY = "buildDirectory"; const std::string kCOOKIE_KEY = "cookie"; +const std::string kEXTRA_GENERATOR_KEY = "extraGenerator"; +const std::string kGENERATOR_KEY = "generator"; +const std::string kSOURCE_DIRECTORY_KEY = "sourceDirectory"; const std::string kTYPE_KEY = "type"; } // namespace @@ -127,3 +132,133 @@ bool cmServerProtocol::DoActivate(const cmServerRequest& /*request*/, { return true; } + +std::pair cmServerProtocol1_0::ProtocolVersion() const +{ + return std::make_pair(1, 0); +} + +bool cmServerProtocol1_0::DoActivate(const cmServerRequest& request, + std::string* errorMessage) +{ + std::string sourceDirectory = request.Data[kSOURCE_DIRECTORY_KEY].asString(); + const std::string buildDirectory = + request.Data[kBUILD_DIRECTORY_KEY].asString(); + std::string generator = request.Data[kGENERATOR_KEY].asString(); + std::string extraGenerator = request.Data[kEXTRA_GENERATOR_KEY].asString(); + + if (buildDirectory.empty()) { + if (errorMessage) + *errorMessage = + std::string("\"") + kBUILD_DIRECTORY_KEY + "\" is missing."; + return false; + } + cmake* cm = CMakeInstance(); + if (cmSystemTools::PathExists(buildDirectory)) { + if (!cmSystemTools::FileIsDirectory(buildDirectory)) { + if (errorMessage) + *errorMessage = std::string("\"") + kBUILD_DIRECTORY_KEY + + "\" exists but is not a directory."; + return false; + } + + const std::string cachePath = cm->FindCacheFile(buildDirectory); + if (cm->LoadCache(cachePath)) { + cmState* state = cm->GetState(); + + // Check generator: + const std::string cachedGenerator = + std::string(state->GetCacheEntryValue("CMAKE_GENERATOR")); + if (cachedGenerator.empty() && generator.empty()) { + if (errorMessage) + *errorMessage = + std::string("\"") + kGENERATOR_KEY + "\" is required but unset."; + return false; + } + if (generator.empty()) { + generator = cachedGenerator; + } + if (generator != cachedGenerator) { + if (errorMessage) + *errorMessage = std::string("\"") + kGENERATOR_KEY + + "\" set but incompatible with configured generator."; + return false; + } + + // check extra generator: + const std::string cachedExtraGenerator = + std::string(state->GetCacheEntryValue("CMAKE_EXTRA_GENERATOR")); + if (!cachedExtraGenerator.empty() && !extraGenerator.empty() && + cachedExtraGenerator != extraGenerator) { + if (errorMessage) + *errorMessage = std::string("\"") + kEXTRA_GENERATOR_KEY + + "\" is set but incompatible with configured extra generator."; + return false; + } + if (extraGenerator.empty()) { + extraGenerator = cachedExtraGenerator; + } + + // check sourcedir: + const std::string cachedSourceDirectory = + std::string(state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY")); + if (!cachedSourceDirectory.empty() && !sourceDirectory.empty() && + cachedSourceDirectory != sourceDirectory) { + if (errorMessage) + *errorMessage = std::string("\"") + kSOURCE_DIRECTORY_KEY + + "\" is set but incompatible with configured source directory."; + return false; + } + if (sourceDirectory.empty()) { + sourceDirectory = cachedSourceDirectory; + } + } + } + + if (sourceDirectory.empty()) { + if (errorMessage) + *errorMessage = std::string("\"") + kSOURCE_DIRECTORY_KEY + + "\" is unset but required."; + return false; + } + if (!cmSystemTools::FileIsDirectory(sourceDirectory)) { + if (errorMessage) + *errorMessage = + std::string("\"") + kSOURCE_DIRECTORY_KEY + "\" is not a directory."; + return false; + } + if (generator.empty()) { + if (errorMessage) + *errorMessage = + std::string("\"") + kGENERATOR_KEY + "\" is unset but required."; + return false; + } + + const std::string fullGeneratorName = + cmExternalMakefileProjectGenerator::CreateFullGeneratorName( + generator, extraGenerator); + + cmGlobalGenerator* gg = cm->CreateGlobalGenerator(fullGeneratorName); + if (!gg) { + if (errorMessage) + *errorMessage = + std::string("Could not set up the requested combination of \"") + + kGENERATOR_KEY + "\" and \"" + kEXTRA_GENERATOR_KEY + "\""; + return false; + } + + cm->SetGlobalGenerator(gg); + cm->SetHomeDirectory(sourceDirectory); + cm->SetHomeOutputDirectory(buildDirectory); + + this->m_State = STATE_ACTIVE; + return true; +} + +const cmServerResponse cmServerProtocol1_0::Process( + const cmServerRequest& request) +{ + assert(this->m_State >= STATE_ACTIVE); + + return request.ReportError("Unknown command!"); +} diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h index e086f7252..33183e973 100644 --- a/Source/cmServerProtocol.h +++ b/Source/cmServerProtocol.h @@ -95,3 +95,21 @@ protected: private: std::unique_ptr m_CMakeInstance; }; + +class cmServerProtocol1_0 : public cmServerProtocol +{ +public: + std::pair ProtocolVersion() const override; + const cmServerResponse Process(const cmServerRequest& request) override; + +private: + bool DoActivate(const cmServerRequest& request, + std::string* errorMessage) override; + + enum State + { + STATE_INACTIVE, + STATE_ACTIVE + }; + State m_State = STATE_INACTIVE; +};