Browse Source

server-mode: Add a configure command

Add a command to trigger cmake to configure a project.

Keep this separate from the compute step (added in the next commit)
to faciliate applications like cmake-gui.
Tobias Hunger 9 years ago
parent
commit
0a8ad6700e

+ 27 - 0
Help/manual/cmake-server.7.rst

@@ -328,3 +328,30 @@ CMake will reply to this with::
   [== CMake Server ==[
   {"inReplyTo":"setGlobalSettings","type":"reply"}
   ]== CMake Server ==]
+
+
+Type "configure"
+^^^^^^^^^^^^^^^^
+
+This request will configure a project for build.
+
+To configure a build directory already containing cmake files, it is enough to
+set "buildDirectory" via "setGlobalSettings". To create a fresh build directory
+you also need to set "currentGenerator" and "sourceDirectory" via "setGlobalSettings"
+in addition to "buildDirectory".
+
+You may a list of strings to "configure" via the "cacheArguments" key. These
+strings will be interpreted similar to command line arguments related to
+cache handling that are passed to the cmake command line client.
+
+Example::
+
+  [== CMake Server ==[
+  {"type":"configure", "cacheArguments":["-Dsomething=else"]}
+  ]== CMake Server ==]
+
+CMake will reply like this (after reporting progress for some time)::
+
+  [== CMake Server ==[
+  {"cookie":"","inReplyTo":"configure","type":"reply"}
+  ]== CMake Server ==]

+ 2 - 0
Source/cmServerDictionary.h

@@ -16,6 +16,7 @@
 
 // Vocabulary:
 
+static const std::string kCONFIGURE_TYPE = "configure";
 static const std::string kERROR_TYPE = "error";
 static const std::string kGLOBAL_SETTINGS_TYPE = "globalSettings";
 static const std::string kHANDSHAKE_TYPE = "handshake";
@@ -26,6 +27,7 @@ static const std::string kSET_GLOBAL_SETTINGS_TYPE = "setGlobalSettings";
 static const std::string kSIGNAL_TYPE = "signal";
 
 static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory";
+static const std::string kCACHE_ARGUMENTS_KEY = "cacheArguments";
 static const std::string kCAPABILITIES_KEY = "capabilities";
 static const std::string kCHECK_SYSTEM_VARS_KEY = "checkSystemVars";
 static const std::string kCOOKIE_KEY = "cookie";

+ 89 - 0
Source/cmServerProtocol.cxx

@@ -280,6 +280,9 @@ const cmServerResponse cmServerProtocol1_0::Process(
 {
   assert(this->m_State >= STATE_ACTIVE);
 
+  if (request.Type == kCONFIGURE_TYPE) {
+    return this->ProcessConfigure(request);
+  }
   if (request.Type == kGLOBAL_SETTINGS_TYPE) {
     return this->ProcessGlobalSettings(request);
   }
@@ -295,6 +298,92 @@ bool cmServerProtocol1_0::IsExperimental() const
   return true;
 }
 
+cmServerResponse cmServerProtocol1_0::ProcessConfigure(
+  const cmServerRequest& request)
+{
+  if (this->m_State == STATE_INACTIVE) {
+    return request.ReportError("This instance is inactive.");
+  }
+
+  // Make sure the types of cacheArguments matches (if given):
+  std::vector<std::string> cacheArgs;
+  bool cacheArgumentsError = false;
+  const Json::Value passedArgs = request.Data[kCACHE_ARGUMENTS_KEY];
+  if (!passedArgs.isNull()) {
+    if (passedArgs.isString()) {
+      cacheArgs.push_back(passedArgs.asString());
+    } else if (passedArgs.isArray()) {
+      for (auto i = passedArgs.begin(); i != passedArgs.end(); ++i) {
+        if (!i->isString()) {
+          cacheArgumentsError = true;
+          break;
+        }
+        cacheArgs.push_back(i->asString());
+      }
+    } else {
+      cacheArgumentsError = true;
+    }
+  }
+  if (cacheArgumentsError) {
+    request.ReportError(
+      "cacheArguments must be unset, a string or an array of strings.");
+  }
+
+  cmake* cm = this->CMakeInstance();
+  std::string sourceDir = cm->GetHomeDirectory();
+  const std::string buildDir = cm->GetHomeOutputDirectory();
+
+  if (buildDir.empty()) {
+    return request.ReportError(
+      "No build directory set via setGlobalSettings.");
+  }
+
+  if (cm->LoadCache(buildDir)) {
+    // build directory has been set up before
+    const char* cachedSourceDir =
+      cm->GetState()->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY");
+    if (!cachedSourceDir) {
+      return request.ReportError("No CMAKE_HOME_DIRECTORY found in cache.");
+    }
+    if (sourceDir.empty()) {
+      sourceDir = std::string(cachedSourceDir);
+      cm->SetHomeDirectory(sourceDir);
+    }
+
+    const char* cachedGenerator =
+      cm->GetState()->GetInitializedCacheValue("CMAKE_GENERATOR");
+    if (cachedGenerator) {
+      cmGlobalGenerator* gen = cm->GetGlobalGenerator();
+      if (gen && gen->GetName() != cachedGenerator) {
+        return request.ReportError("Configured generator does not match with "
+                                   "CMAKE_GENERATOR found in cache.");
+      }
+    }
+  } else {
+    // build directory has not been set up before
+    if (sourceDir.empty()) {
+      return request.ReportError("No sourceDirectory set via "
+                                 "setGlobalSettings and no cache found in "
+                                 "buildDirectory.");
+    }
+  }
+
+  if (cm->AddCMakePaths() != 1) {
+    return request.ReportError("Failed to set CMake paths.");
+  }
+
+  if (!cm->SetCacheArgs(cacheArgs)) {
+    return request.ReportError("cacheArguments could not be set.");
+  }
+
+  int ret = cm->Configure();
+  if (ret < 0) {
+    return request.ReportError("Configuration failed.");
+  }
+  m_State = STATE_CONFIGURED;
+  return request.Reply(Json::Value());
+}
+
 cmServerResponse cmServerProtocol1_0::ProcessGlobalSettings(
   const cmServerRequest& request)
 {

+ 3 - 1
Source/cmServerProtocol.h

@@ -118,13 +118,15 @@ private:
                   std::string* errorMessage) override;
 
   // Handle requests:
+  cmServerResponse ProcessConfigure(const cmServerRequest& request);
   cmServerResponse ProcessGlobalSettings(const cmServerRequest& request);
   cmServerResponse ProcessSetGlobalSettings(const cmServerRequest& request);
 
   enum State
   {
     STATE_INACTIVE,
-    STATE_ACTIVE
+    STATE_ACTIVE,
+    STATE_CONFIGURED
   };
   State m_State = STATE_INACTIVE;
 };