1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-20 12:53:55 +08:00

fileapi: add cache v2

Start with v2 to distinguish it from server-mode v1.

Issue: #18398
This commit is contained in:
Brad King
2018-11-01 09:37:17 -04:00
parent ea0a060168
commit 7489e95b8e
15 changed files with 315 additions and 0 deletions

View File

@@ -869,3 +869,77 @@ with members:
with forward slashes. If the file is inside the top-level source with forward slashes. If the file is inside the top-level source
directory then the path is specified relative to that directory. directory then the path is specified relative to that directory.
Otherwise the path is absolute. Otherwise the path is absolute.
Object Kind "cache"
-------------------
The ``cache`` object kind lists cache entries. These are the
:ref:`CMake Language Variables` stored in the persistent cache
(``CMakeCache.txt``) for the build tree.
There is only one ``cache`` object major version, version 2.
Version 1 does not exist to avoid confusion with that from
:manual:`cmake-server(7)` mode.
"cache" version 2
^^^^^^^^^^^^^^^^^
``cache`` object version 2 is a JSON object:
.. code-block:: json
{
"kind": "cache",
"version": { "major": 2, "minor": 0 },
"entries": [
{
"name": "BUILD_SHARED_LIBS",
"value": "ON",
"type": "BOOL",
"properties": [
{
"name": "HELPSTRING",
"value": "Build shared libraries"
}
]
},
{
"name": "CMAKE_GENERATOR",
"value": "Unix Makefiles",
"type": "INTERNAL",
"properties": [
{
"name": "HELPSTRING",
"value": "Name of generator."
}
]
}
]
}
The members specific to ``cache`` objects are:
``entries``
A JSON array whose entries are each a JSON object specifying a
cache entry. The members of each entry are:
``name``
A string specifying the name of the entry.
``value``
A string specifying the value of the entry.
``type``
A string specifying the type of the entry used by
:manual:`cmake-gui(1)` to choose a widget for editing.
``properties``
A JSON array of entries specifying associated
:ref:`cache entry properties <Cache Entry Properties>`.
Each entry is a JSON object containing members:
``name``
A string specifying the name of the cache entry property.
``value``
A string specifying the value of the cache entry property.

View File

