| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854 | /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying   file Copyright.txt or https://cmake.org/licensing for details.  */#include "cmServerProtocol.h"#include "cmExternalMakefileProjectGenerator.h"#include "cmGeneratorTarget.h"#include "cmGlobalGenerator.h"#include "cmLocalGenerator.h"#include "cmMakefile.h"#include "cmServer.h"#include "cmServerDictionary.h"#include "cmSourceFile.h"#include "cmSystemTools.h"#include "cmake.h"#include "cmServerDictionary.h"#if defined(CMAKE_BUILD_WITH_CMAKE)#include "cm_jsoncpp_reader.h"#include "cm_jsoncpp_value.h"#endif#include <algorithm>#include <string>#include <vector>// Get rid of some windows macros:#undef maxnamespace {static std::vector<std::string> getConfigurations(const cmake* cm){  std::vector<std::string> configurations;  auto makefiles = cm->GetGlobalGenerator()->GetMakefiles();  if (makefiles.empty()) {    return configurations;  }  makefiles[0]->GetConfigurations(configurations);  if (configurations.empty())    configurations.push_back("");  return configurations;}static bool hasString(const Json::Value& v, const std::string& s){  return !v.isNull() &&    std::find_if(v.begin(), v.end(), [s](const Json::Value& i) {      return i.asString() == s;    }) != v.end();}template <class T>static Json::Value fromStringList(const T& in){  Json::Value result = Json::arrayValue;  for (const std::string& i : in) {    result.append(i);  }  return result;}} // namespacecmServerRequest::cmServerRequest(cmServer* server, const std::string& t,                                 const std::string& c, const Json::Value& d)  : Type(t)  , Cookie(c)  , Data(d)  , m_Server(server){}void cmServerRequest::ReportProgress(int min, int current, int max,                                     const std::string& message) const{  this->m_Server->WriteProgress(*this, min, current, max, message);}void cmServerRequest::ReportMessage(const std::string& message,                                    const std::string& title) const{  m_Server->WriteMessage(*this, message, title);}cmServerResponse cmServerRequest::Reply(const Json::Value& data) const{  cmServerResponse response(*this);  response.SetData(data);  return response;}cmServerResponse cmServerRequest::ReportError(const std::string& message) const{  cmServerResponse response(*this);  response.SetError(message);  return response;}cmServerResponse::cmServerResponse(const cmServerRequest& request)  : Type(request.Type)  , Cookie(request.Cookie){}void cmServerResponse::SetData(const Json::Value& data){  assert(this->m_Payload == PAYLOAD_UNKNOWN);  if (!data[kCOOKIE_KEY].isNull() || !data[kTYPE_KEY].isNull()) {    this->SetError("Response contains cookie or type field.");    return;  }  this->m_Payload = PAYLOAD_DATA;  this->m_Data = data;}void cmServerResponse::SetError(const std::string& message){  assert(this->m_Payload == PAYLOAD_UNKNOWN);  this->m_Payload = PAYLOAD_ERROR;  this->m_ErrorMessage = message;}bool cmServerResponse::IsComplete() const{  return this->m_Payload != PAYLOAD_UNKNOWN;}bool cmServerResponse::IsError() const{  assert(this->m_Payload != PAYLOAD_UNKNOWN);  return this->m_Payload == PAYLOAD_ERROR;}std::string cmServerResponse::ErrorMessage() const{  if (this->m_Payload == PAYLOAD_ERROR) {    return this->m_ErrorMessage;  }  return std::string();}Json::Value cmServerResponse::Data() const{  assert(this->m_Payload != PAYLOAD_UNKNOWN);  return this->m_Data;}bool cmServerProtocol::Activate(cmServer* server,                                const cmServerRequest& request,                                std::string* errorMessage){  assert(server);  this->m_Server = server;  this->m_CMakeInstance = std::make_unique<cmake>();  const bool result = this->DoActivate(request, errorMessage);  if (!result) {    this->m_CMakeInstance = CM_NULLPTR;  }  return result;}void cmServerProtocol::SendSignal(const std::string& name,                                  const Json::Value& data) const{  if (this->m_Server) {    this->m_Server->WriteSignal(name, data);  }}cmake* cmServerProtocol::CMakeInstance() const{  return this->m_CMakeInstance.get();}bool cmServerProtocol::DoActivate(const cmServerRequest& /*request*/,                                  std::string* /*errorMessage*/){  return true;}std::pair<int, int> 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);  if (request.Type == kCODE_MODEL_TYPE) {    return this->ProcessCodeModel(request);  }  if (request.Type == kCOMPUTE_TYPE) {    return this->ProcessCompute(request);  }  if (request.Type == kCONFIGURE_TYPE) {    return this->ProcessConfigure(request);  }  if (request.Type == kGLOBAL_SETTINGS_TYPE) {    return this->ProcessGlobalSettings(request);  }  if (request.Type == kSET_GLOBAL_SETTINGS_TYPE) {    return this->ProcessSetGlobalSettings(request);  }  return request.ReportError("Unknown command!");}bool cmServerProtocol1_0::IsExperimental() const{  return true;}class LanguageData{public:  bool operator==(const LanguageData& other) const;  void SetDefines(const std::set<std::string>& defines);  bool IsGenerated = false;  std::string Language;  std::string Flags;  std::vector<std::string> Defines;  std::vector<std::pair<std::string, bool> > IncludePathList;};bool LanguageData::operator==(const LanguageData& other) const{  return Language == other.Language && Defines == other.Defines &&    Flags == other.Flags && IncludePathList == other.IncludePathList &&    IsGenerated == other.IsGenerated;}void LanguageData::SetDefines(const std::set<std::string>& defines){  std::vector<std::string> result;  for (auto i : defines) {    result.push_back(i);  }  std::sort(result.begin(), result.end());  Defines = result;}namespace std {template <>struct hash<LanguageData>{  std::size_t operator()(const LanguageData& in) const  {    using std::hash;    size_t result =      hash<std::string>()(in.Language) ^ hash<std::string>()(in.Flags);    for (auto i : in.IncludePathList) {      result = result ^ (hash<std::string>()(i.first) ^                         (i.second ? std::numeric_limits<size_t>::max() : 0));    }    for (auto i : in.Defines) {      result = result ^ hash<std::string>()(i);    }    result =      result ^ (in.IsGenerated ? std::numeric_limits<size_t>::max() : 0);    return result;  }};} // namespace stdstatic Json::Value DumpSourceFileGroup(const LanguageData& data,                                       const std::vector<std::string>& files,                                       const std::string& baseDir){  Json::Value result = Json::objectValue;  if (!data.Language.empty()) {    result[kLANGUAGE_KEY] = data.Language;    if (!data.Flags.empty()) {      result[kCOMPILE_FLAGS_KEY] = data.Flags;    }    if (!data.IncludePathList.empty()) {      Json::Value includes = Json::arrayValue;      for (auto i : data.IncludePathList) {        Json::Value tmp = Json::objectValue;        tmp[kPATH_KEY] = i.first;        if (i.second) {          tmp[kIS_SYSTEM_KEY] = i.second;        }        includes.append(tmp);      }      result[kINCLUDE_PATH_KEY] = includes;    }    if (!data.Defines.empty()) {      result[kDEFINES_KEY] = fromStringList(data.Defines);    }  }  result[kIS_GENERATED_KEY] = data.IsGenerated;  Json::Value sourcesValue = Json::arrayValue;  for (auto i : files) {    const std::string relPath =      cmSystemTools::RelativePath(baseDir.c_str(), i.c_str());    sourcesValue.append(relPath.size() < i.size() ? relPath : i);  }  result[kSOURCES_KEY] = sourcesValue;  return result;}static Json::Value DumpSourceFilesList(  cmGeneratorTarget* target, const std::string& config,  const std::map<std::string, LanguageData>& languageDataMap){  // Collect sourcefile groups:  std::vector<cmSourceFile*> files;  target->GetSourceFiles(files, config);  std::unordered_map<LanguageData, std::vector<std::string> > fileGroups;  for (cmSourceFile* file : files) {    LanguageData fileData;    fileData.Language = file->GetLanguage();    if (!fileData.Language.empty()) {      const LanguageData& ld = languageDataMap.at(fileData.Language);      cmLocalGenerator* lg = target->GetLocalGenerator();      std::string compileFlags = ld.Flags;      lg->AppendFlags(compileFlags, file->GetProperty("COMPILE_FLAGS"));      fileData.Flags = compileFlags;      fileData.IncludePathList = ld.IncludePathList;      std::set<std::string> defines;      lg->AppendDefines(defines, file->GetProperty("COMPILE_DEFINITIONS"));      const std::string defPropName =        "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);      lg->AppendDefines(defines, file->GetProperty(defPropName));      defines.insert(ld.Defines.begin(), ld.Defines.end());      fileData.SetDefines(defines);    }    fileData.IsGenerated = file->GetPropertyAsBool("GENERATED");    std::vector<std::string>& groupFileList = fileGroups[fileData];    groupFileList.push_back(file->GetFullPath());  }  const std::string baseDir = target->Makefile->GetCurrentSourceDirectory();  Json::Value result = Json::arrayValue;  for (auto it = fileGroups.begin(); it != fileGroups.end(); ++it) {    Json::Value group = DumpSourceFileGroup(it->first, it->second, baseDir);    if (!group.isNull())      result.append(group);  }  return result;}static Json::Value DumpTarget(cmGeneratorTarget* target,                              const std::string& config){  cmLocalGenerator* lg = target->GetLocalGenerator();  const cmState* state = lg->GetState();  const cmState::TargetType type = target->GetType();  const std::string typeName = state->GetTargetTypeName(type);  Json::Value ttl = Json::arrayValue;  ttl.append("EXECUTABLE");  ttl.append("STATIC_LIBRARY");  ttl.append("SHARED_LIBRARY");  ttl.append("MODULE_LIBRARY");  ttl.append("OBJECT_LIBRARY");  ttl.append("UTILITY");  ttl.append("INTERFACE_LIBRARY");  if (!hasString(ttl, typeName) || target->IsImported()) {    return Json::Value();  }  Json::Value result = Json::objectValue;  result[kNAME_KEY] = target->GetName();  result[kTYPE_KEY] = typeName;  result[kFULL_NAME_KEY] = target->GetFullName(config);  result[kSOURCE_DIRECTORY_KEY] = lg->GetCurrentSourceDirectory();  result[kBUILD_DIRECTORY_KEY] = lg->GetCurrentBinaryDirectory();  if (target->HaveWellDefinedOutputFiles()) {    Json::Value artifacts = Json::arrayValue;    artifacts.append(target->GetFullPath(config, false));    if (target->IsDLLPlatform()) {      artifacts.append(target->GetFullPath(config, true));      const cmGeneratorTarget::OutputInfo* output =        target->GetOutputInfo(config);      if (output && !output->PdbDir.empty()) {        artifacts.append(output->PdbDir + '/' + target->GetPDBName(config));      }    }    result[kARTIFACTS_KEY] = artifacts;    result[kLINKER_LANGUAGE_KEY] = target->GetLinkerLanguage(config);    std::string linkLibs;    std::string linkFlags;    std::string linkLanguageFlags;    std::string frameworkPath;    std::string linkPath;    lg->GetTargetFlags(config, linkLibs, linkLanguageFlags, linkFlags,                       frameworkPath, linkPath, target, false);    linkLibs = cmSystemTools::TrimWhitespace(linkLibs);    linkFlags = cmSystemTools::TrimWhitespace(linkFlags);    linkLanguageFlags = cmSystemTools::TrimWhitespace(linkLanguageFlags);    frameworkPath = cmSystemTools::TrimWhitespace(frameworkPath);    linkPath = cmSystemTools::TrimWhitespace(linkPath);    if (!cmSystemTools::TrimWhitespace(linkLibs).empty()) {      result[kLINK_LIBRARIES_KEY] = linkLibs;    }    if (!cmSystemTools::TrimWhitespace(linkFlags).empty()) {      result[kLINK_FLAGS_KEY] = linkFlags;    }    if (!cmSystemTools::TrimWhitespace(linkLanguageFlags).empty()) {      result[kLINK_LANGUAGE_FLAGS_KEY] = linkLanguageFlags;    }    if (!frameworkPath.empty()) {      result[kFRAMEWORK_PATH_KEY] = frameworkPath;    }    if (!linkPath.empty()) {      result[kLINK_PATH_KEY] = linkPath;    }    const std::string sysroot =      lg->GetMakefile()->GetSafeDefinition("CMAKE_SYSROOT");    if (!sysroot.empty()) {      result[kSYSROOT_KEY] = sysroot;    }  }  std::set<std::string> languages;  target->GetLanguages(languages, config);  std::map<std::string, LanguageData> languageDataMap;  for (auto lang : languages) {    LanguageData& ld = languageDataMap[lang];    ld.Language = lang;    lg->GetTargetCompileFlags(target, config, lang, ld.Flags);    std::set<std::string> defines;    lg->GetTargetDefines(target, config, lang, defines);    ld.SetDefines(defines);    std::vector<std::string> includePathList;    lg->GetIncludeDirectories(includePathList, target, lang, config, true);    for (auto i : includePathList) {      ld.IncludePathList.push_back(        std::make_pair(i, target->IsSystemIncludeDirectory(i, config)));    }  }  Json::Value sourceGroupsValue =    DumpSourceFilesList(target, config, languageDataMap);  if (!sourceGroupsValue.empty()) {    result[kFILE_GROUPS_KEY] = sourceGroupsValue;  }  return result;}static Json::Value DumpTargetsList(  const std::vector<cmLocalGenerator*>& generators, const std::string& config){  Json::Value result = Json::arrayValue;  std::vector<cmGeneratorTarget*> targetList;  for (const auto& lgIt : generators) {    auto list = lgIt->GetGeneratorTargets();    targetList.insert(targetList.end(), list.begin(), list.end());  }  std::sort(targetList.begin(), targetList.end());  for (cmGeneratorTarget* target : targetList) {    Json::Value tmp = DumpTarget(target, config);    if (!tmp.isNull()) {      result.append(tmp);    }  }  return result;}static Json::Value DumpProjectList(const cmake* cm, const std::string config){  Json::Value result = Json::arrayValue;  auto globalGen = cm->GetGlobalGenerator();  for (const auto& projectIt : globalGen->GetProjectMap()) {    Json::Value pObj = Json::objectValue;    pObj[kNAME_KEY] = projectIt.first;    assert(projectIt.second.size() >           0); // All Projects must have at least one local generator    const cmLocalGenerator* lg = projectIt.second.at(0);    // Project structure information:    const cmMakefile* mf = lg->GetMakefile();    pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory();    pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory();    pObj[kTARGETS_KEY] = DumpTargetsList(projectIt.second, config);    result.append(pObj);  }  return result;}static Json::Value DumpConfiguration(const cmake* cm,                                     const std::string& config){  Json::Value result = Json::objectValue;  result[kNAME_KEY] = config;  result[kPROJECTS_KEY] = DumpProjectList(cm, config);  return result;}static Json::Value DumpConfigurationsList(const cmake* cm){  Json::Value result = Json::arrayValue;  for (const std::string& c : getConfigurations(cm)) {    result.append(DumpConfiguration(cm, c));  }  return result;}cmServerResponse cmServerProtocol1_0::ProcessCodeModel(  const cmServerRequest& request){  if (this->m_State != STATE_COMPUTED) {    return request.ReportError("No build system was generated yet.");  }  Json::Value result = Json::objectValue;  result[kCONFIGURATIONS_KEY] = DumpConfigurationsList(this->CMakeInstance());  return request.Reply(result);}cmServerResponse cmServerProtocol1_0::ProcessCompute(  const cmServerRequest& request){  if (this->m_State > STATE_CONFIGURED) {    return request.ReportError("This build system was already generated.");  }  if (this->m_State < STATE_CONFIGURED) {    return request.ReportError("This project was not configured yet.");  }  cmake* cm = this->CMakeInstance();  int ret = cm->Generate();  if (ret < 0) {    return request.ReportError("Failed to compute build system.");  }  m_State = STATE_COMPUTED;  return request.Reply(Json::Value());}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){  cmake* cm = this->CMakeInstance();  Json::Value obj = Json::objectValue;  // Capabilities information:  obj[kCAPABILITIES_KEY] = cm->ReportCapabilitiesJson(true);  obj[kDEBUG_OUTPUT_KEY] = cm->GetDebugOutput();  obj[kTRACE_KEY] = cm->GetTrace();  obj[kTRACE_EXPAND_KEY] = cm->GetTraceExpand();  obj[kWARN_UNINITIALIZED_KEY] = cm->GetWarnUninitialized();  obj[kWARN_UNUSED_KEY] = cm->GetWarnUnused();  obj[kWARN_UNUSED_CLI_KEY] = cm->GetWarnUnusedCli();  obj[kCHECK_SYSTEM_VARS_KEY] = cm->GetCheckSystemVars();  obj[kSOURCE_DIRECTORY_KEY] = cm->GetHomeDirectory();  obj[kBUILD_DIRECTORY_KEY] = cm->GetHomeOutputDirectory();  // Currently used generator:  cmGlobalGenerator* gen = cm->GetGlobalGenerator();  obj[kGENERATOR_KEY] = gen ? gen->GetName() : std::string();  obj[kEXTRA_GENERATOR_KEY] =    gen ? gen->GetExtraGeneratorName() : std::string();  return request.Reply(obj);}static void setBool(const cmServerRequest& request, const std::string& key,                    std::function<void(bool)> setter){  if (request.Data[key].isNull()) {    return;  }  setter(request.Data[key].asBool());}cmServerResponse cmServerProtocol1_0::ProcessSetGlobalSettings(  const cmServerRequest& request){  const std::vector<std::string> boolValues = {    kDEBUG_OUTPUT_KEY,       kTRACE_KEY,       kTRACE_EXPAND_KEY,    kWARN_UNINITIALIZED_KEY, kWARN_UNUSED_KEY, kWARN_UNUSED_CLI_KEY,    kCHECK_SYSTEM_VARS_KEY  };  for (auto i : boolValues) {    if (!request.Data[i].isNull() && !request.Data[i].isBool()) {      return request.ReportError("\"" + i +                                 "\" must be unset or a bool value.");    }  }  cmake* cm = this->CMakeInstance();  setBool(request, kDEBUG_OUTPUT_KEY,          [cm](bool e) { cm->SetDebugOutputOn(e); });  setBool(request, kTRACE_KEY, [cm](bool e) { cm->SetTrace(e); });  setBool(request, kTRACE_EXPAND_KEY, [cm](bool e) { cm->SetTraceExpand(e); });  setBool(request, kWARN_UNINITIALIZED_KEY,          [cm](bool e) { cm->SetWarnUninitialized(e); });  setBool(request, kWARN_UNUSED_KEY, [cm](bool e) { cm->SetWarnUnused(e); });  setBool(request, kWARN_UNUSED_CLI_KEY,          [cm](bool e) { cm->SetWarnUnusedCli(e); });  setBool(request, kCHECK_SYSTEM_VARS_KEY,          [cm](bool e) { cm->SetCheckSystemVars(e); });  return request.Reply(Json::Value());}
 |