|  | @@ -3,9 +3,13 @@
 | 
	
		
			
				|  |  |  #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"
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -16,6 +20,49 @@
 | 
	
		
			
				|  |  |  #include "cm_jsoncpp_value.h"
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#include <algorithm>
 | 
	
		
			
				|  |  | +#include <string>
 | 
	
		
			
				|  |  | +#include <vector>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// Get rid of some windows macros:
 | 
	
		
			
				|  |  | +#undef max
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +namespace {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +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;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +} // namespace
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  cmServerRequest::cmServerRequest(cmServer* server, const std::string& t,
 | 
	
		
			
				|  |  |                                   const std::string& c, const Json::Value& d)
 | 
	
		
			
				|  |  |    : Type(t)
 | 
	
	
		
			
				|  | @@ -270,6 +317,9 @@ const cmServerResponse cmServerProtocol1_0::Process(
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    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);
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -291,6 +341,342 @@ 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 std
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static 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)
 | 
	
		
			
				|  |  |  {
 |