@@ -209,6 +209,8 @@ set(SRCS
cmExtraSublimeTextGenerator.h cmExtraSublimeTextGenerator.h
cmFileAPI.cxx cmFileAPI.cxx
cmFileAPI.h cmFileAPI.h
cmFileAPICache.cxx
cmFileAPICache.h
cmFileAPICodemodel.cxx cmFileAPICodemodel.cxx
cmFileAPICodemodel.h cmFileAPICodemodel.h
cmFileLock.cxx cmFileLock.cxx

View File

@@ -4,6 +4,7 @@
#include "cmAlgorithms.h" #include "cmAlgorithms.h"
#include "cmCryptoHash.h" #include "cmCryptoHash.h"
#include "cmFileAPICache.h"
#include "cmFileAPICodemodel.h" #include "cmFileAPICodemodel.h"
#include "cmGlobalGenerator.h" #include "cmGlobalGenerator.h"
#include "cmSystemTools.h" #include "cmSystemTools.h"
@@ -236,6 +237,17 @@ bool cmFileAPI::ReadQuery(std::string const& query,
objects.push_back(o); objects.push_back(o);
return true; return true;
} }
if (kindName == ObjectKindName(ObjectKind::Cache)) {
Object o;
o.Kind = ObjectKind::Cache;
if (verStr == "v2") {
o.Version = 2;
} else {
return false;
}
objects.push_back(o);
return true;
}
if (kindName == ObjectKindName(ObjectKind::InternalTest)) { if (kindName == ObjectKindName(ObjectKind::InternalTest)) {
Object o; Object o;
o.Kind = ObjectKind::InternalTest; o.Kind = ObjectKind::InternalTest;
@@ -374,6 +386,7 @@ const char* cmFileAPI::ObjectKindName(ObjectKind kind)
// Keep in sync with ObjectKind enum. // Keep in sync with ObjectKind enum.
static const char* objectKindNames[] = { static const char* objectKindNames[] = {
"codemodel", // "codemodel", //
"cache", //
"__test" // "__test" //
}; };
return objectKindNames[size_t(kind)]; return objectKindNames[size_t(kind)];
@@ -395,6 +408,9 @@ Json::Value cmFileAPI::BuildObject(Object const& object)
case ObjectKind::CodeModel: case ObjectKind::CodeModel:
value = this->BuildCodeModel(object); value = this->BuildCodeModel(object);
break; break;
case ObjectKind::Cache:
value = this->BuildCache(object);
break;
case ObjectKind::InternalTest: case ObjectKind::InternalTest:
value = this->BuildInternalTest(object); value = this->BuildInternalTest(object);
break; break;
@@ -447,6 +463,8 @@ cmFileAPI::ClientRequest cmFileAPI::BuildClientRequest(
if (kindName == this->ObjectKindName(ObjectKind::CodeModel)) { if (kindName == this->ObjectKindName(ObjectKind::CodeModel)) {
r.Kind = ObjectKind::CodeModel; r.Kind = ObjectKind::CodeModel;
} else if (kindName == this->ObjectKindName(ObjectKind::Cache)) {
r.Kind = ObjectKind::Cache;
} else if (kindName == this->ObjectKindName(ObjectKind::InternalTest)) { } else if (kindName == this->ObjectKindName(ObjectKind::InternalTest)) {
r.Kind = ObjectKind::InternalTest; r.Kind = ObjectKind::InternalTest;
} else { } else {
@@ -468,6 +486,9 @@ cmFileAPI::ClientRequest cmFileAPI::BuildClientRequest(
case ObjectKind::CodeModel: case ObjectKind::CodeModel:
this->BuildClientRequestCodeModel(r, versions); this->BuildClientRequestCodeModel(r, versions);
break; break;
case ObjectKind::Cache:
this->BuildClientRequestCache(r, versions);
break;
case ObjectKind::InternalTest: case ObjectKind::InternalTest:
this->BuildClientRequestInternalTest(r, versions); this->BuildClientRequestInternalTest(r, versions);
break; break;
@@ -649,6 +670,42 @@ Json::Value cmFileAPI::BuildCodeModel(Object const& object)
return codemodel; return codemodel;
} }
// The "cache" object kind.
static unsigned int const CacheV2Minor = 0;
void cmFileAPI::BuildClientRequestCache(
ClientRequest& r, std::vector<RequestVersion> const& versions)
{
// Select a known version from those requested.
for (RequestVersion const& v : versions) {
if ((v.Major == 2 && v.Minor <= CacheV2Minor)) {
r.Version = v.Major;
break;
}
}
if (!r.Version) {
r.Error = NoSupportedVersion(versions);
}
}
Json::Value cmFileAPI::BuildCache(Object const& object)
{
using namespace std::placeholders;
Json::Value cache = cmFileAPICacheDump(*this, object.Version);
cache["kind"] = this->ObjectKindName(object.Kind);
Json::Value& version = cache["version"] = Json::objectValue;
if (object.Version == 2) {
version["major"] = 2;
version["minor"] = CacheV2Minor;
} else {
return cache; // should be unreachable
}
return cache;
}
// The "__test" object kind is for internal testing of CMake. // The "__test" object kind is for internal testing of CMake.
static unsigned int const InternalTestV1Minor = 3; static unsigned int const InternalTestV1Minor = 3;

View File

@@ -52,6 +52,7 @@ private:
enum class ObjectKind enum class ObjectKind
{ {
CodeModel, CodeModel,
Cache,
InternalTest InternalTest
}; };
@@ -186,6 +187,10 @@ private:
ClientRequest& r, std::vector<RequestVersion> const& versions); ClientRequest& r, std::vector<RequestVersion> const& versions);
Json::Value BuildCodeModel(Object const& object); Json::Value BuildCodeModel(Object const& object);
void BuildClientRequestCache(ClientRequest& r,
std::vector<RequestVersion> const& versions);
Json::Value BuildCache(Object const& object);
void BuildClientRequestInternalTest( void BuildClientRequestInternalTest(
ClientRequest& r, std::vector<RequestVersion> const& versions); ClientRequest& r, std::vector<RequestVersion> const& versions);
Json::Value BuildInternalTest(Object const& object); Json::Value BuildInternalTest(Object const& object);

105
Source/cmFileAPICache.cxx Normal file
View File

@@ -0,0 +1,105 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFileAPICache.h"
#include "cmFileAPI.h"
#include "cmState.h"
#include "cmake.h"
#include "cm_jsoncpp_value.h"
#include <algorithm>
#include <string>
#include <vector>
namespace {
class Cache
{
cmFileAPI& FileAPI;
unsigned long Version;
cmState* State;
Json::Value DumpEntries();
Json::Value DumpEntry(std::string const& name);
Json::Value DumpEntryProperties(std::string const& name);
Json::Value DumpEntryProperty(std::string const& name,
std::string const& prop);
public:
Cache(cmFileAPI& fileAPI, unsigned long version);
Json::Value Dump();
};
Cache::Cache(cmFileAPI& fileAPI, unsigned long version)
: FileAPI(fileAPI)
, Version(version)
, State(this->FileAPI.GetCMakeInstance()->GetState())
{
static_cast<void>(this->Version);
}
Json::Value Cache::Dump()
{
Json::Value cache = Json::objectValue;
cache["entries"] = DumpEntries();
return cache;
}
Json::Value Cache::DumpEntries()
{
Json::Value entries = Json::arrayValue;
std::vector<std::string> names = this->State->GetCacheEntryKeys();
std::sort(names.begin(), names.end());
for (std::string const& name : names) {
entries.append(this->DumpEntry(name));
}
return entries;
}
Json::Value Cache::DumpEntry(std::string const& name)
{
Json::Value entry = Json::objectValue;
entry["name"] = name;
entry["type"] =
cmState::CacheEntryTypeToString(this->State->GetCacheEntryType(name));
entry["value"] = this->State->GetCacheEntryValue(name);
Json::Value properties = this->DumpEntryProperties(name);
if (!properties.empty()) {
entry["properties"] = std::move(properties);
}
return entry;
}
Json::Value Cache::DumpEntryProperties(std::string const& name)
{
Json::Value properties = Json::arrayValue;
std::vector<std::string> props =
this->State->GetCacheEntryPropertyList(name);
std::sort(props.begin(), props.end());
for (std::string const& prop : props) {
properties.append(this->DumpEntryProperty(name, prop));
}
return properties;
}
Json::Value Cache::DumpEntryProperty(std::string const& name,
std::string const& prop)
{
Json::Value property = Json::objectValue;
property["name"] = prop;
property["value"] = this->State->GetCacheEntryProperty(name, prop);
return property;
}
}
Json::Value cmFileAPICacheDump(cmFileAPI& fileAPI, unsigned long version)
{
Cache cache(fileAPI, version);
return cache.Dump();
}

15
Source/cmFileAPICache.h Normal file
View File

@@ -0,0 +1,15 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmFileAPICache_h
#define cmFileAPICache_h
#include "cmConfigure.h" // IWYU pragma: keep
#include "cm_jsoncpp_value.h"
class cmFileAPI;
extern Json::Value cmFileAPICacheDump(cmFileAPI& fileAPI,
unsigned long version);
#endif

View File

@@ -54,3 +54,4 @@ function(run_object object)
endfunction() endfunction()
run_object(codemodel-v2) run_object(codemodel-v2)
run_object(cache-v2)

View File

@@ -0,0 +1,11 @@
set(expect
query
query/client-foo
query/client-foo/query.json
reply
reply/cache-v2-[0-9a-f]+.json
reply/index-[0-9.T-]+.json
)
check_api("^${expect}$")
check_python(cache-v2)

View File

@@ -0,0 +1,4 @@
file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/query.json" [[
{ "requests": [ { "kind": "cache", "version" : 2 } ] }
]])

