From 0cc962665bc6d70ae9996b7c9c5f4086bea0ec45 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 14 Apr 2025 09:34:24 -0400 Subject: [PATCH] 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 --- Help/manual/cmake-file-api.7.rst | 67 ++++++++++++++--- Help/release/dev/fileapi-reply-on-failure.rst | 6 ++ Source/cmFileAPI.cxx | 24 +++++- Source/cmFileAPI.h | 14 +++- Source/cmake.cxx | 9 ++- .../FileAPI/FailConfigure-check.cmake | 22 ++++++ Tests/RunCMake/FileAPI/FailConfigure-check.py | 74 +++++++++++++++++++ .../RunCMake/FileAPI/FailConfigure-prep.cmake | 26 +++++++ .../RunCMake/FileAPI/FailConfigure-result.txt | 1 + .../RunCMake/FileAPI/FailConfigure-stderr.txt | 4 + Tests/RunCMake/FileAPI/FailConfigure.cmake | 1 + Tests/RunCMake/FileAPI/RunCMakeTest.cmake | 2 + .../cache-v2-FailConfigure-check.cmake | 16 ++++ .../FileAPI/cache-v2-FailConfigure-check.py | 43 +++++++++++ .../FileAPI/cache-v2-FailConfigure-prep.cmake | 6 ++ .../FileAPI/cache-v2-FailConfigure-result.txt | 1 + .../FileAPI/cache-v2-FailConfigure-stderr.txt | 4 + Tests/RunCMake/FileAPI/cache-v2.cmake | 4 + .../cmakeFiles-v1-FailConfigure-check.cmake | 16 ++++ .../cmakeFiles-v1-FailConfigure-check.py | 43 +++++++++++ .../cmakeFiles-v1-FailConfigure-prep.cmake | 6 ++ .../cmakeFiles-v1-FailConfigure-result.txt | 1 + .../cmakeFiles-v1-FailConfigure-stderr.txt | 4 + Tests/RunCMake/FileAPI/cmakeFiles-v1.cmake | 4 + .../codemodel-v2-FailConfigure-check.cmake | 18 +++++ .../codemodel-v2-FailConfigure-check.py | 43 +++++++++++ .../codemodel-v2-FailConfigure-prep.cmake | 6 ++ .../codemodel-v2-FailConfigure-result.txt | 1 + .../codemodel-v2-FailConfigure-stderr.txt | 4 + Tests/RunCMake/FileAPI/codemodel-v2.cmake | 4 + .../configureLog-v1-FailConfigure-check.cmake | 16 ++++ .../configureLog-v1-FailConfigure-check.py | 54 ++++++++++++++ .../configureLog-v1-FailConfigure-prep.cmake | 6 ++ .../configureLog-v1-FailConfigure-result.txt | 1 + .../configureLog-v1-FailConfigure-stderr.txt | 4 + Tests/RunCMake/FileAPI/configureLog-v1.cmake | 3 + .../toolchains-v1-FailConfigure-check.cmake | 16 ++++ .../toolchains-v1-FailConfigure-check.py | 43 +++++++++++ .../toolchains-v1-FailConfigure-prep.cmake | 6 ++ .../toolchains-v1-FailConfigure-result.txt | 1 + .../toolchains-v1-FailConfigure-stderr.txt | 4 + Tests/RunCMake/FileAPI/toolchains-v1.cmake | 4 + 42 files changed, 616 insertions(+), 16 deletions(-) create mode 100644 Help/release/dev/fileapi-reply-on-failure.rst create mode 100644 Tests/RunCMake/FileAPI/FailConfigure-check.cmake create mode 100644 Tests/RunCMake/FileAPI/FailConfigure-check.py create mode 100644 Tests/RunCMake/FileAPI/FailConfigure-prep.cmake create mode 100644 Tests/RunCMake/FileAPI/FailConfigure-result.txt create mode 100644 Tests/RunCMake/FileAPI/FailConfigure-stderr.txt create mode 100644 Tests/RunCMake/FileAPI/FailConfigure.cmake create mode 100644 Tests/RunCMake/FileAPI/cache-v2-FailConfigure-check.cmake create mode 100644 Tests/RunCMake/FileAPI/cache-v2-FailConfigure-check.py create mode 100644 Tests/RunCMake/FileAPI/cache-v2-FailConfigure-prep.cmake create mode 100644 Tests/RunCMake/FileAPI/cache-v2-FailConfigure-result.txt create mode 100644 Tests/RunCMake/FileAPI/cache-v2-FailConfigure-stderr.txt create mode 100644 Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-check.cmake create mode 100644 Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-check.py create mode 100644 Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-prep.cmake create mode 100644 Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-result.txt create mode 100644 Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-stderr.txt create mode 100644 Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-check.cmake create mode 100644 Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-check.py create mode 100644 Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-prep.cmake create mode 100644 Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-result.txt create mode 100644 Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-stderr.txt create mode 100644 Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-check.cmake create mode 100644 Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-check.py create mode 100644 Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-prep.cmake create mode 100644 Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-result.txt create mode 100644 Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-stderr.txt create mode 100644 Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-check.cmake create mode 100644 Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-check.py create mode 100644 Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-prep.cmake create mode 100644 Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-result.txt create mode 100644 Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-stderr.txt diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst index 6ff4f77f38..f61cff5d17 100644 --- a/Help/manual/cmake-file-api.7.rst +++ b/Help/manual/cmake-file-api.7.rst @@ -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 ```` with major version ````. - 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. ```` 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 ```` with major version ````. - 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. ```` 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 `_ + .. versionadded:: 4.1 + + Index entries for other object kinds contain an ``error`` message + instead of a `v1 Reply File Reference`_. + v1 Reply Files -------------- diff --git a/Help/release/dev/fileapi-reply-on-failure.rst b/Help/release/dev/fileapi-reply-on-failure.rst new file mode 100644 index 0000000000..02bb5373a4 --- /dev/null +++ b/Help/release/dev/fileapi-reply-on-failure.rst @@ -0,0 +1,6 @@ +fileapi-reply-on-failure +------------------------ + +* The :manual:`cmake-file-api(7)` :ref:`v1 ` now writes + partial replies when buildsystem generation fails with an error. + See the :ref:`v1 Reply Error Index `. diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx index 3ce8749d17..4533392baf 100644 --- a/Source/cmFileAPI.cxx +++ b/Source/cmFileAPI.cxx @@ -105,14 +105,20 @@ std::vector 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 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); } diff --git a/Source/cmFileAPI.h b/Source/cmFileAPI.h index 8cdf828135..5b639ced44 100644 --- a/Source/cmFileAPI.h +++ b/Source/cmFileAPI.h @@ -27,8 +27,17 @@ public: /** Get the list of configureLog object kind versions requested. */ std::vector 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 ReplyIndexObjects; + /** Identify the situation in which WriteReplies was called. */ + IndexFor ReplyIndexFor = IndexFor::Success; + std::unique_ptr JsonReader; std::unique_ptr JsonWriter; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index e1edf45b47..1f424ab25b 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -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; diff --git a/Tests/RunCMake/FileAPI/FailConfigure-check.cmake b/Tests/RunCMake/FileAPI/FailConfigure-check.cmake new file mode 100644 index 0000000000..f136f4b21b --- /dev/null +++ b/Tests/RunCMake/FileAPI/FailConfigure-check.cmake @@ -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) diff --git a/Tests/RunCMake/FileAPI/FailConfigure-check.py b/Tests/RunCMake/FileAPI/FailConfigure-check.py new file mode 100644 index 0000000000..a1531d95a1 --- /dev/null +++ b/Tests/RunCMake/FileAPI/FailConfigure-check.py @@ -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"]) diff --git a/Tests/RunCMake/FileAPI/FailConfigure-prep.cmake b/Tests/RunCMake/FileAPI/FailConfigure-prep.cmake new file mode 100644 index 0000000000..70cb654c34 --- /dev/null +++ b/Tests/RunCMake/FileAPI/FailConfigure-prep.cmake @@ -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 } + ] } +]]) diff --git a/Tests/RunCMake/FileAPI/FailConfigure-result.txt b/Tests/RunCMake/FileAPI/FailConfigure-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/FileAPI/FailConfigure-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/FileAPI/FailConfigure-stderr.txt b/Tests/RunCMake/FileAPI/FailConfigure-stderr.txt new file mode 100644 index 0000000000..4ff5940276 --- /dev/null +++ b/Tests/RunCMake/FileAPI/FailConfigure-stderr.txt @@ -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\)$ diff --git a/Tests/RunCMake/FileAPI/FailConfigure.cmake b/Tests/RunCMake/FileAPI/FailConfigure.cmake new file mode 100644 index 0000000000..475780a612 --- /dev/null +++ b/Tests/RunCMake/FileAPI/FailConfigure.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "Intentionally fail to configure") diff --git a/Tests/RunCMake/FileAPI/RunCMakeTest.cmake b/Tests/RunCMake/FileAPI/RunCMakeTest.cmake index 12c61496d4..bf9354ef43 100644 --- a/Tests/RunCMake/FileAPI/RunCMakeTest.cmake +++ b/Tests/RunCMake/FileAPI/RunCMakeTest.cmake @@ -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) diff --git a/Tests/RunCMake/FileAPI/cache-v2-FailConfigure-check.cmake b/Tests/RunCMake/FileAPI/cache-v2-FailConfigure-check.cmake new file mode 100644 index 0000000000..624cee77ba --- /dev/null +++ b/Tests/RunCMake/FileAPI/cache-v2-FailConfigure-check.cmake @@ -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. diff --git a/Tests/RunCMake/FileAPI/cache-v2-FailConfigure-check.py b/Tests/RunCMake/FileAPI/cache-v2-FailConfigure-check.py new file mode 100644 index 0000000000..186a58eec2 --- /dev/null +++ b/Tests/RunCMake/FileAPI/cache-v2-FailConfigure-check.py @@ -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"]) diff --git a/Tests/RunCMake/FileAPI/cache-v2-FailConfigure-prep.cmake b/Tests/RunCMake/FileAPI/cache-v2-FailConfigure-prep.cmake new file mode 100644 index 0000000000..11132c2bea --- /dev/null +++ b/Tests/RunCMake/FileAPI/cache-v2-FailConfigure-prep.cmake @@ -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 } ] } +]]) diff --git a/Tests/RunCMake/FileAPI/cache-v2-FailConfigure-result.txt b/Tests/RunCMake/FileAPI/cache-v2-FailConfigure-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/FileAPI/cache-v2-FailConfigure-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/FileAPI/cache-v2-FailConfigure-stderr.txt b/Tests/RunCMake/FileAPI/cache-v2-FailConfigure-stderr.txt new file mode 100644 index 0000000000..91bce759d1 --- /dev/null +++ b/Tests/RunCMake/FileAPI/cache-v2-FailConfigure-stderr.txt @@ -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\)$ diff --git a/Tests/RunCMake/FileAPI/cache-v2.cmake b/Tests/RunCMake/FileAPI/cache-v2.cmake index 45b402de68..fb71f0401d 100644 --- a/Tests/RunCMake/FileAPI/cache-v2.cmake +++ b/Tests/RunCMake/FileAPI/cache-v2.cmake @@ -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() diff --git a/Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-check.cmake b/Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-check.cmake new file mode 100644 index 0000000000..68a32b810c --- /dev/null +++ b/Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-check.cmake @@ -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. diff --git a/Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-check.py b/Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-check.py new file mode 100644 index 0000000000..49d095f7b5 --- /dev/null +++ b/Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-check.py @@ -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"]) diff --git a/Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-prep.cmake b/Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-prep.cmake new file mode 100644 index 0000000000..c65dd07c91 --- /dev/null +++ b/Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-prep.cmake @@ -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 } ] } +]]) diff --git a/Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-result.txt b/Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-stderr.txt b/Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-stderr.txt new file mode 100644 index 0000000000..a846cadc7e --- /dev/null +++ b/Tests/RunCMake/FileAPI/cmakeFiles-v1-FailConfigure-stderr.txt @@ -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\)$ diff --git a/Tests/RunCMake/FileAPI/cmakeFiles-v1.cmake b/Tests/RunCMake/FileAPI/cmakeFiles-v1.cmake index b98a283093..855703fab7 100644 --- a/Tests/RunCMake/FileAPI/cmakeFiles-v1.cmake +++ b/Tests/RunCMake/FileAPI/cmakeFiles-v1.cmake @@ -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() diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-check.cmake b/Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-check.cmake new file mode 100644 index 0000000000..a794b55e39 --- /dev/null +++ b/Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-check.cmake @@ -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. diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-check.py new file mode 100644 index 0000000000..80a6bf8b47 --- /dev/null +++ b/Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-check.py @@ -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"]) diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-prep.cmake b/Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-prep.cmake new file mode 100644 index 0000000000..2fc3b2b181 --- /dev/null +++ b/Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-prep.cmake @@ -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 } ] } +]]) diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-result.txt b/Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-stderr.txt b/Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-stderr.txt new file mode 100644 index 0000000000..762f3ab71b --- /dev/null +++ b/Tests/RunCMake/FileAPI/codemodel-v2-FailConfigure-stderr.txt @@ -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\)$ diff --git a/Tests/RunCMake/FileAPI/codemodel-v2.cmake b/Tests/RunCMake/FileAPI/codemodel-v2.cmake index 42bdceab28..d2c337840e 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2.cmake +++ b/Tests/RunCMake/FileAPI/codemodel-v2.cmake @@ -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() diff --git a/Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-check.cmake b/Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-check.cmake new file mode 100644 index 0000000000..8091f6a567 --- /dev/null +++ b/Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-check.cmake @@ -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. diff --git a/Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-check.py b/Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-check.py new file mode 100644 index 0000000000..19041d8526 --- /dev/null +++ b/Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-check.py @@ -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"]) diff --git a/Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-prep.cmake b/Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-prep.cmake new file mode 100644 index 0000000000..242dcf07cb --- /dev/null +++ b/Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-prep.cmake @@ -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 } ] } +]]) diff --git a/Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-result.txt b/Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-stderr.txt b/Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-stderr.txt new file mode 100644 index 0000000000..a81fe85cd3 --- /dev/null +++ b/Tests/RunCMake/FileAPI/configureLog-v1-FailConfigure-stderr.txt @@ -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\)$ diff --git a/Tests/RunCMake/FileAPI/configureLog-v1.cmake b/Tests/RunCMake/FileAPI/configureLog-v1.cmake index c00af08d10..ee00d8553c 100644 --- a/Tests/RunCMake/FileAPI/configureLog-v1.cmake +++ b/Tests/RunCMake/FileAPI/configureLog-v1.cmake @@ -1 +1,4 @@ enable_language(C) +if(FAIL) + message(FATAL_ERROR "Intentionally fail to configure") +endif() diff --git a/Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-check.cmake b/Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-check.cmake new file mode 100644 index 0000000000..bfa141c5fb --- /dev/null +++ b/Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-check.cmake @@ -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. diff --git a/Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-check.py b/Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-check.py new file mode 100644 index 0000000000..73d53b2513 --- /dev/null +++ b/Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-check.py @@ -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"]) diff --git a/Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-prep.cmake b/Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-prep.cmake new file mode 100644 index 0000000000..d0bd1003ac --- /dev/null +++ b/Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-prep.cmake @@ -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 } ] } +]]) diff --git a/Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-result.txt b/Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-stderr.txt b/Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-stderr.txt new file mode 100644 index 0000000000..a99632f033 --- /dev/null +++ b/Tests/RunCMake/FileAPI/toolchains-v1-FailConfigure-stderr.txt @@ -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\)$ diff --git a/Tests/RunCMake/FileAPI/toolchains-v1.cmake b/Tests/RunCMake/FileAPI/toolchains-v1.cmake index 367aadef59..1ad777dd29 100644 --- a/Tests/RunCMake/FileAPI/toolchains-v1.cmake +++ b/Tests/RunCMake/FileAPI/toolchains-v1.cmake @@ -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()