summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2018-11-13 14:34:10 (GMT)
committerKyle Edwards <kyle.edwards@kitware.com>2018-12-12 20:12:26 (GMT)
commit4b6b2a571c39439f3b07d56f36e6a927ed6d1dd8 (patch)
treec0ee27f9e86aea592e750d4004c46f96b44d9df4
parenteb8c7676a4723a44245e47630f12d4868e8e182c (diff)
downloadCMake-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.rst32
-rw-r--r--Source/cmFileAPICodemodel.cxx50
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-check.py26
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,
},
]