View File

@@ -0,0 +1,11 @@
set(expect
query
query/client-foo
query/client-foo/cache-v2
reply
reply/cache-v2-[0-9a-f]+.json
reply/index-[0-9.T-]+.json
)
check_api("^${expect}$")
check_python(cache-v2)

View File

@@ -0,0 +1,2 @@
file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/cache-v2" "")

View File

@@ -0,0 +1,10 @@
set(expect
query
query/cache-v2
reply
reply/cache-v2-[0-9a-f]+.json
reply/index-[0-9.T-]+.json
)
check_api("^${expect}$")
check_python(cache-v2)

View File

@@ -0,0 +1,2 @@
file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/cache-v2" "")

View File

@@ -0,0 +1,15 @@
from check_index import *
def check_objects(o):
assert is_list(o)
assert len(o) == 1
check_index_object(o[0], "cache", 2, 0, check_object_cache)
def check_object_cache(o):
assert sorted(o.keys()) == ["entries", "kind", "version"]
# The "kind" and "version" members are handled by check_index_object.
# FIXME: Check "entries" member
assert is_dict(index)
assert sorted(index.keys()) == ["cmake", "objects", "reply"]
check_objects(index["objects"])

View File

@@ -0,0 +1 @@
# FIXME: add some specific cache entries to cover in test, with properties