diff options
author | Brad King <brad.king@kitware.com> | 2018-11-13 14:34:10 (GMT) |
---|---|---|
committer | Kyle Edwards <kyle.edwards@kitware.com> | 2018-12-12 20:12:26 (GMT) |
commit | 4b6b2a571c39439f3b07d56f36e6a927ed6d1dd8 (patch) | |
tree | c0ee27f9e86aea592e750d4004c46f96b44d9df4 | |
parent | eb8c7676a4723a44245e47630f12d4868e8e182c (diff) | |
download | CMake-4b6b2a571c39439f3b07d56f36e6a927ed6d1dd8.zip CMake-4b6b2a571c39439f3b07d56f36e6a927ed6d1dd8.tar.gz CMake-4b6b2a571c39439f3b07d56f36e6a927ed6d1dd8.tar.bz2 |
fileapi: extend codemodel v2 with directory details
Issue: #18398
Co-Author: Kyle Edwards <kyle.edwards@kitware.com>
-rw-r--r-- | Help/manual/cmake-file-api.7.rst | 32 | ||||
-rw-r--r-- | Source/cmFileAPICodemodel.cxx | 50 | ||||
-rw-r--r-- | Tests/RunCMake/FileAPI/codemodel-v2-check.py | 26 |
3 files changed, 106 insertions, 2 deletions
diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst index f35e351..f3e0208 100644 --- a/Help/manual/cmake-file-api.7.rst +++ b/Help/manual/cmake-file-api.7.rst @@ -433,14 +433,21 @@ Version 1 does not exist to avoid confusion with that from "build": ".", "childIndexes": [ 1 ], "projectIndex": 0, - "targetIndexes": [ 0 ] + "targetIndexes": [ 0 ], + "hasInstallRule": true, + "minimumCMakeVersion": { + "string": "3.14" + } }, { "source": "sub", "build": "sub", "parentIndex": 0, "projectIndex": 0, - "targetIndexes": [ 1 ] + "targetIndexes": [ 1 ], + "minimumCMakeVersion": { + "string": "3.14" + } } ], "projects": [ @@ -535,6 +542,27 @@ The members specific to ``codemodel`` objects are: array of entries corresponding to the targets. Each entry is an unsigned integer 0-based index into the main ``targets`` array. + ``minimumCMakeVersion`` + Optional member present when a minimum required version of CMake is + known for the directory. This is the ``<min>`` version given to the + most local call to the :command:`cmake_minimum_required(VERSION)` + command in the directory itself or one of its ancestors. + The value is a JSON object with one member: + + ``string`` + A string specifying the minimum required version in the format:: + + <major>.<minor>[.<patch>[.<tweak>]][<suffix>] + + Each component is an unsigned integer and the suffix may be an + arbitrary string. + + ``hasInstallRule`` + Optional member that is present with boolean value ``true`` when + the directory or one of its subdirectories contains any + :command:`install` rules, i.e. whether a ``make install`` + or equivalent rule is available. + ``projects`` A JSON array of entries corresponding to the top-level project and sub-projects defined in the build system. Each (sub-)project diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index d432c1e..078d1d5 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -8,6 +8,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmInstallGenerator.h" +#include "cmInstallSubdirectoryGenerator.h" #include "cmInstallTargetGenerator.h" #include "cmLinkLineComputer.h" #include "cmListFileCache.h" @@ -62,8 +63,10 @@ class CodemodelConfig struct Directory { cmStateSnapshot Snapshot; + cmLocalGenerator const* LocalGenerator = nullptr; Json::Value TargetIndexes = Json::arrayValue; Json::ArrayIndex ProjectIndex; + bool HasInstallRule = false; }; std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder> DirectoryMap; @@ -99,6 +102,8 @@ class CodemodelConfig Json::Value DumpProjects(); Json::Value DumpProject(Project& p); + Json::Value DumpMinimumCMakeVersion(cmStateSnapshot s); + public: CodemodelConfig(cmFileAPI& fileAPI, unsigned long version, std::string const& config); @@ -396,11 +401,36 @@ void CodemodelConfig::ProcessDirectories() this->Directories.emplace_back(); Directory& d = this->Directories[directoryIndex]; d.Snapshot = lg->GetStateSnapshot().GetBuildsystemDirectory(); + d.LocalGenerator = lg; this->DirectoryMap[d.Snapshot] = directoryIndex; d.ProjectIndex = this->AddProject(d.Snapshot); this->Projects[d.ProjectIndex].DirectoryIndexes.append(directoryIndex); } + + // Update directories in reverse order to process children before parents. + for (auto di = this->Directories.rbegin(); di != this->Directories.rend(); + ++di) { + Directory& d = *di; + + // Accumulate the presence of install rules on the way up. + for (auto gen : d.LocalGenerator->GetMakefile()->GetInstallGenerators()) { + if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(gen)) { + d.HasInstallRule = true; + break; + } + } + if (!d.HasInstallRule) { + for (cmStateSnapshot const& child : d.Snapshot.GetChildren()) { + cmStateSnapshot childDir = child.GetBuildsystemDirectory(); + Json::ArrayIndex const childIndex = this->GetDirectoryIndex(childDir); + if (this->Directories[childIndex].HasInstallRule) { + d.HasInstallRule = true; + break; + } + } + } + } } Json::ArrayIndex CodemodelConfig::GetDirectoryIndex(cmLocalGenerator const* lg) @@ -531,6 +561,15 @@ Json::Value CodemodelConfig::DumpDirectory(Directory& d) directory["targetIndexes"] = std::move(d.TargetIndexes); } + Json::Value minimumCMakeVersion = this->DumpMinimumCMakeVersion(d.Snapshot); + if (!minimumCMakeVersion.isNull()) { + directory["minimumCMakeVersion"] = std::move(minimumCMakeVersion); + } + + if (d.HasInstallRule) { + directory["hasInstallRule"] = true; + } + return directory; } @@ -566,6 +605,17 @@ Json::Value CodemodelConfig::DumpProject(Project& p) return project; } +Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s) +{ + Json::Value minimumCMakeVersion; + if (std::string const* def = + s.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) { + minimumCMakeVersion = Json::objectValue; + minimumCMakeVersion["string"] = *def; + } + return minimumCMakeVersion; +} + Target::Target(cmGeneratorTarget* gt, std::string const& config) : GT(gt) , Config(config) diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index 8111c79..18b9347 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -64,6 +64,16 @@ def check_directory(c): missing_exception=lambda e: "Target ID: %s" % e, extra_exception=lambda a: "Target ID: %s" % c["targets"][a]["id"]) + if expected["minimumCMakeVersion"] is not None: + expected_keys.append("minimumCMakeVersion") + assert is_dict(actual["minimumCMakeVersion"]) + assert sorted(actual["minimumCMakeVersion"].keys()) == ["string"] + assert is_string(actual["minimumCMakeVersion"]["string"], expected["minimumCMakeVersion"]) + + if expected["hasInstallRule"] is not None: + expected_keys.append("hasInstallRule") + assert is_bool(actual["hasInstallRule"], expected["hasInstallRule"]) + assert sorted(actual.keys()) == sorted(expected_keys) return _check @@ -448,6 +458,8 @@ def gen_check_directories(c, g): "^interface_exe::@6890427a1f51a3e7e1df$", ], "projectName": "codemodel-v2", + "minimumCMakeVersion": "3.12", + "hasInstallRule": True, }, { "source": "^alias$", @@ -461,6 +473,8 @@ def gen_check_directories(c, g): "^cxx_alias_exe::@53632cba2752272bb008$", ], "projectName": "Alias", + "minimumCMakeVersion": "3.12", + "hasInstallRule": None, }, { "source": "^custom$", @@ -474,6 +488,8 @@ def gen_check_directories(c, g): "^custom_tgt::@c11385ffed57b860da63$", ], "projectName": "Custom", + "minimumCMakeVersion": "3.12", + "hasInstallRule": None, }, { "source": "^cxx$", @@ -491,6 +507,8 @@ def gen_check_directories(c, g): "^cxx_static_lib::@a56b12a3f5c0529fb296$", ], "projectName": "Cxx", + "minimumCMakeVersion": "3.12", + "hasInstallRule": None, }, { "source": "^imported$", @@ -507,6 +525,8 @@ def gen_check_directories(c, g): "^link_imported_static_exe::@ba7eb709d0b48779c6c8$", ], "projectName": "Imported", + "minimumCMakeVersion": "3.12", + "hasInstallRule": None, }, { "source": "^object$", @@ -522,6 +542,8 @@ def gen_check_directories(c, g): "^cxx_object_lib::@5ed5358f70faf8d8af7a$", ], "projectName": "Object", + "minimumCMakeVersion": "3.13", + "hasInstallRule": True, }, { "source": "^dir$", @@ -542,6 +564,8 @@ def gen_check_directories(c, g): "childSources": None, "targetIds": None, "projectName": "codemodel-v2", + "minimumCMakeVersion": "3.12", + "hasInstallRule": None, }, { "source": "^.*/Tests/RunCMake/FileAPIExternalSource$", @@ -554,6 +578,8 @@ def gen_check_directories(c, g): "^generated_exe::@[0-9a-f]+$", ], "projectName": "External", + "minimumCMakeVersion": "3.12", + "hasInstallRule": None, }, ] |