From 84553a6e709ea810f3e7fc5ece5daa1c53be5cda Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Fri, 9 Sep 2016 10:01:46 +0200 Subject: [PATCH] server-mode: Add command to retrieve build system files Add a command to retrieve files that are input to cmake itself. --- Help/manual/cmake-server.7.rst | 41 ++++++++++++++ Source/cmServerDictionary.h | 5 ++ Source/cmServerProtocol.cxx | 99 +++++++++++++++++++++++++++++++++- Source/cmServerProtocol.h | 1 + 4 files changed, 144 insertions(+), 2 deletions(-) diff --git a/Help/manual/cmake-server.7.rst b/Help/manual/cmake-server.7.rst index 79b67b012f..76ee3fb914 100644 --- a/Help/manual/cmake-server.7.rst +++ b/Help/manual/cmake-server.7.rst @@ -558,3 +558,44 @@ listed by default. Finally you can limit the target types that are going to be listed. This is done by providing a list of target types as an array of strings to the "targetTypes" key. + + +Type "cmakeInputs" +^^^^^^^^^^^^^^^^^^ + +The "cmakeInputs" requests will report files used by CMake as part +of the build system itself. + +This request is only available after a project was successfully +"configure"d. + +Example:: + + [== CMake Server ==[ + {"type":"cmakeInputs"} + ]== CMake Server ==] + +CMake will reply with the following information:: + + [== CMake Server ==[ + {"buildFiles": + [ + {"isCMake":true,"isTemporary":false,"sources":["/usr/lib/cmake/...", ... ]}, + {"isCMake":false,"isTemporary":false,"sources":["CMakeLists.txt", ...]}, + {"isCMake":false,"isTemporary":true,"sources":["/tmp/build/CMakeFiles/...", ...]} + ], + "cmakeRootDirectory":"/usr/lib/cmake", + "sourceDirectory":"/home/code/src/cmake", + "cookie":"", + "inReplyTo":"cmakeInputs", + "type":"reply" + } + ]== CMake Server ==] + +All file names are either relative to the top level source directory or +absolute. + +The list of files which "isCMake" set to true are part of the cmake installation. + +The list of files witch "isTemporary" set to true are part of the build directory +and will not survive the build directory getting cleaned out. diff --git a/Source/cmServerDictionary.h b/Source/cmServerDictionary.h index 9e838648a5..bccce550ba 100644 --- a/Source/cmServerDictionary.h +++ b/Source/cmServerDictionary.h @@ -6,6 +6,7 @@ // Vocabulary: +static const std::string kCMAKE_INPUTS_TYPE = "cmakeInputs"; static const std::string kCODE_MODEL_TYPE = "codemodel"; static const std::string kCOMPUTE_TYPE = "compute"; static const std::string kCONFIGURE_TYPE = "configure"; @@ -20,9 +21,11 @@ static const std::string kSIGNAL_TYPE = "signal"; static const std::string kARTIFACTS_KEY = "artifacts"; static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory"; +static const std::string kBUILD_FILES_KEY = "buildFiles"; 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 kCMAKE_ROOT_DIRECTORY_KEY = "cmakeRootDirectory"; static const std::string kCOMPILE_FLAGS_KEY = "compileFlags"; static const std::string kCONFIGURATIONS_KEY = "configurations"; static const std::string kCOOKIE_KEY = "cookie"; @@ -35,9 +38,11 @@ static const std::string kFRAMEWORK_PATH_KEY = "frameworkPath"; static const std::string kFULL_NAME_KEY = "fullName"; static const std::string kGENERATOR_KEY = "generator"; static const std::string kINCLUDE_PATH_KEY = "includePath"; +static const std::string kIS_CMAKE_KEY = "isCMake"; static const std::string kIS_EXPERIMENTAL_KEY = "isExperimental"; static const std::string kIS_GENERATED_KEY = "isGenerated"; static const std::string kIS_SYSTEM_KEY = "isSystem"; +static const std::string kIS_TEMPORARY_KEY = "isTemporary"; static const std::string kLANGUAGE_KEY = "language"; static const std::string kLINKER_LANGUAGE_KEY = "linkerLanguage"; static const std::string kLINK_FLAGS_KEY = "linkFlags"; diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index c2eeee0719..00a8135797 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -5,6 +5,7 @@ #include "cmExternalMakefileProjectGenerator.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmServer.h" @@ -61,6 +62,48 @@ static Json::Value fromStringList(const T& in) return result; } +static void getCMakeInputs(const cmGlobalGenerator* gg, + const std::string& sourceDir, + const std::string& buildDir, + std::vector* internalFiles, + std::vector* explicitFiles, + std::vector* tmpFiles) +{ + const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot() + '/'; + const std::vector makefiles = gg->GetMakefiles(); + for (auto it = makefiles.begin(); it != makefiles.end(); ++it) { + const std::vector listFiles = (*it)->GetListFiles(); + + for (auto jt = listFiles.begin(); jt != listFiles.end(); ++jt) { + + const std::string startOfFile = jt->substr(0, cmakeRootDir.size()); + const bool isInternal = (startOfFile == cmakeRootDir); + const bool isTemporary = !isInternal && (jt->find(buildDir + '/') == 0); + + std::string toAdd = *jt; + if (!sourceDir.empty()) { + const std::string& relative = + cmSystemTools::RelativePath(sourceDir.c_str(), jt->c_str()); + if (toAdd.size() > relative.size()) + toAdd = relative; + } + + if (isInternal) { + if (internalFiles) + internalFiles->push_back(toAdd); + } else { + if (isTemporary) { + if (tmpFiles) + tmpFiles->push_back(toAdd); + } else { + if (explicitFiles) + explicitFiles->push_back(toAdd); + } + } + } + } +} + } // namespace cmServerRequest::cmServerRequest(cmServer* server, const std::string& t, @@ -317,6 +360,9 @@ const cmServerResponse cmServerProtocol1_0::Process( { assert(this->m_State >= STATE_ACTIVE); + if (request.Type == kCMAKE_INPUTS_TYPE) { + return this->ProcessCMakeInputs(request); + } if (request.Type == kCODE_MODEL_TYPE) { return this->ProcessCodeModel(request); } @@ -341,6 +387,54 @@ bool cmServerProtocol1_0::IsExperimental() const return true; } +cmServerResponse cmServerProtocol1_0::ProcessCMakeInputs( + const cmServerRequest& request) +{ + if (this->m_State < STATE_CONFIGURED) { + return request.ReportError("This instance was not yet configured."); + } + + const cmake* cm = this->CMakeInstance(); + const cmGlobalGenerator* gg = cm->GetGlobalGenerator(); + const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot(); + const std::string buildDir = cm->GetHomeOutputDirectory(); + const std::string sourceDir = cm->GetHomeDirectory(); + + Json::Value result = Json::objectValue; + result[kSOURCE_DIRECTORY_KEY] = sourceDir; + result[kCMAKE_ROOT_DIRECTORY_KEY] = cmakeRootDir; + + std::vector internalFiles; + std::vector explicitFiles; + std::vector tmpFiles; + getCMakeInputs(gg, sourceDir, buildDir, &internalFiles, &explicitFiles, + &tmpFiles); + + Json::Value array = Json::arrayValue; + + Json::Value tmp = Json::objectValue; + tmp[kIS_CMAKE_KEY] = true; + tmp[kIS_TEMPORARY_KEY] = false; + tmp[kSOURCES_KEY] = fromStringList(internalFiles); + array.append(tmp); + + tmp = Json::objectValue; + tmp[kIS_CMAKE_KEY] = false; + tmp[kIS_TEMPORARY_KEY] = false; + tmp[kSOURCES_KEY] = fromStringList(explicitFiles); + array.append(tmp); + + tmp = Json::objectValue; + tmp[kIS_CMAKE_KEY] = false; + tmp[kIS_TEMPORARY_KEY] = true; + tmp[kSOURCES_KEY] = fromStringList(tmpFiles); + array.append(tmp); + + result[kBUILD_FILES_KEY] = array; + + return request.Reply(result); +} + class LanguageData { public: @@ -732,6 +826,8 @@ cmServerResponse cmServerProtocol1_0::ProcessConfigure( std::string sourceDir = cm->GetHomeDirectory(); const std::string buildDir = cm->GetHomeOutputDirectory(); + cmGlobalGenerator* gg = cm->GetGlobalGenerator(); + if (buildDir.empty()) { return request.ReportError( "No build directory set via setGlobalSettings."); @@ -752,8 +848,7 @@ cmServerResponse cmServerProtocol1_0::ProcessConfigure( const char* cachedGenerator = cm->GetState()->GetInitializedCacheValue("CMAKE_GENERATOR"); if (cachedGenerator) { - cmGlobalGenerator* gen = cm->GetGlobalGenerator(); - if (gen && gen->GetName() != cachedGenerator) { + if (gg && gg->GetName() != cachedGenerator) { return request.ReportError("Configured generator does not match with " "CMAKE_GENERATOR found in cache."); } diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h index 193e0a35d9..2a6b1937cf 100644 --- a/Source/cmServerProtocol.h +++ b/Source/cmServerProtocol.h @@ -108,6 +108,7 @@ private: std::string* errorMessage) override; // Handle requests: + cmServerResponse ProcessCMakeInputs(const cmServerRequest& request); cmServerResponse ProcessCodeModel(const cmServerRequest& request); cmServerResponse ProcessCompute(const cmServerRequest& request); cmServerResponse ProcessConfigure(const cmServerRequest& request);