mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-10 07:40:03 -06:00
FileAPI: Add "configureLog" object kind
Provide clients with a way to get a known set of configure log event versions. Issue: #23200
This commit is contained in:
@@ -73,6 +73,16 @@ they do not understand:
|
||||
* If an existing build tree is re-configured with a different version of
|
||||
CMake, the log may contain different versions of the same event kind.
|
||||
|
||||
* If :manual:`cmake-file-api(7)` queries request one or more
|
||||
:ref:`configureLog <file-api configureLog>` object versions,
|
||||
the log may contain multiple entries for the same event, each
|
||||
with a different version of its event kind.
|
||||
|
||||
IDEs should write a :manual:`cmake-file-api(7)` query requesting a
|
||||
specific :ref:`configureLog <file-api configureLog>` object version,
|
||||
before running CMake, and then read the configure log only as described
|
||||
by the file-api reply.
|
||||
|
||||
Text Block Encoding
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -1298,6 +1298,45 @@ elsewhere in the containing object. The backtrace graph object members are:
|
||||
directory then the path is specified relative to that directory.
|
||||
Otherwise the path is absolute.
|
||||
|
||||
.. _`file-api configureLog`:
|
||||
|
||||
Object Kind "configureLog"
|
||||
--------------------------
|
||||
|
||||
The ``configureLog`` object kind describes the location and contents of
|
||||
a :manual:`cmake-configure-log(7)` file.
|
||||
|
||||
There is only one ``configureLog`` object major version, version 1.
|
||||
|
||||
"configureLog" version 1
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``configureLog`` object version 1 is a JSON object:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"kind": "configureLog",
|
||||
"version": { "major": 1, "minor": 0 },
|
||||
"path": "/path/to/top-level-build-dir/CMakeFiles/CMakeConfigureLog.yaml",
|
||||
"eventKindNames": [ "try_compile-v1", "try_run-v1" ]
|
||||
}
|
||||
|
||||
The members specific to ``configureLog`` objects are:
|
||||
|
||||
``path``
|
||||
A string specifying the path to the configure log file.
|
||||
Clients must read the log file from this path, which may be
|
||||
different than the path documented by :manual:`cmake-configure-log(7)`.
|
||||
The log file may not exist if no events are logged.
|
||||
|
||||
``eventKindNames``
|
||||
A JSON array whose entries are each a JSON string naming one
|
||||
of the :manual:`cmake-configure-log(7)` versioned event kinds.
|
||||
At most one version of each configure log event kind will be listed.
|
||||
Although the configure log may contain other (versioned) event kinds,
|
||||
clients must ignore those that are not listed in this field.
|
||||
|
||||
Object Kind "cache"
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -3,3 +3,6 @@ Configure Log
|
||||
|
||||
* CMake now writes a YAML log of configure-time checks.
|
||||
See the :manual:`cmake-configure-log(7)` manual.
|
||||
|
||||
* The :manual:`cmake-file-api(7)` gained a new "configureLog" object kind
|
||||
that enables stable access to the :manual:`cmake-configure-log(7)`.
|
||||
|
||||
@@ -237,6 +237,8 @@ add_library(
|
||||
cmFileAPICache.h
|
||||
cmFileAPICodemodel.cxx
|
||||
cmFileAPICodemodel.h
|
||||
cmFileAPIConfigureLog.cxx
|
||||
cmFileAPIConfigureLog.h
|
||||
cmFileAPICMakeFiles.cxx
|
||||
cmFileAPICMakeFiles.h
|
||||
cmFileAPIToolchains.cxx
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "cmFileAPICMakeFiles.h"
|
||||
#include "cmFileAPICache.h"
|
||||
#include "cmFileAPICodemodel.h"
|
||||
#include "cmFileAPIConfigureLog.h"
|
||||
#include "cmFileAPIToolchains.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
@@ -66,6 +67,26 @@ void cmFileAPI::ReadQueries()
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned long> cmFileAPI::GetConfigureLogVersions()
|
||||
{
|
||||
std::vector<unsigned long> versions;
|
||||
auto getConfigureLogVersions = [&versions](Query const& q) {
|
||||
for (Object const& o : q.Known) {
|
||||
if (o.Kind == ObjectKind::ConfigureLog) {
|
||||
versions.emplace_back(o.Version);
|
||||
}
|
||||
}
|
||||
};
|
||||
getConfigureLogVersions(this->TopQuery);
|
||||
for (auto const& client : this->ClientQueries) {
|
||||
getConfigureLogVersions(client.second.DirQuery);
|
||||
}
|
||||
std::sort(versions.begin(), versions.end());
|
||||
versions.erase(std::unique(versions.begin(), versions.end()),
|
||||
versions.end());
|
||||
return versions;
|
||||
}
|
||||
|
||||
void cmFileAPI::WriteReplies()
|
||||
{
|
||||
if (this->QueryExists) {
|
||||
@@ -241,6 +262,17 @@ bool cmFileAPI::ReadQuery(std::string const& query,
|
||||
objects.push_back(o);
|
||||
return true;
|
||||
}
|
||||
if (kindName == ObjectKindName(ObjectKind::ConfigureLog)) {
|
||||
Object o;
|
||||
o.Kind = ObjectKind::ConfigureLog;
|
||||
if (verStr == "v1") {
|
||||
o.Version = 1;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
objects.push_back(o);
|
||||
return true;
|
||||
}
|
||||
if (kindName == ObjectKindName(ObjectKind::Cache)) {
|
||||
Object o;
|
||||
o.Kind = ObjectKind::Cache;
|
||||
@@ -411,11 +443,12 @@ const char* cmFileAPI::ObjectKindName(ObjectKind kind)
|
||||
{
|
||||
// Keep in sync with ObjectKind enum.
|
||||
static const char* objectKindNames[] = {
|
||||
"codemodel", //
|
||||
"cache", //
|
||||
"cmakeFiles", //
|
||||
"toolchains", //
|
||||
"__test" //
|
||||
"codemodel", //
|
||||
"configureLog", //
|
||||
"cache", //
|
||||
"cmakeFiles", //
|
||||
"toolchains", //
|
||||
"__test" //
|
||||
};
|
||||
return objectKindNames[static_cast<size_t>(kind)];
|
||||
}
|
||||
@@ -442,6 +475,9 @@ Json::Value cmFileAPI::BuildObject(Object const& object)
|
||||
case ObjectKind::CodeModel:
|
||||
value = this->BuildCodeModel(object);
|
||||
break;
|
||||
case ObjectKind::ConfigureLog:
|
||||
value = this->BuildConfigureLog(object);
|
||||
break;
|
||||
case ObjectKind::Cache:
|
||||
value = this->BuildCache(object);
|
||||
break;
|
||||
@@ -503,6 +539,8 @@ cmFileAPI::ClientRequest cmFileAPI::BuildClientRequest(
|
||||
|
||||
if (kindName == this->ObjectKindName(ObjectKind::CodeModel)) {
|
||||
r.Kind = ObjectKind::CodeModel;
|
||||
} else if (kindName == this->ObjectKindName(ObjectKind::ConfigureLog)) {
|
||||
r.Kind = ObjectKind::ConfigureLog;
|
||||
} else if (kindName == this->ObjectKindName(ObjectKind::Cache)) {
|
||||
r.Kind = ObjectKind::Cache;
|
||||
} else if (kindName == this->ObjectKindName(ObjectKind::CMakeFiles)) {
|
||||
@@ -530,6 +568,9 @@ cmFileAPI::ClientRequest cmFileAPI::BuildClientRequest(
|
||||
case ObjectKind::CodeModel:
|
||||
this->BuildClientRequestCodeModel(r, versions);
|
||||
break;
|
||||
case ObjectKind::ConfigureLog:
|
||||
this->BuildClientRequestConfigureLog(r, versions);
|
||||
break;
|
||||
case ObjectKind::Cache:
|
||||
this->BuildClientRequestCache(r, versions);
|
||||
break;
|
||||
@@ -719,6 +760,41 @@ Json::Value cmFileAPI::BuildCodeModel(Object const& object)
|
||||
return codemodel;
|
||||
}
|
||||
|
||||
// The "configureLog" object kind.
|
||||
|
||||
// Update Help/manual/cmake-file-api.7.rst when updating this constant.
|
||||
static unsigned int const ConfigureLogV1Minor = 0;
|
||||
|
||||
void cmFileAPI::BuildClientRequestConfigureLog(
|
||||
ClientRequest& r, std::vector<RequestVersion> const& versions)
|
||||
{
|
||||
// Select a known version from those requested.
|
||||
for (RequestVersion const& v : versions) {
|
||||
if ((v.Major == 1 && v.Minor <= ConfigureLogV1Minor)) {
|
||||
r.Version = v.Major;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!r.Version) {
|
||||
r.Error = NoSupportedVersion(versions);
|
||||
}
|
||||
}
|
||||
|
||||
Json::Value cmFileAPI::BuildConfigureLog(Object const& object)
|
||||
{
|
||||
Json::Value configureLog = cmFileAPIConfigureLogDump(*this, object.Version);
|
||||
configureLog["kind"] = this->ObjectKindName(object.Kind);
|
||||
|
||||
Json::Value& version = configureLog["version"];
|
||||
if (object.Version == 1) {
|
||||
version = BuildVersion(1, ConfigureLogV1Minor);
|
||||
} else {
|
||||
return configureLog; // should be unreachable
|
||||
}
|
||||
|
||||
return configureLog;
|
||||
}
|
||||
|
||||
// The "cache" object kind.
|
||||
|
||||
static unsigned int const CacheV2Minor = 0;
|
||||
@@ -868,6 +944,14 @@ Json::Value cmFileAPI::ReportCapabilities()
|
||||
requests.append(std::move(request)); // NOLINT(*)
|
||||
}
|
||||
|
||||
{
|
||||
Json::Value request = Json::objectValue;
|
||||
request["kind"] = ObjectKindName(ObjectKind::ConfigureLog);
|
||||
Json::Value& versions = request["version"] = Json::arrayValue;
|
||||
versions.append(BuildVersion(1, ConfigureLogV1Minor));
|
||||
requests.append(std::move(request)); // NOLINT(*)
|
||||
}
|
||||
|
||||
{
|
||||
Json::Value request = Json::objectValue;
|
||||
request["kind"] = ObjectKindName(ObjectKind::Cache);
|
||||
|
||||
@@ -24,6 +24,9 @@ public:
|
||||
/** Read fileapi queries from disk. */
|
||||
void ReadQueries();
|
||||
|
||||
/** Get the list of configureLog object kind versions requested. */
|
||||
std::vector<unsigned long> GetConfigureLogVersions();
|
||||
|
||||
/** Write fileapi replies to disk. */
|
||||
void WriteReplies();
|
||||
|
||||
@@ -54,6 +57,7 @@ private:
|
||||
enum class ObjectKind
|
||||
{
|
||||
CodeModel,
|
||||
ConfigureLog,
|
||||
Cache,
|
||||
CMakeFiles,
|
||||
Toolchains,
|
||||
@@ -193,6 +197,10 @@ private:
|
||||
ClientRequest& r, std::vector<RequestVersion> const& versions);
|
||||
Json::Value BuildCodeModel(Object const& object);
|
||||
|
||||
void BuildClientRequestConfigureLog(
|
||||
ClientRequest& r, std::vector<RequestVersion> const& versions);
|
||||
Json::Value BuildConfigureLog(Object const& object);
|
||||
|
||||
void BuildClientRequestCache(ClientRequest& r,
|
||||
std::vector<RequestVersion> const& versions);
|
||||
Json::Value BuildCache(Object const& object);
|
||||
|
||||
67
Source/cmFileAPIConfigureLog.cxx
Normal file
67
Source/cmFileAPIConfigureLog.cxx
Normal file
@@ -0,0 +1,67 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmFileAPIConfigureLog.h"
|
||||
|
||||
#include <cm3p/json/value.h>
|
||||
|
||||
#include "cmFileAPI.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmake.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class ConfigureLog
|
||||
{
|
||||
cmFileAPI& FileAPI;
|
||||
unsigned long Version;
|
||||
|
||||
Json::Value DumpPath();
|
||||
Json::Value DumpEventKindNames();
|
||||
|
||||
public:
|
||||
ConfigureLog(cmFileAPI& fileAPI, unsigned long version);
|
||||
Json::Value Dump();
|
||||
};
|
||||
|
||||
ConfigureLog::ConfigureLog(cmFileAPI& fileAPI, unsigned long version)
|
||||
: FileAPI(fileAPI)
|
||||
, Version(version)
|
||||
{
|
||||
static_cast<void>(this->Version);
|
||||
}
|
||||
|
||||
Json::Value ConfigureLog::Dump()
|
||||
{
|
||||
Json::Value configureLog = Json::objectValue;
|
||||
configureLog["path"] = this->DumpPath();
|
||||
configureLog["eventKindNames"] = this->DumpEventKindNames();
|
||||
return configureLog;
|
||||
}
|
||||
|
||||
Json::Value ConfigureLog::DumpPath()
|
||||
{
|
||||
return cmStrCat(this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory(),
|
||||
"/CMakeFiles/CMakeConfigureLog.yaml");
|
||||
}
|
||||
|
||||
Json::Value ConfigureLog::DumpEventKindNames()
|
||||
{
|
||||
// Report at most one version of each event kind.
|
||||
// If a new event kind is added, increment ConfigureLogV1Minor.
|
||||
// If a new version of an existing event kind is added, a new
|
||||
// major version of the configureLog object kind is needed.
|
||||
Json::Value eventKindNames = Json::arrayValue;
|
||||
if (this->Version == 1) {
|
||||
eventKindNames.append("try_compile-v1"); // WriteTryCompileEvent
|
||||
eventKindNames.append("try_run-v1"); // WriteTryRunEvent
|
||||
}
|
||||
return eventKindNames;
|
||||
}
|
||||
}
|
||||
|
||||
Json::Value cmFileAPIConfigureLogDump(cmFileAPI& fileAPI,
|
||||
unsigned long version)
|
||||
{
|
||||
ConfigureLog configureLog(fileAPI, version);
|
||||
return configureLog.Dump();
|
||||
}
|
||||
12
Source/cmFileAPIConfigureLog.h
Normal file
12
Source/cmFileAPIConfigureLog.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#pragma once
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include <cm3p/json/value.h>
|
||||
|
||||
class cmFileAPI;
|
||||
|
||||
extern Json::Value cmFileAPIConfigureLogDump(cmFileAPI& fileAPI,
|
||||
unsigned long version);
|
||||
@@ -21,6 +21,7 @@ namespace {
|
||||
void WriteTryCompileEvent(cmConfigureLog& log, cmMakefile const& mf,
|
||||
cmTryCompileResult const& compileResult)
|
||||
{
|
||||
// Keep in sync with cmFileAPIConfigureLog's DumpEventKindNames.
|
||||
static const std::vector<unsigned long> LogVersionsWithTryCompileV1{ 1 };
|
||||
|
||||
if (log.IsAnyLogVersionEnabled(LogVersionsWithTryCompileV1)) {
|
||||
|
||||
@@ -40,6 +40,7 @@ void WriteTryRunEvent(cmConfigureLog& log, cmMakefile const& mf,
|
||||
cmTryCompileResult const& compileResult,
|
||||
cmTryRunResult const& runResult)
|
||||
{
|
||||
// Keep in sync with cmFileAPIConfigureLog's DumpEventKindNames.
|
||||
static const std::vector<unsigned long> LogVersionsWithTryRunV1{ 1 };
|
||||
|
||||
if (log.IsAnyLogVersionEnabled(LogVersionsWithTryRunV1)) {
|
||||
|
||||
@@ -2429,7 +2429,7 @@ int cmake::ActualConfigure()
|
||||
this->TruncateOutputLog("CMakeConfigureLog.yaml");
|
||||
this->ConfigureLog = cm::make_unique<cmConfigureLog>(
|
||||
cmStrCat(this->GetHomeOutputDirectory(), "/CMakeFiles"_s),
|
||||
std::vector<unsigned long>());
|
||||
this->FileAPI->GetConfigureLogVersions());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":5}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]},{"kind":"toolchains","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":false,"tls":(true|false),"version":{.*}}$
|
||||
^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":5}]},{"kind":"configureLog","version":\[{"major":1,"minor":0}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]},{"kind":"toolchains","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":false,"tls":(true|false),"version":{.*}}$
|
||||
|
||||
@@ -65,6 +65,7 @@ function(run_object object)
|
||||
endfunction()
|
||||
|
||||
run_object(codemodel-v2)
|
||||
run_object(configureLog-v1)
|
||||
run_object(cache-v2)
|
||||
run_object(cmakeFiles-v1)
|
||||
run_object(toolchains-v1)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
set(expect
|
||||
query
|
||||
query/client-foo
|
||||
query/client-foo/query.json
|
||||
reply
|
||||
reply/configureLog-v1-[0-9a-f]+.json
|
||||
reply/index-[0-9.T-]+.json
|
||||
)
|
||||
check_api("^${expect}$")
|
||||
|
||||
check_python(configureLog-v1)
|
||||
@@ -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": "configureLog", "version" : 1 } ] }
|
||||
]])
|
||||
@@ -0,0 +1,11 @@
|
||||
set(expect
|
||||
query
|
||||
query/client-foo
|
||||
query/client-foo/configureLog-v1
|
||||
reply
|
||||
reply/configureLog-v1-[0-9a-f]+.json
|
||||
reply/index-[0-9.T-]+.json
|
||||
)
|
||||
check_api("^${expect}$")
|
||||
|
||||
check_python(configureLog-v1)
|
||||
@@ -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/configureLog-v1" "")
|
||||
@@ -0,0 +1,10 @@
|
||||
set(expect
|
||||
query
|
||||
query/configureLog-v1
|
||||
reply
|
||||
reply/configureLog-v1-[0-9a-f]+.json
|
||||
reply/index-[0-9.T-]+.json
|
||||
)
|
||||
check_api("^${expect}$")
|
||||
|
||||
check_python(configureLog-v1)
|
||||
@@ -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/configureLog-v1" "")
|
||||
21
Tests/RunCMake/FileAPI/configureLog-v1-check.py
Normal file
21
Tests/RunCMake/FileAPI/configureLog-v1-check.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from check_index import *
|
||||
import os
|
||||
|
||||
def check_objects(o):
|
||||
assert is_list(o)
|
||||
assert len(o) == 1
|
||||
check_index_object(o[0], "configureLog", 1, 0, check_object_configureLog)
|
||||
|
||||
def check_object_configureLog(o):
|
||||
assert sorted(o.keys()) == ["eventKindNames", "kind", "path", "version"]
|
||||
# The "kind" and "version" members are handled by check_index_object.
|
||||
path = o["path"]
|
||||
assert matches(path, "^.*/CMakeFiles/CMakeConfigureLog\\.yaml$")
|
||||
assert os.path.exists(path)
|
||||
eventKindNames = o["eventKindNames"]
|
||||
assert is_list(eventKindNames)
|
||||
assert sorted(eventKindNames) == ["try_compile-v1", "try_run-v1"]
|
||||
|
||||
assert is_dict(index)
|
||||
assert sorted(index.keys()) == ["cmake", "objects", "reply"]
|
||||
check_objects(index["objects"])
|
||||
1
Tests/RunCMake/FileAPI/configureLog-v1.cmake
Normal file
1
Tests/RunCMake/FileAPI/configureLog-v1.cmake
Normal file
@@ -0,0 +1 @@
|
||||
enable_language(C)
|
||||
Reference in New Issue
Block a user