summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/command/cmake_file_api.rst78
-rw-r--r--Help/manual/cmake-commands.7.rst1
-rw-r--r--Help/manual/cmake-file-api.7.rst6
-rw-r--r--Help/release/dev/file-api-query-command.rst6
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/cmCommands.cxx3
-rw-r--r--Source/cmFileAPI.cxx42
-rw-r--r--Source/cmFileAPI.h33
-rw-r--r--Source/cmFileAPICommand.cxx170
-rw-r--r--Source/cmFileAPICommand.h13
-rw-r--r--Source/cmake.h4
-rw-r--r--Tests/RunCMake/FileAPI/ProjectQueryBad-result.txt1
-rw-r--r--Tests/RunCMake/FileAPI/ProjectQueryBad-stderr.txt36
-rw-r--r--Tests/RunCMake/FileAPI/ProjectQueryBad.cmake42
-rw-r--r--Tests/RunCMake/FileAPI/ProjectQueryGood-check.cmake11
-rw-r--r--Tests/RunCMake/FileAPI/ProjectQueryGood.cmake8
-rw-r--r--Tests/RunCMake/FileAPI/RunCMakeTest.cmake2
17 files changed, 447 insertions, 11 deletions
diff --git a/Help/command/cmake_file_api.rst b/Help/command/cmake_file_api.rst
new file mode 100644
index 0000000..e7ee7e7
--- /dev/null
+++ b/Help/command/cmake_file_api.rst
@@ -0,0 +1,78 @@
+cmake_file_api
+--------------
+
+.. versionadded:: 3.27
+
+Enables interacting with the :manual:`CMake file API <cmake-file-api(7)>`.
+
+.. signature::
+ cmake_file_api(QUERY ...)
+
+ The ``QUERY`` subcommand adds a file API query for the current CMake
+ invocation.
+
+ .. code-block:: cmake
+
+ cmake_file_api(
+ QUERY
+ API_VERSION <version>
+ [CODEMODEL <versions>...]
+ [CACHE <versions>...]
+ [CMAKEFILES <versions>...]
+ [TOOLCHAINS <versions>...]
+ )
+
+ The ``API_VERSION`` must always be given. Currently, the only supported
+ value for ``<version>`` is 1. See :ref:`file-api v1` for details of the
+ reply content and location.
+
+ Each of the optional keywords ``CODEMODEL``, ``CACHE``, ``CMAKEFILES`` and
+ ``TOOLCHAINS`` correspond to one of the object kinds that can be requested
+ by the project. The ``configureLog`` object kind cannot be set with this
+ command, since it must be set before CMake starts reading the top level
+ ``CMakeLists.txt`` file.
+
+ For each of the optional keywords, the ``<versions>`` list must contain one
+ or more version values of the form ``major`` or ``major.minor``, where
+ ``major`` and ``minor`` are integers. Projects should list the versions they
+ accept in their preferred order, as only the first supported value from the
+ list will be selected. The command will ignore versions with a ``major``
+ version higher than any major version it supports for that object kind.
+ It will raise an error if it encounters an invalid version number, or if none
+ of the requested versions is supported.
+
+ For each type of object kind requested, a query equivalent to a shared,
+ stateless query will be added internally. No query file will be created in
+ the file system. The reply *will* be written to the file system at
+ generation time.
+
+ It is not an error to add a query for the same thing more than once, whether
+ from query files or from multiple calls to ``cmake_file_api(QUERY)``.
+ The final set of queries will be a merged combination of all queries
+ specified on disk and queries submitted by the project.
+
+Example
+^^^^^^^
+
+A project may want to use replies from the file API at build time to implement
+some form of verification task. Instead of relying on something outside of
+CMake to create a query file, the project can use ``cmake_file_api(QUERY)``
+to request the required information for the current run. It can then create
+a custom command to run at build time, knowing that the requested information
+should always be available.
+
+.. code-block:: cmake
+
+ cmake_file_api(
+ QUERY
+ API_VERSION 1
+ CODEMODEL 2.3
+ TOOLCHAINS 1
+ )
+
+ add_custom_target(verify_project
+ COMMAND ${CMAKE_COMMAND}
+ -D BUILD_DIR=${CMAKE_BINARY_DIR}
+ -D CONFIG=$<CONFIG>
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/verify_project.cmake
+ )
diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst
index 0f35632..bd678b7 100644
--- a/Help/manual/cmake-commands.7.rst
+++ b/Help/manual/cmake-commands.7.rst
@@ -87,6 +87,7 @@ These commands are available only in CMake projects.
/command/add_test
/command/aux_source_directory
/command/build_command
+ /command/cmake_file_api
/command/create_test_sourcelist
/command/define_property
/command/enable_language
diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst
index 0bdb419..5f16a8b 100644
--- a/Help/manual/cmake-file-api.7.rst
+++ b/Help/manual/cmake-file-api.7.rst
@@ -23,6 +23,12 @@ of files within the API directory. API file layout versioning is
orthogonal to the versioning of `Object Kinds`_ used in replies.
This version of CMake supports only one API version, `API v1`_.
+.. versionadded:: 3.27
+ Projects may also submit queries for the current run using the
+ :command:`cmake_file_api` command.
+
+.. _`file-api v1`:
+
API v1
======
diff --git a/Help/release/dev/file-api-query-command.rst b/Help/release/dev/file-api-query-command.rst
new file mode 100644
index 0000000..66ae7d9
--- /dev/null
+++ b/Help/release/dev/file-api-query-command.rst
@@ -0,0 +1,6 @@
+file-api-query-command
+----------------------
+
+* The :command:`cmake_file_api` command was added, enabling projects to
+ add :manual:`CMake file API <cmake-file-api(7)>` queries for the current
+ CMake run.
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index bcaf890..b01e1e7 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -232,6 +232,8 @@ add_library(
cmFileAPIConfigureLog.h
cmFileAPICMakeFiles.cxx
cmFileAPICMakeFiles.h
+ cmFileAPICommand.cxx
+ cmFileAPICommand.h
cmFileAPIToolchains.cxx
cmFileAPIToolchains.h
cmFileCopier.cxx
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 27f2156..ae83b2e 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -97,6 +97,7 @@
# include "cmExportCommand.h"
# include "cmExportLibraryDependenciesCommand.h"
# include "cmFLTKWrapUICommand.h"
+# include "cmFileAPICommand.h"
# include "cmIncludeExternalMSProjectCommand.h"
# include "cmInstallProgramsCommand.h"
# include "cmLinkLibrariesCommand.h"
@@ -293,6 +294,7 @@ void GetProjectCommands(cmState* state)
state->AddBuiltinCommand("qt_wrap_ui", cmQTWrapUICommand);
state->AddBuiltinCommand("remove_definitions", cmRemoveDefinitionsCommand);
state->AddBuiltinCommand("source_group", cmSourceGroupCommand);
+ state->AddBuiltinCommand("cmake_file_api", cmFileAPICommand);
state->AddDisallowedCommand(
"export_library_dependencies", cmExportLibraryDependenciesCommand,
@@ -333,6 +335,7 @@ void GetProjectCommandsInScriptMode(cmState* state)
CM_UNEXPECTED_PROJECT_COMMAND("add_test");
CM_UNEXPECTED_PROJECT_COMMAND("aux_source_directory");
CM_UNEXPECTED_PROJECT_COMMAND("build_command");
+ CM_UNEXPECTED_PROJECT_COMMAND("cmake_file_api");
CM_UNEXPECTED_PROJECT_COMMAND("create_test_sourcelist");
CM_UNEXPECTED_PROJECT_COMMAND("define_property");
CM_UNEXPECTED_PROJECT_COMMAND("enable_language");
diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx
index 8b98916..8abb5a8 100644
--- a/Source/cmFileAPI.cxx
+++ b/Source/cmFileAPI.cxx
@@ -978,3 +978,45 @@ Json::Value cmFileAPI::ReportCapabilities()
return capabilities;
}
+
+bool cmFileAPI::AddProjectQuery(cmFileAPI::ObjectKind kind,
+ unsigned majorVersion, unsigned minorVersion)
+{
+ switch (kind) {
+ case ObjectKind::CodeModel:
+ if (majorVersion != 2 || minorVersion > CodeModelV2Minor) {
+ return false;
+ }
+ break;
+ case ObjectKind::Cache:
+ if (majorVersion != 2 || minorVersion > CacheV2Minor) {
+ return false;
+ }
+ break;
+ case ObjectKind::CMakeFiles:
+ if (majorVersion != 1 || minorVersion > CMakeFilesV1Minor) {
+ return false;
+ }
+ break;
+ case ObjectKind::Toolchains:
+ if (majorVersion != 1 || minorVersion > ToolchainsV1Minor) {
+ return false;
+ }
+ break;
+ // These cannot be requested by the project
+ case ObjectKind::ConfigureLog:
+ case ObjectKind::InternalTest:
+ return false;
+ }
+
+ Object query;
+ query.Kind = kind;
+ query.Version = majorVersion;
+ if (std::find(this->TopQuery.Known.begin(), this->TopQuery.Known.end(),
+ query) == this->TopQuery.Known.end()) {
+ this->TopQuery.Known.emplace_back(query);
+ this->QueryExists = true;
+ }
+
+ return true;
+}
diff --git a/Source/cmFileAPI.h b/Source/cmFileAPI.h
index 6d7678f..1c13d7b 100644
--- a/Source/cmFileAPI.h
+++ b/Source/cmFileAPI.h
@@ -41,6 +41,20 @@ public:
/** Report file-api capabilities for cmake -E capabilities. */
static Json::Value ReportCapabilities();
+ // Keep in sync with ObjectKindName.
+ enum class ObjectKind
+ {
+ CodeModel,
+ ConfigureLog,
+ Cache,
+ CMakeFiles,
+ Toolchains,
+ InternalTest
+ };
+
+ bool AddProjectQuery(ObjectKind kind, unsigned majorVersion,
+ unsigned minorVersion);
+
private:
cmake* CMakeInstance;
@@ -53,17 +67,6 @@ private:
static std::vector<std::string> LoadDir(std::string const& dir);
void RemoveOldReplyFiles();
- // Keep in sync with ObjectKindName.
- enum class ObjectKind
- {
- CodeModel,
- ConfigureLog,
- Cache,
- CMakeFiles,
- Toolchains,
- InternalTest
- };
-
/** Identify one object kind and major version. */
struct Object
{
@@ -76,6 +79,14 @@ private:
}
return l.Version < r.Version;
}
+ friend bool operator==(Object const& l, Object const& r)
+ {
+ return l.Kind == r.Kind && l.Version == r.Version;
+ }
+ friend bool operator!=(Object const& l, Object const& r)
+ {
+ return !(l == r);
+ }
};
/** Represent content of a query directory. */
diff --git a/Source/cmFileAPICommand.cxx b/Source/cmFileAPICommand.cxx
new file mode 100644
index 0000000..d051c9c
--- /dev/null
+++ b/Source/cmFileAPICommand.cxx
@@ -0,0 +1,170 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFileAPICommand.h"
+
+#include <algorithm>
+#include <array>
+#include <cctype>
+#include <cstdlib>
+
+#include <cm/string_view>
+#include <cmext/string_view>
+
+#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
+#include "cmExecutionStatus.h"
+#include "cmFileAPI.h"
+#include "cmMakefile.h"
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
+#include "cmSubcommandTable.h"
+#include "cmake.h"
+
+namespace {
+
+bool isCharDigit(char ch)
+{
+ return std::isdigit(static_cast<unsigned char>(ch));
+}
+
+std::string processObjectKindVersions(cmFileAPI& fileApi,
+ cmFileAPI::ObjectKind objectKind,
+ cm::string_view keyword,
+ const std::vector<std::string>& versions)
+{
+ // The "versions" vector is empty only when the keyword was not present.
+ // It is an error to provide the keyword with no versions after it, and that
+ // is enforced by the argument parser before we get here.
+ if (versions.empty()) {
+ return {};
+ }
+
+ // The first supported version listed is what we use
+ for (const std::string& ver : versions) {
+ const char* vStart = ver.c_str();
+ int majorVersion = std::atoi(vStart);
+ int minorVersion = 0;
+ std::string::size_type pos = ver.find('.');
+ if (pos != std::string::npos) {
+ vStart += pos + 1;
+ minorVersion = std::atoi(vStart);
+ }
+ if (majorVersion < 1 || minorVersion < 0) {
+ return cmStrCat("Given a malformed version \"", ver, "\" for ", keyword,
+ ".");
+ }
+ if (fileApi.AddProjectQuery(objectKind,
+ static_cast<unsigned>(majorVersion),
+ static_cast<unsigned>(minorVersion))) {
+ return {};
+ }
+ }
+ return cmStrCat("None of the specified ", keyword,
+ " versions is supported by this version of CMake.");
+}
+
+bool handleQueryCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.empty()) {
+ status.SetError("QUERY subcommand called without required arguments.");
+ return false;
+ }
+
+ struct Arguments : public ArgumentParser::ParseResult
+ {
+ ArgumentParser::NonEmpty<std::string> ApiVersion;
+ ArgumentParser::NonEmpty<std::vector<std::string>> CodeModelVersions;
+ ArgumentParser::NonEmpty<std::vector<std::string>> CacheVersions;
+ ArgumentParser::NonEmpty<std::vector<std::string>> CMakeFilesVersions;
+ ArgumentParser::NonEmpty<std::vector<std::string>> ToolchainsVersions;
+ };
+
+ static auto const parser =
+ cmArgumentParser<Arguments>{}
+ .Bind("API_VERSION"_s, &Arguments::ApiVersion)
+ .Bind("CODEMODEL"_s, &Arguments::CodeModelVersions)
+ .Bind("CACHE"_s, &Arguments::CacheVersions)
+ .Bind("CMAKEFILES"_s, &Arguments::CMakeFilesVersions)
+ .Bind("TOOLCHAINS"_s, &Arguments::ToolchainsVersions);
+
+ std::vector<std::string> unparsedArguments;
+ Arguments const arguments =
+ parser.Parse(cmMakeRange(args).advance(1), &unparsedArguments);
+
+ if (arguments.MaybeReportError(status.GetMakefile())) {
+ return true;
+ }
+ if (!unparsedArguments.empty()) {
+ status.SetError("QUERY subcommand given unknown argument \"" +
+ unparsedArguments.front() + "\".");
+ return false;
+ }
+
+ if (!std::all_of(arguments.ApiVersion.begin(), arguments.ApiVersion.end(),
+ isCharDigit)) {
+ status.SetError("QUERY subcommand given a non-integer API_VERSION.");
+ return false;
+ }
+ const int apiVersion = std::atoi(arguments.ApiVersion.c_str());
+ if (apiVersion != 1) {
+ status.SetError(
+ cmStrCat("QUERY subcommand given an unsupported API_VERSION \"",
+ arguments.ApiVersion,
+ "\" (the only currently supported version is 1)."));
+ return false;
+ }
+
+ cmMakefile& mf = status.GetMakefile();
+ cmake* cmi = mf.GetCMakeInstance();
+ cmFileAPI* fileApi = cmi->GetFileAPI();
+
+ // We want to check all keywords and report all errors, not just the first.
+ // Record each result rather than short-circuiting on the first error.
+
+ // NOTE: Double braces are needed here for compilers that don't implement the
+ // CWG 1270 revision to C++11.
+ std::array<std::string, 4> errors{
+ { processObjectKindVersions(*fileApi, cmFileAPI::ObjectKind::CodeModel,
+ "CODEMODEL"_s, arguments.CodeModelVersions),
+ processObjectKindVersions(*fileApi, cmFileAPI::ObjectKind::Cache,
+ "CACHE"_s, arguments.CacheVersions),
+ processObjectKindVersions(*fileApi, cmFileAPI::ObjectKind::CMakeFiles,
+ "CMAKEFILES"_s, arguments.CMakeFilesVersions),
+ processObjectKindVersions(*fileApi, cmFileAPI::ObjectKind::Toolchains,
+ "TOOLCHAINS"_s, arguments.ToolchainsVersions) }
+ };
+
+ if (!std::all_of(errors.begin(), errors.end(),
+ [](const std::string& s) -> bool { return s.empty(); })) {
+ std::string message("QUERY subcommand was given invalid arguments:");
+ for (const std::string& s : errors) {
+ if (!s.empty()) {
+ message = cmStrCat(message, "\n ", s);
+ }
+ }
+ status.SetError(message);
+ return false;
+ }
+
+ return true;
+}
+
+}
+
+bool cmFileAPICommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.empty()) {
+ status.SetError("must be called with arguments.");
+ return false;
+ }
+
+ // clang-format off
+ static cmSubcommandTable const subcommand{
+ { "QUERY"_s, handleQueryCommand }
+ };
+ // clang-format on
+
+ return subcommand(args[0], args, status);
+}
diff --git a/Source/cmFileAPICommand.h b/Source/cmFileAPICommand.h
new file mode 100644
index 0000000..28a4571
--- /dev/null
+++ b/Source/cmFileAPICommand.h
@@ -0,0 +1,13 @@
+/* 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 <string>
+#include <vector>
+
+class cmExecutionStatus;
+
+bool cmFileAPICommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
diff --git a/Source/cmake.h b/Source/cmake.h
index 2f5ea24..156d061 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -635,6 +635,10 @@ public:
void UnwatchUnusedCli(const std::string& var);
void WatchUnusedCli(const std::string& var);
+#if !defined(CMAKE_BOOTSTRAP)
+ cmFileAPI* GetFileAPI() const { return this->FileAPI.get(); }
+#endif
+
cmState* GetState() const { return this->State.get(); }
void SetCurrentSnapshot(cmStateSnapshot const& snapshot)
{
diff --git a/Tests/RunCMake/FileAPI/ProjectQueryBad-result.txt b/Tests/RunCMake/FileAPI/ProjectQueryBad-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/ProjectQueryBad-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/FileAPI/ProjectQueryBad-stderr.txt b/Tests/RunCMake/FileAPI/ProjectQueryBad-stderr.txt
new file mode 100644
index 0000000..84eff98
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/ProjectQueryBad-stderr.txt
@@ -0,0 +1,36 @@
+Non-query check
+CMake Error at ProjectQueryBad\.cmake:[0-9]+ \(cmake_file_api\):
+ cmake_file_api does not recognize sub-command NOT_A_QUERY
+.*
+Invalid API version checks
+CMake Error at ProjectQueryBad\.cmake:[0-9]+ \(cmake_file_api\):
+ cmake_file_api QUERY subcommand given an unsupported API_VERSION "2" \(the
+ only currently supported version is 1\)\.
+.*
+CMake Error at ProjectQueryBad\.cmake:[0-9]+ \(cmake_file_api\):
+ cmake_file_api QUERY subcommand given a non-integer API_VERSION\.
+.*
+Invalid version numbers check
+CMake Error at ProjectQueryBad\.cmake:[0-9]+ \(cmake_file_api\):
+ cmake_file_api QUERY subcommand was given invalid arguments:
+
+ Given a malformed version "nope" for CODEMODEL\.
+ Given a malformed version "-2" for CACHE\.
+ Given a malformed version "\.8" for CMAKEFILES\.
+ Given a malformed version "0\.1" for TOOLCHAINS\.
+.*
+Requested versions too high check
+CMake Error at ProjectQueryBad\.cmake:[0-9]+ \(cmake_file_api\):
+ cmake_file_api QUERY subcommand was given invalid arguments:
+
+ None of the specified CODEMODEL versions is supported by this version of CMake\.
+ None of the specified CACHE versions is supported by this version of CMake\.
+ None of the specified CMAKEFILES versions is supported by this version of CMake\.
+ None of the specified TOOLCHAINS versions is supported by this version of CMake\.
+.*
+Requested versions too low check
+CMake Error at ProjectQueryBad\.cmake:[0-9]+ \(cmake_file_api\):
+ cmake_file_api QUERY subcommand was given invalid arguments:
+
+ None of the specified CODEMODEL versions is supported by this version of CMake\.
+ None of the specified CACHE versions is supported by this version of CMake\.
diff --git a/Tests/RunCMake/FileAPI/ProjectQueryBad.cmake b/Tests/RunCMake/FileAPI/ProjectQueryBad.cmake
new file mode 100644
index 0000000..3a06105
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/ProjectQueryBad.cmake
@@ -0,0 +1,42 @@
+# All of these should fail. Execution does continue though, so we should see
+# the error output from each one. There is no observable effect of the command
+# during the configure phase, so it isn't critical to end processing on the
+# first failure. Allowing execution to proceed may allow the project to see
+# other potential errors before ultimately halting. That behavior is generally
+# desirable, and the multiple failing calls here will confirm that we retain
+# that behavior.
+
+message(NOTICE "Non-query check")
+cmake_file_api(NOT_A_QUERY)
+
+message(NOTICE "Invalid API version checks")
+cmake_file_api(QUERY API_VERSION 2)
+cmake_file_api(QUERY API_VERSION nah)
+
+message(NOTICE "Invalid version numbers check")
+cmake_file_api(
+ QUERY
+ API_VERSION 1
+ CODEMODEL nope
+ CACHE -2
+ CMAKEFILES .8
+ TOOLCHAINS 2 0.1
+)
+
+message(NOTICE "Requested versions too high check")
+cmake_file_api(
+ QUERY
+ API_VERSION 1
+ CODEMODEL 3
+ CACHE 3
+ CMAKEFILES 2
+ TOOLCHAINS 1.1
+)
+
+message(NOTICE "Requested versions too low check")
+cmake_file_api(
+ QUERY
+ API_VERSION 1
+ CODEMODEL 1
+ CACHE 1
+)
diff --git a/Tests/RunCMake/FileAPI/ProjectQueryGood-check.cmake b/Tests/RunCMake/FileAPI/ProjectQueryGood-check.cmake
new file mode 100644
index 0000000..46d3f77
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/ProjectQueryGood-check.cmake
@@ -0,0 +1,11 @@
+set(expect
+ reply
+ reply/cache-v2-[0-9a-f]+.json
+ reply/cmakeFiles-v1-[0-9a-f]+.json
+ reply/codemodel-v2-[0-9a-f]+.json
+ .*reply/index-[0-9.T-]+.json
+ .*reply/toolchains-v1-[0-9a-f]+.json
+)
+
+# Only need to check for existence. Other tests check the reply contents.
+check_api("^${expect}$")
diff --git a/Tests/RunCMake/FileAPI/ProjectQueryGood.cmake b/Tests/RunCMake/FileAPI/ProjectQueryGood.cmake
new file mode 100644
index 0000000..da0f3ce
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/ProjectQueryGood.cmake
@@ -0,0 +1,8 @@
+cmake_file_api(
+ QUERY
+ API_VERSION 1
+ CODEMODEL 3 2.1
+ CACHE 3.2 2
+ CMAKEFILES 3 2 1.0
+ TOOLCHAINS 3 2 1
+)
diff --git a/Tests/RunCMake/FileAPI/RunCMakeTest.cmake b/Tests/RunCMake/FileAPI/RunCMakeTest.cmake
index c768d18..81926af 100644
--- a/Tests/RunCMake/FileAPI/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FileAPI/RunCMakeTest.cmake
@@ -52,6 +52,8 @@ run_cmake(ClientStateless)
run_cmake(MixedStateless)
run_cmake(DuplicateStateless)
run_cmake(ClientStateful)
+run_cmake(ProjectQueryGood)
+run_cmake(ProjectQueryBad)
function(run_object object)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${object}-build)