mirror of
https://github.com/Kitware/CMake.git
synced 2025-12-31 02:39:48 -06:00
fileapi: Generate partial reply when buildsystem generation fails
In particular, the `configureLog` reply is useful for IDEs to read `CMakeFiles/CMakeConfigureLog.yaml` when configuration fails. Fixes: #26621
This commit is contained in:
@@ -41,14 +41,22 @@ It has the following subdirectories:
|
||||
`v1 Client Stateless Query Files`_, or `v1 Client Stateful Query Files`_.
|
||||
|
||||
``reply/``
|
||||
Holds reply files written by CMake whenever it runs to generate a build
|
||||
system. These are indexed by a `v1 Reply Index File`_ that may
|
||||
reference additional `v1 Reply Files`_. CMake owns all reply files.
|
||||
Clients must never remove them.
|
||||
Holds reply files written by CMake when it runs to generate a build system.
|
||||
Clients may read reply files only when referenced by a reply index:
|
||||
|
||||
Clients may look for and read a reply index file at any time.
|
||||
``index-*.json``
|
||||
A `v1 Reply Index File`_ written when CMake generates a build system.
|
||||
|
||||
``error-*.json``
|
||||
.. versionadded:: 4.1
|
||||
|
||||
A `v1 Reply Error Index`_ written when CMake fails to generate a build
|
||||
system due to an error.
|
||||
|
||||
Clients may look for and read a reply index at any time.
|
||||
Clients may optionally create the ``reply/`` directory at any time
|
||||
and monitor it for the appearance of a new reply index file.
|
||||
and monitor it for the appearance of a new reply index.
|
||||
CMake owns all reply files. Clients must never remove them.
|
||||
|
||||
.. versionadded:: 3.31
|
||||
Users can add query files to ``api/v1/query`` inside the
|
||||
@@ -179,7 +187,7 @@ v1 Reply Index File
|
||||
-------------------
|
||||
|
||||
CMake writes an ``index-*.json`` file to the ``v1/reply/`` directory
|
||||
whenever it runs to generate a build system. Clients must read the
|
||||
when it successfully generates a build system. Clients must read the
|
||||
reply index file first and may read other `v1 Reply Files`_ only by
|
||||
following references. The form of the reply index file name is::
|
||||
|
||||
@@ -300,8 +308,12 @@ The members are:
|
||||
A member of this form appears for each of the
|
||||
`v1 Shared Stateless Query Files`_ that CMake recognized as a
|
||||
request for object kind ``<kind>`` with major version ``<major>``.
|
||||
The value is a `v1 Reply File Reference`_ to the corresponding
|
||||
reply file for that object kind and version.
|
||||
The value is
|
||||
|
||||
* a `v1 Reply File Reference`_ to the corresponding reply file for
|
||||
that object kind and version, or
|
||||
* in a `v1 Reply Error Index`_, a JSON object with a single ``error``
|
||||
member containing a string with an error message.
|
||||
|
||||
``<unknown>``
|
||||
A member of this form appears for each of the
|
||||
@@ -320,8 +332,12 @@ The members are:
|
||||
A member of this form appears for each of the
|
||||
`v1 Client Stateless Query Files`_ that CMake recognized as a
|
||||
request for object kind ``<kind>`` with major version ``<major>``.
|
||||
The value is a `v1 Reply File Reference`_ to the corresponding
|
||||
reply file for that object kind and version.
|
||||
The value is
|
||||
|
||||
* a `v1 Reply File Reference`_ to the corresponding reply file for
|
||||
that object kind and version, or
|
||||
* in a `v1 Reply Error Index`_, a JSON object with a single ``error``
|
||||
member containing a string with an error message.
|
||||
|
||||
``<unknown>``
|
||||
A member of this form appears for each of the
|
||||
@@ -375,6 +391,35 @@ using a JSON object with members:
|
||||
A JSON string specifying a path relative to the reply index file
|
||||
to another JSON file containing the object.
|
||||
|
||||
.. _`file-api reply error index`:
|
||||
|
||||
v1 Reply Error Index
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 4.1
|
||||
|
||||
CMake writes an ``error-*.json`` file to the ``v1/reply/`` directory
|
||||
when it fails to generate a build system. This reply error index
|
||||
follows the same naming pattern, syntax, and semantics of a
|
||||
`v1 Reply Index File`_, with the following exceptions:
|
||||
|
||||
* The ``index-`` prefix is replaced by an ``error-`` prefix.
|
||||
|
||||
* When a new error index is generated, old index files are *not*
|
||||
deleted. If a `v1 Reply Index File`_ exists, it indexes replies
|
||||
from the most recent successful run. If multiple ``index-*.json``
|
||||
and/or ``error-*.json`` files are present, the one with the largest
|
||||
name in lexicographic order, excluding the ``index-`` or ``error-``
|
||||
prefix, is the current index.
|
||||
|
||||
* Only a subset of `Object Kinds`_ are provided:
|
||||
|
||||
`configureLog <file-api configureLog_>`_
|
||||
.. versionadded:: 4.1
|
||||
|
||||
Index entries for other object kinds contain an ``error`` message
|
||||
instead of a `v1 Reply File Reference`_.
|
||||
|
||||
v1 Reply Files
|
||||
--------------
|
||||
|
||||
|
||||
6
Help/release/dev/fileapi-reply-on-failure.rst
Normal file
6
Help/release/dev/fileapi-reply-on-failure.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
fileapi-reply-on-failure
|
||||
------------------------
|
||||
|
||||
* The :manual:`cmake-file-api(7)` :ref:`v1 <file-api v1>` now writes
|
||||
partial replies when buildsystem generation fails with an error.
|
||||
See the :ref:`v1 Reply Error Index <file-api reply error index>`.
|
||||
@@ -105,14 +105,20 @@ std::vector<unsigned long> cmFileAPI::GetConfigureLogVersions()
|
||||
return versions;
|
||||
}
|
||||
|
||||
void cmFileAPI::WriteReplies()
|
||||
void cmFileAPI::WriteReplies(IndexFor indexFor)
|
||||
{
|
||||
bool const success = indexFor == IndexFor::Success;
|
||||
this->ReplyIndexFor = indexFor;
|
||||
|
||||
if (this->QueryExists) {
|
||||
cmSystemTools::MakeDirectory(this->APIv1 + "/reply");
|
||||
this->WriteJsonFile(this->BuildReplyIndex(), "index", ComputeSuffixTime);
|
||||
this->WriteJsonFile(this->BuildReplyIndex(), success ? "index" : "error",
|
||||
ComputeSuffixTime);
|
||||
}
|
||||
|
||||
this->RemoveOldReplyFiles();
|
||||
if (success) {
|
||||
this->RemoveOldReplyFiles();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> cmFileAPI::LoadDir(std::string const& dir)
|
||||
@@ -453,6 +459,18 @@ Json::Value cmFileAPI::BuildReply(Query const& q)
|
||||
|
||||
Json::Value cmFileAPI::BuildReplyEntry(Object const& object)
|
||||
{
|
||||
if (this->ReplyIndexFor != IndexFor::Success) {
|
||||
switch (object.Kind) {
|
||||
case ObjectKind::ConfigureLog:
|
||||
break;
|
||||
case ObjectKind::CodeModel:
|
||||
case ObjectKind::Cache:
|
||||
case ObjectKind::CMakeFiles:
|
||||
case ObjectKind::Toolchains:
|
||||
case ObjectKind::InternalTest:
|
||||
return this->BuildReplyError("no buildsystem generated");
|
||||
}
|
||||
}
|
||||
return this->AddReplyIndexObject(object);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,8 +27,17 @@ public:
|
||||
/** Get the list of configureLog object kind versions requested. */
|
||||
std::vector<unsigned long> GetConfigureLogVersions();
|
||||
|
||||
/** Identify the situation in which WriteReplies is called. */
|
||||
enum class IndexFor
|
||||
{
|
||||
Success,
|
||||
FailedConfigure,
|
||||
FailedCompute,
|
||||
FailedGenerate,
|
||||
};
|
||||
|
||||
/** Write fileapi replies to disk. */
|
||||
void WriteReplies();
|
||||
void WriteReplies(IndexFor indexFor);
|
||||
|
||||
/** Get the "cmake" instance with which this was constructed. */
|
||||
cmake* GetCMakeInstance() const { return this->CMakeInstance; }
|
||||
@@ -157,6 +166,9 @@ private:
|
||||
This populates the "objects" field of the reply index. */
|
||||
std::map<Object, Json::Value> ReplyIndexObjects;
|
||||
|
||||
/** Identify the situation in which WriteReplies was called. */
|
||||
IndexFor ReplyIndexFor = IndexFor::Success;
|
||||
|
||||
std::unique_ptr<Json::CharReader> JsonReader;
|
||||
std::unique_ptr<Json::StreamWriter> JsonWriter;
|
||||
|
||||
|
||||
@@ -2725,6 +2725,9 @@ int cmake::ActualConfigure()
|
||||
this->Messenger.get());
|
||||
this->SaveCache(this->GetHomeOutputDirectory());
|
||||
if (cmSystemTools::GetErrorOccurredFlag()) {
|
||||
#if !defined(CMAKE_BOOTSTRAP)
|
||||
this->FileAPI->WriteReplies(cmFileAPI::IndexFor::FailedConfigure);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -3041,6 +3044,7 @@ int cmake::Generate()
|
||||
auto profilingRAII = this->CreateProfilingEntry("project", "generate");
|
||||
auto doGenerate = [this]() -> int {
|
||||
if (!this->GlobalGenerator->Compute()) {
|
||||
this->FileAPI->WriteReplies(cmFileAPI::IndexFor::FailedCompute);
|
||||
return -1;
|
||||
}
|
||||
this->GlobalGenerator->Generate();
|
||||
@@ -3080,6 +3084,9 @@ int cmake::Generate()
|
||||
this->RunCheckForUnusedVariables();
|
||||
}
|
||||
if (cmSystemTools::GetErrorOccurredFlag()) {
|
||||
#if !defined(CMAKE_BOOTSTRAP)
|
||||
this->FileAPI->WriteReplies(cmFileAPI::IndexFor::FailedGenerate);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
// Save the cache again after a successful Generate so that any internal
|
||||
@@ -3089,7 +3096,7 @@ int cmake::Generate()
|
||||
|
||||
#if !defined(CMAKE_BOOTSTRAP)
|
||||
this->GlobalGenerator->WriteInstallJson();
|
||||
this->FileAPI->WriteReplies();
|
||||
this->FileAPI->WriteReplies(cmFileAPI::IndexFor::Success);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
22
Tests/RunCMake/FileAPI/FailConfigure-check.cmake
Normal file
22
Tests/RunCMake/FileAPI/FailConfigure-check.cmake
Normal file
@@ -0,0 +1,22 @@
|
||||
set(expect
|
||||
query
|
||||
query/cache-v2
|
||||
query/client-bar
|
||||
query/client-bar/query.json
|
||||
query/client-foo
|
||||
query/client-foo/cache-v2
|
||||
query/client-foo/cmakeFiles-v1
|
||||
query/client-foo/codemodel-v2
|
||||
query/client-foo/configureLog-v1
|
||||
query/client-foo/toolchains-v1
|
||||
query/cmakeFiles-v1
|
||||
query/codemodel-v2
|
||||
query/configureLog-v1
|
||||
query/toolchains-v1
|
||||
reply
|
||||
reply/configureLog-v1-[0-9a-f]+\\.json
|
||||
reply/error-[0-9.T-]+\\.json
|
||||
)
|
||||
check_api("^${expect}$")
|
||||
|
||||
check_python(FailConfigure error)
|
||||
74
Tests/RunCMake/FileAPI/FailConfigure-check.py
Normal file
74
Tests/RunCMake/FileAPI/FailConfigure-check.py
Normal file
@@ -0,0 +1,74 @@
|
||||
from check_index import *
|
||||
import os
|
||||
|
||||
def check_reply(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == [
|
||||
"cache-v2",
|
||||
"client-bar",
|
||||
"client-foo",
|
||||
"cmakeFiles-v1",
|
||||
"codemodel-v2",
|
||||
"configureLog-v1",
|
||||
"toolchains-v1",
|
||||
]
|
||||
check_error(r["cache-v2"], "no buildsystem generated")
|
||||
check_error(r["cmakeFiles-v1"], "no buildsystem generated")
|
||||
check_reply_client_bar(r["client-bar"])
|
||||
check_reply_client_foo(r["client-foo"])
|
||||
check_error(r["codemodel-v2"], "no buildsystem generated")
|
||||
check_index_object(r["configureLog-v1"], "configureLog", 1, 0, None)
|
||||
check_error(r["toolchains-v1"], "no buildsystem generated")
|
||||
|
||||
def check_reply_client_bar(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == ["query.json"]
|
||||
query = r["query.json"]
|
||||
assert sorted(query.keys()) == ["requests", "responses"]
|
||||
requests = query["requests"]
|
||||
assert is_list(requests)
|
||||
assert len(requests) == 5
|
||||
responses = query["responses"]
|
||||
assert is_list(responses)
|
||||
assert len(responses) == 5
|
||||
check_error(responses[0], "no buildsystem generated")
|
||||
check_index_object(responses[1], "configureLog", 1, 0, None)
|
||||
check_error(responses[2], "no buildsystem generated")
|
||||
check_error(responses[3], "no buildsystem generated")
|
||||
check_error(responses[4], "no buildsystem generated")
|
||||
|
||||
def check_reply_client_foo(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == [
|
||||
"cache-v2",
|
||||
"cmakeFiles-v1",
|
||||
"codemodel-v2",
|
||||
"configureLog-v1",
|
||||
"toolchains-v1",
|
||||
]
|
||||
check_error(r["cache-v2"], "no buildsystem generated")
|
||||
check_error(r["cmakeFiles-v1"], "no buildsystem generated")
|
||||
check_error(r["codemodel-v2"], "no buildsystem generated")
|
||||
check_index_object(r["configureLog-v1"], "configureLog", 1, 0, None)
|
||||
check_error(r["toolchains-v1"], "no buildsystem generated")
|
||||
|
||||
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) == ["message-v1", "try_compile-v1", "try_run-v1"]
|
||||
|
||||
assert is_dict(index)
|
||||
assert sorted(index.keys()) == ["cmake", "objects", "reply"]
|
||||
check_cmake(index["cmake"])
|
||||
check_reply(index["reply"])
|
||||
check_objects(index["objects"])
|
||||
26
Tests/RunCMake/FileAPI/FailConfigure-prep.cmake
Normal file
26
Tests/RunCMake/FileAPI/FailConfigure-prep.cmake
Normal file
@@ -0,0 +1,26 @@
|
||||
file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
|
||||
|
||||
# Shared Stateless
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/codemodel-v2" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/configureLog-v1" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/cache-v2" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/cmakeFiles-v1" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/toolchains-v1" "")
|
||||
|
||||
# Client Stateless
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/codemodel-v2" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/configureLog-v1" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/cache-v2" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/cmakeFiles-v1" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/toolchains-v1" "")
|
||||
|
||||
# Client Stateful
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-bar/query.json" [[
|
||||
{ "requests": [
|
||||
{ "kind": "codemodel", "version" : 2 },
|
||||
{ "kind": "configureLog", "version" : 1 },
|
||||
{ "kind": "cache", "version" : 2 },
|
||||
{ "kind": "cmakeFiles", "version" : 1 },
|
||||
{ "kind": "toolchains", "version" : 1 }
|
||||
] }
|
||||
]])
|
||||
1
Tests/RunCMake/FileAPI/FailConfigure-result.txt
Normal file
1
Tests/RunCMake/FileAPI/FailConfigure-result.txt
Normal file
@@ -0,0 +1 @@
|
||||
1
|
||||
4
Tests/RunCMake/FileAPI/FailConfigure-stderr.txt
Normal file
4
Tests/RunCMake/FileAPI/FailConfigure-stderr.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
^CMake Error at FailConfigure.cmake:1 \(message\):
|
||||
Intentionally fail to configure
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
||||
1
Tests/RunCMake/FileAPI/FailConfigure.cmake
Normal file
1
Tests/RunCMake/FileAPI/FailConfigure.cmake
Normal file
@@ -0,0 +1 @@
|
||||
message(FATAL_ERROR "Intentionally fail to configure")
|
||||
@@ -54,6 +54,7 @@ run_cmake(DuplicateStateless)
|
||||
run_cmake(ClientStateful)
|
||||
run_cmake(ProjectQueryGood)
|
||||
run_cmake(ProjectQueryBad)
|
||||
run_cmake(FailConfigure)
|
||||
|
||||
function(run_object object)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${object}-build)
|
||||
@@ -64,6 +65,7 @@ function(run_object object)
|
||||
run_cmake_command(${object}-SharedStateless ${CMAKE_COMMAND} .)
|
||||
run_cmake_command(${object}-ClientStateless ${CMAKE_COMMAND} .)
|
||||
run_cmake_command(${object}-ClientStateful ${CMAKE_COMMAND} .)
|
||||
run_cmake_command(${object}-FailConfigure ${CMAKE_COMMAND} . -DFAIL=1)
|
||||
endfunction()
|
||||
|
||||
run_object(codemodel-v2)
|
||||
|
||||
16
Tests/RunCMake/FileAPI/cache-v2-FailConfigure-check.cmake
Normal file
16
Tests/RunCMake/FileAPI/cache-v2-FailConfigure-check.cmake
Normal file
@@ -0,0 +1,16 @@
|
||||
set(expect
|
||||
query
|
||||
query/cache-v2
|
||||
query/client-bar
|
||||
query/client-bar/query.json
|
||||
query/client-foo
|
||||
query/client-foo/cache-v2
|
||||
reply
|
||||
reply/cache-v2-[0-9a-f]+\\.json
|
||||
reply/error-[0-9.T-]+.json
|
||||
reply/index-[0-9.T-]+.json
|
||||
)
|
||||
check_api("^${expect}$")
|
||||
|
||||
check_python(cache-v2-FailConfigure error)
|
||||
check_python(cache-v2 index) # Last-good index is intact.
|
||||
43
Tests/RunCMake/FileAPI/cache-v2-FailConfigure-check.py
Normal file
43
Tests/RunCMake/FileAPI/cache-v2-FailConfigure-check.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from check_index import *
|
||||
import os
|
||||
|
||||
def check_reply(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == [
|
||||
"cache-v2",
|
||||
"client-bar",
|
||||
"client-foo",
|
||||
]
|
||||
check_error(r["cache-v2"], "no buildsystem generated")
|
||||
check_reply_client_bar(r["client-bar"])
|
||||
check_reply_client_foo(r["client-foo"])
|
||||
|
||||
def check_reply_client_bar(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == ["query.json"]
|
||||
query = r["query.json"]
|
||||
assert sorted(query.keys()) == ["requests", "responses"]
|
||||
requests = query["requests"]
|
||||
assert is_list(requests)
|
||||
assert len(requests) == 1
|
||||
responses = query["responses"]
|
||||
assert is_list(responses)
|
||||
assert len(responses) == 1
|
||||
check_error(responses[0], "no buildsystem generated")
|
||||
|
||||
def check_reply_client_foo(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == [
|
||||
"cache-v2",
|
||||
]
|
||||
check_error(r["cache-v2"], "no buildsystem generated")
|
||||
|
||||
def check_objects(o):
|
||||
assert is_list(o)
|
||||
assert len(o) == 0
|
||||
|
||||
assert is_dict(index)
|
||||
assert sorted(index.keys()) == ["cmake", "objects", "reply"]
|
||||
check_cmake(index["cmake"])
|
||||
check_reply(index["reply"])
|
||||
check_objects(index["objects"])
|
||||
6
Tests/RunCMake/FileAPI/cache-v2-FailConfigure-prep.cmake
Normal file
6
Tests/RunCMake/FileAPI/cache-v2-FailConfigure-prep.cmake
Normal file
@@ -0,0 +1,6 @@
|
||||
file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/cache-v2" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/cache-v2" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-bar/query.json" [[
|
||||
{ "requests": [ { "kind": "cache", "version" : 2 } ] }
|
||||
]])
|
||||
1
Tests/RunCMake/FileAPI/cache-v2-FailConfigure-result.txt
Normal file
1
Tests/RunCMake/FileAPI/cache-v2-FailConfigure-result.txt
Normal file
@@ -0,0 +1 @@
|
||||
1
|
||||
4
Tests/RunCMake/FileAPI/cache-v2-FailConfigure-stderr.txt
Normal file
4
Tests/RunCMake/FileAPI/cache-v2-FailConfigure-stderr.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
^CMake Error at cache-v2.cmake:[0-9]+ \(message\):
|
||||
Intentionally fail to configure
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
||||
@@ -12,3 +12,7 @@ set_property(CACHE CM_SET_INTERNAL PROPERTY VALUE "int2")
|
||||
set(CM_SET_TYPE "1" CACHE INTERNAL "Testing set(CACHE INTERNAL) with set_property(TYPE)")
|
||||
set_property(CACHE CM_SET_TYPE PROPERTY TYPE "STRING")
|
||||
set_property(CACHE CM_SET_TYPE PROPERTY ADVANCED "0")
|
||||
|
||||
if(FAIL)
|
||||
message(FATAL_ERROR "Intentionally fail to configure")
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
set(expect
|
||||
query
|
||||
query/client-bar
|
||||
query/client-bar/query.json
|
||||
query/client-foo
|
||||
query/client-foo/cmakeFiles-v1
|
||||
query/cmakeFiles-v1
|
||||
reply
|
||||
reply/cmakeFiles-v1-[0-9a-f]+\\.json
|
||||
reply/error-[0-9.T-]+.json
|
||||
reply/index-[0-9.T-]+.json
|
||||
)
|
||||
check_api("^${expect}$")
|
||||
|
||||
check_python(cmakeFiles-v1-FailConfigure error)
|
||||
check_python(cmakeFiles-v1 index) # Last-good index is intact.
|
||||
43
Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-check.py
Normal file
43
Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-check.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from check_index import *
|
||||
import os
|
||||
|
||||
def check_reply(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == [
|
||||
"client-bar",
|
||||
"client-foo",
|
||||
"cmakeFiles-v1",
|
||||
]
|
||||
check_reply_client_bar(r["client-bar"])
|
||||
check_reply_client_foo(r["client-foo"])
|
||||
check_error(r["cmakeFiles-v1"], "no buildsystem generated")
|
||||
|
||||
def check_reply_client_bar(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == ["query.json"]
|
||||
query = r["query.json"]
|
||||
assert sorted(query.keys()) == ["requests", "responses"]
|
||||
requests = query["requests"]
|
||||
assert is_list(requests)
|
||||
assert len(requests) == 1
|
||||
responses = query["responses"]
|
||||
assert is_list(responses)
|
||||
assert len(responses) == 1
|
||||
check_error(responses[0], "no buildsystem generated")
|
||||
|
||||
def check_reply_client_foo(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == [
|
||||
"cmakeFiles-v1",
|
||||
]
|
||||
check_error(r["cmakeFiles-v1"], "no buildsystem generated")
|
||||
|
||||
def check_objects(o):
|
||||
assert is_list(o)
|
||||
assert len(o) == 0
|
||||
|
||||
assert is_dict(index)
|
||||
assert sorted(index.keys()) == ["cmake", "objects", "reply"]
|
||||
check_cmake(index["cmake"])
|
||||
check_reply(index["reply"])
|
||||
check_objects(index["objects"])
|
||||
@@ -0,0 +1,6 @@
|
||||
file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/cmakeFiles-v1" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/cmakeFiles-v1" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-bar/query.json" [[
|
||||
{ "requests": [ { "kind": "cmakeFiles", "version" : 1 } ] }
|
||||
]])
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
^CMake Error at cmakeFiles-v1.cmake:[0-9]+ \(message\):
|
||||
Intentionally fail to configure
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
||||
@@ -16,3 +16,7 @@ file(GLOB_RECURSE var
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dir/*.cmake")
|
||||
|
||||
add_subdirectory(dir)
|
||||
|
||||
if(FAIL)
|
||||
message(FATAL_ERROR "Intentionally fail to configure")
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
set(expect
|
||||
query
|
||||
query/client-bar
|
||||
query/client-bar/query.json
|
||||
query/client-foo
|
||||
query/client-foo/codemodel-v2
|
||||
query/codemodel-v2
|
||||
reply
|
||||
reply/codemodel-v2-[0-9a-f]+\\.json
|
||||
.*
|
||||
reply/error-[0-9.T-]+.json
|
||||
reply/index-[0-9.T-]+.json
|
||||
.*
|
||||
)
|
||||
check_api("^${expect}$")
|
||||
|
||||
check_python(codemodel-v2-FailConfigure error)
|
||||
check_python(codemodel-v2 index) # Last-good index is intact.
|
||||
43
Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-check.py
Normal file
43
Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-check.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from check_index import *
|
||||
import os
|
||||
|
||||
def check_reply(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == [
|
||||
"client-bar",
|
||||
"client-foo",
|
||||
"codemodel-v2",
|
||||
]
|
||||
check_reply_client_bar(r["client-bar"])
|
||||
check_reply_client_foo(r["client-foo"])
|
||||
check_error(r["codemodel-v2"], "no buildsystem generated")
|
||||
|
||||
def check_reply_client_bar(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == ["query.json"]
|
||||
query = r["query.json"]
|
||||
assert sorted(query.keys()) == ["requests", "responses"]
|
||||
requests = query["requests"]
|
||||
assert is_list(requests)
|
||||
assert len(requests) == 1
|
||||
responses = query["responses"]
|
||||
assert is_list(responses)
|
||||
assert len(responses) == 1
|
||||
check_error(responses[0], "no buildsystem generated")
|
||||
|
||||
def check_reply_client_foo(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == [
|
||||
"codemodel-v2",
|
||||
]
|
||||
check_error(r["codemodel-v2"], "no buildsystem generated")
|
||||
|
||||
def check_objects(o):
|
||||
assert is_list(o)
|
||||
assert len(o) == 0
|
||||
|
||||
assert is_dict(index)
|
||||
assert sorted(index.keys()) == ["cmake", "objects", "reply"]
|
||||
check_cmake(index["cmake"])
|
||||
check_reply(index["reply"])
|
||||
check_objects(index["objects"])
|
||||
@@ -0,0 +1,6 @@
|
||||
file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/codemodel-v2" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/codemodel-v2" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-bar/query.json" [[
|
||||
{ "requests": [ { "kind": "codemodel", "version" : 2 } ] }
|
||||
]])
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
^CMake Error at codemodel-v2.cmake:[0-9]+ \(message\):
|
||||
Intentionally fail to configure
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
||||
@@ -60,3 +60,7 @@ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/dir
|
||||
install(EXPORT FooTargets DESTINATION lib/cmake/foo)
|
||||
install(SCRIPT InstallScript.cmake)
|
||||
install(CODE "message(foo)" ALL_COMPONENTS)
|
||||
|
||||
if(FAIL)
|
||||
message(FATAL_ERROR "Intentionally fail to configure")
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
set(expect
|
||||
query
|
||||
query/client-bar
|
||||
query/client-bar/query.json
|
||||
query/client-foo
|
||||
query/client-foo/configureLog-v1
|
||||
query/configureLog-v1
|
||||
reply
|
||||
reply/configureLog-v1-[0-9a-f]+.json
|
||||
reply/error-[0-9.T-]+.json
|
||||
reply/index-[0-9.T-]+.json
|
||||
)
|
||||
check_api("^${expect}$")
|
||||
|
||||
check_python(configureLog-v1-FailConfigure error)
|
||||
check_python(configureLog-v1 index) # Last-good index is intact.
|
||||
@@ -0,0 +1,54 @@
|
||||
from check_index import *
|
||||
import os
|
||||
|
||||
def check_reply(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == [
|
||||
"client-bar",
|
||||
"client-foo",
|
||||
"configureLog-v1",
|
||||
]
|
||||
check_reply_client_bar(r["client-bar"])
|
||||
check_reply_client_foo(r["client-foo"])
|
||||
check_index_object(r["configureLog-v1"], "configureLog", 1, 0, None)
|
||||
|
||||
def check_reply_client_bar(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == ["query.json"]
|
||||
query = r["query.json"]
|
||||
assert sorted(query.keys()) == ["requests", "responses"]
|
||||
requests = query["requests"]
|
||||
assert is_list(requests)
|
||||
assert len(requests) == 1
|
||||
responses = query["responses"]
|
||||
assert is_list(responses)
|
||||
assert len(responses) == 1
|
||||
check_index_object(responses[0], "configureLog", 1, 0, None)
|
||||
|
||||
def check_reply_client_foo(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == [
|
||||
"configureLog-v1",
|
||||
]
|
||||
check_index_object(r["configureLog-v1"], "configureLog", 1, 0, None)
|
||||
|
||||
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) == ["message-v1", "try_compile-v1", "try_run-v1"]
|
||||
|
||||
assert is_dict(index)
|
||||
assert sorted(index.keys()) == ["cmake", "objects", "reply"]
|
||||
check_cmake(index["cmake"])
|
||||
check_reply(index["reply"])
|
||||
check_objects(index["objects"])
|
||||
@@ -0,0 +1,6 @@
|
||||
file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/configureLog-v1" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/configureLog-v1" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-bar/query.json" [[
|
||||
{ "requests": [ { "kind": "configureLog", "version" : 1 } ] }
|
||||
]])
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
^CMake Error at configureLog-v1.cmake:[0-9]+ \(message\):
|
||||
Intentionally fail to configure
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
||||
@@ -1 +1,4 @@
|
||||
enable_language(C)
|
||||
if(FAIL)
|
||||
message(FATAL_ERROR "Intentionally fail to configure")
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
set(expect
|
||||
query
|
||||
query/client-bar
|
||||
query/client-bar/query.json
|
||||
query/client-foo
|
||||
query/client-foo/toolchains-v1
|
||||
query/toolchains-v1
|
||||
reply
|
||||
reply/error-[0-9.T-]+.json
|
||||
reply/index-[0-9.T-]+.json
|
||||
reply/toolchains-v1-[0-9a-f]+\\.json
|
||||
)
|
||||
check_api("^${expect}$")
|
||||
|
||||
check_python(toolchains-v1-FailConfigure error)
|
||||
check_python(toolchains-v1 index) # Last-good index is intact.
|
||||
43
Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-check.py
Normal file
43
Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-check.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from check_index import *
|
||||
import os
|
||||
|
||||
def check_reply(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == [
|
||||
"client-bar",
|
||||
"client-foo",
|
||||
"toolchains-v1",
|
||||
]
|
||||
check_reply_client_bar(r["client-bar"])
|
||||
check_reply_client_foo(r["client-foo"])
|
||||
check_error(r["toolchains-v1"], "no buildsystem generated")
|
||||
|
||||
def check_reply_client_bar(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == ["query.json"]
|
||||
query = r["query.json"]
|
||||
assert sorted(query.keys()) == ["requests", "responses"]
|
||||
requests = query["requests"]
|
||||
assert is_list(requests)
|
||||
assert len(requests) == 1
|
||||
responses = query["responses"]
|
||||
assert is_list(responses)
|
||||
assert len(responses) == 1
|
||||
check_error(responses[0], "no buildsystem generated")
|
||||
|
||||
def check_reply_client_foo(r):
|
||||
assert is_dict(r)
|
||||
assert sorted(r.keys()) == [
|
||||
"toolchains-v1",
|
||||
]
|
||||
check_error(r["toolchains-v1"], "no buildsystem generated")
|
||||
|
||||
def check_objects(o):
|
||||
assert is_list(o)
|
||||
assert len(o) == 0
|
||||
|
||||
assert is_dict(index)
|
||||
assert sorted(index.keys()) == ["cmake", "objects", "reply"]
|
||||
check_cmake(index["cmake"])
|
||||
check_reply(index["reply"])
|
||||
check_objects(index["objects"])
|
||||
@@ -0,0 +1,6 @@
|
||||
file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/toolchains-v1" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/toolchains-v1" "")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-bar/query.json" [[
|
||||
{ "requests": [ { "kind": "toolchains", "version" : 1 } ] }
|
||||
]])
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
^CMake Error at toolchains-v1.cmake:[0-9]+ \(message\):
|
||||
Intentionally fail to configure
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
||||
@@ -20,3 +20,7 @@ foreach(variable_suffix ${variable_suffixes})
|
||||
endforeach()
|
||||
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/toolchain_variables.json "${json}")
|
||||
|
||||
if(FAIL)
|
||||
message(FATAL_ERROR "Intentionally fail to configure")
|
||||
endif()
|
||||
|
||||
Reference in New Issue
Block a user