mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-10-04 04:03:22 +03:00
ctest: Support Test Dependencies for discover_test modules
- Update discover_tests to work with test_prep targets and ctest --out-of-date - Extend behavior to gtest_discover_tests - Don't treat non-built targets as always out of date - Support imported targets in BUILD_DEPENDS Issue: #28052, #28070
This commit is contained in:
1 parent
d291927f5d
commit
463517fddd
69 files changed
+1146
-160
No files matched your search
@@ -117,6 +117,8 @@ directory the test is created in.
|
||||
``COMMAND`` also enable the :option:`--out-of-date <ctest --out-of-date>`
|
||||
behavior of :manual:`ctest(1)`.
|
||||
|
||||
Tests with missing build dependencies will not be run.
|
||||
|
||||
``COMMAND_EXPAND_LISTS``
|
||||
.. versionadded:: 3.16
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ Register tests with names and properties discovered at test time by
|
||||
TEST_NAME <replacement>
|
||||
TEST_ARGS <replacement>...
|
||||
[TEST_PROPERTIES <key> <replacement> [<key> <replacement>]...]
|
||||
[BUILD_DEPENDS <dependencies>...]
|
||||
)
|
||||
|
||||
This command configures test discovery rather than defining a single test at
|
||||
@@ -94,6 +95,25 @@ the provided regular expression and replacement strings.
|
||||
they do not set :prop_test:`FIXTURE_REPEAT_MODE`, policy :policy:`CMP0224`
|
||||
determines the behavior when the :ctest-option:`--repeat` option is used.
|
||||
|
||||
``BUILD_DEPENDS``
|
||||
Specify a list of targets or files that must be built before the test
|
||||
discovery can run.
|
||||
|
||||
When the :variable:`CMAKE_TEST_BUILD_DEPENDS` variable is enabled with the
|
||||
:ref:`Ninja Generators`, :generator:`FASTBuild`, or :ref:`Makefile
|
||||
Generators`, these dependencies are built by the ``test_prep/all`` target.
|
||||
If ``COMMAND`` names an executable target created by
|
||||
:command:`add_executable`, that target is also added automatically.
|
||||
|
||||
Individual ``test_prep/<test-name>`` targets are not created for discovered
|
||||
tests because their names are not known at generation time.
|
||||
|
||||
Build dependencies added by this argument, and an executable target
|
||||
named by ``COMMAND``, also enable the
|
||||
:ctest-option:`--out-of-date` behavior of :manual:`ctest(1)`.
|
||||
|
||||
Tests with missing build dependencies will not be run.
|
||||
|
||||
CTest executes the discovery step to obtain the list of tests and then runs
|
||||
each discovered test using the command-line produced by ``COMMAND`` together
|
||||
with ``TEST_ARGS``. The pass/fail behavior of each discovered test follows
|
||||
|
||||
@@ -29,6 +29,32 @@ This writes a FASTBuild configuration file named ``fbuild.bff`` into
|
||||
These IDE files can be generated by building ``xcode`` or ``solution`` targets
|
||||
and will build using FASTBuild as the backend.
|
||||
|
||||
Built-in Targets
|
||||
----------------
|
||||
|
||||
.. versionadded:: 4.5
|
||||
|
||||
When the :variable:`CMAKE_TEST_BUILD_DEPENDS` variable is enabled, the
|
||||
generated build file provides the following targets:
|
||||
|
||||
``test_prep/<test-name>``
|
||||
Builds all known build dependencies for the test named ``<test-name>``
|
||||
added by :command:`add_test`, including the executable target invoked by
|
||||
the test, targets referenced by generator expressions in the test command,
|
||||
and explicit ``BUILD_DEPENDS`` entries.
|
||||
|
||||
Tests whose names are not valid target names are excluded. If multiple
|
||||
tests in different directories share the same name, their dependencies are
|
||||
merged into one ``test_prep/<test-name>`` target.
|
||||
|
||||
Individual ``test_prep/<test-name>`` targets are not created for tests
|
||||
discovered at test time, because their names are not known during generation.
|
||||
|
||||
``test_prep/all``
|
||||
Depends on every generated ``test_prep/<test-name>`` target. Also builds
|
||||
dependencies recorded by the :prop_dir:`CMAKE_TEST_BUILD_DEPENDS` directory
|
||||
property.
|
||||
|
||||
Caching
|
||||
-------
|
||||
|
||||
@@ -70,6 +96,7 @@ The following variables can be used to configure this generator:
|
||||
* :variable:`CMAKE_FASTBUILD_IDE_ARGS`
|
||||
* :variable:`CMAKE_FASTBUILD_TRACK_BYPRODUCTS_AS_OUTPUT`
|
||||
* :variable:`CMAKE_FASTBUILD_VERBOSE_GENERATOR`
|
||||
* :variable:`CMAKE_TEST_BUILD_DEPENDS`
|
||||
|
||||
Target Properties
|
||||
-----------------
|
||||
|
||||
@@ -72,6 +72,7 @@ Properties on Directories
|
||||
/prop_dir/CACHE_VARIABLES
|
||||
/prop_dir/CLEAN_NO_CUSTOM
|
||||
/prop_dir/CMAKE_CONFIGURE_DEPENDS
|
||||
/prop_dir/CMAKE_TEST_BUILD_DEPENDS
|
||||
/prop_dir/COMPILE_DEFINITIONS
|
||||
/prop_dir/COMPILE_OPTIONS
|
||||
/prop_dir/DEFINITIONS
|
||||
|
||||
@@ -616,13 +616,16 @@ The options for running tests are:
|
||||
respect to their recorded build dependencies. Build dependencies include
|
||||
executables and targets in generator expressions as part of the test
|
||||
``COMMAND``, as well as the outputs of targets or files added as explicit
|
||||
dependencies with the ``BUILD_DEPENDS`` argument of :command:`add_test`.
|
||||
dependencies with the ``BUILD_DEPENDS`` argument of :command:`add_test` or
|
||||
:command:`discover_tests`. Tests discovered by
|
||||
:command:`gtest_discover_tests` also record their test executable as a build
|
||||
dependency.
|
||||
|
||||
A test is selected to run when any of its recorded build dependencies are
|
||||
newer than the test's last-run timestamp, or when the test has not been
|
||||
run before. Tests without any known build dependencies, including any tests
|
||||
not added by the :command:`add_test` command, are excluded when this argument
|
||||
is provided.
|
||||
newer than the test's last-run timestamp, when any dependency is missing, or
|
||||
when the test has not been run before. Selected tests with missing build
|
||||
dependencies are reported as ``Not Run``. Tests without any known build
|
||||
dependencies are excluded when this argument is provided.
|
||||
|
||||
View Help
|
||||
=========
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
CMAKE_TEST_BUILD_DEPENDS
|
||||
------------------------
|
||||
|
||||
.. versionadded:: 4.5
|
||||
|
||||
List of directory-scoped build time dependencies for tests.
|
||||
|
||||
This property holds a
|
||||
:ref:`semicolon-separated list <CMake Language Lists>` of targets and/or files
|
||||
that should be built by ``test_prep/all`` when
|
||||
:variable:`CMAKE_TEST_BUILD_DEPENDS` is enabled.
|
||||
|
||||
Projects may append to this property directly with :command:`set_property` or
|
||||
:command:`set_directory_properties` to extend ``test_prep/all`` with
|
||||
directory-scoped build dependencies.
|
||||
@@ -18,6 +18,9 @@ target for all such tests. Building these targets ensures the test executable,
|
||||
targets referenced by test command generator expressions, and explicit
|
||||
``BUILD_DEPENDS`` entries are up-to-date before the test runs.
|
||||
|
||||
Modules may also extend ``test_prep/all`` with directory-scoped dependencies
|
||||
via the :prop_dir:`CMAKE_TEST_BUILD_DEPENDS` directory property.
|
||||
|
||||
Tests whose names are not valid target names are excluded from this behavior.
|
||||
If multiple tests in different directories share the same name, their
|
||||
dependencies are merged into a single ``test_prep/<name>`` target.
|
||||
|
||||
@@ -740,6 +740,10 @@ function(gtest_discover_tests target)
|
||||
)
|
||||
file(GENERATE OUTPUT "${discovery_file}" CONTENT "${discovery_content}")
|
||||
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_TEST_BUILD_DEPENDS
|
||||
"${target}"
|
||||
)
|
||||
|
||||
set(ctest_include_content)
|
||||
if(arg_DISCOVERY_MODE STREQUAL "POST_BUILD")
|
||||
# Make sure that TEST_LAUNCHER and CROSSCOMPILING_EMULATOR appear on the
|
||||
|
||||
@@ -97,6 +97,7 @@ macro(write_test_to_file)
|
||||
"set_tests_properties(${guarded_testname}\n"
|
||||
" PROPERTIES\n"
|
||||
" ${maybe_DISABLED}\n"
|
||||
" _CMAKE_TEST_BUILD_DEPENDS [==[${arg_TEST_EXECUTABLE}]==]\n"
|
||||
" ${maybe_LOCATION}\n"
|
||||
" WORKING_DIRECTORY [==[${arg_TEST_WORKING_DIR}]==]\n"
|
||||
" SKIP_REGULAR_EXPRESSION [==[\\[ SKIPPED \\]]==]\n"
|
||||
|
||||
@@ -161,11 +161,16 @@ bool cmCTestDiscoverTests(cmTestDiscoveryArgs const& args,
|
||||
}
|
||||
|
||||
auto testProperties = std::vector<std::string>{ testName, "PROPERTIES" };
|
||||
testProperties.reserve(2 + args.TestProperties.size());
|
||||
testProperties.reserve(2 + args.TestProperties.size() +
|
||||
(args.BuildDepends.empty() ? 0 : 2));
|
||||
for (std::size_t i = 0; i < args.TestProperties.size(); i += 2) {
|
||||
testProperties.push_back(args.TestProperties[i]);
|
||||
testProperties.push_back(replace(args.TestProperties[i + 1]));
|
||||
}
|
||||
if (!args.BuildDepends.empty()) {
|
||||
testProperties.push_back("_CMAKE_TEST_BUILD_DEPENDS");
|
||||
testProperties.push_back(cmList::to_string(args.BuildDepends));
|
||||
}
|
||||
if (!handler->SetTestsProperties(testProperties)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "cmInstrumentation.h"
|
||||
#include "cmInstrumentationQuery.h"
|
||||
#include "cmJSONState.h"
|
||||
#include "cmList.h"
|
||||
#include "cmProcess.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
@@ -668,6 +669,20 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total)
|
||||
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
|
||||
return false;
|
||||
}
|
||||
// log and return if we did not find any other test dependencies
|
||||
for (std::string const& dep : cmList{ this->TestProperties->BuildDepends }) {
|
||||
if (!dep.empty() && !cmSystemTools::FileExists(dep)) {
|
||||
std::string const msg = "Unable to find build dependency: " + dep;
|
||||
*this->TestHandler->LogFile << msg << std::endl;
|
||||
cmCTestLog(this->CTest, ERROR_MESSAGE, msg, '\n');
|
||||
this->TestResult.Output = msg;
|
||||
this->TestResult.FullCommandLine.clear();
|
||||
this->TestResult.Environment.clear();
|
||||
this->TestResult.CompletionStatus = "Build Dependencies Missing";
|
||||
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this->StartTime = this->CTest->CurrentTime();
|
||||
if (this->CTest->GetInstrumentation().HasQuery()) {
|
||||
this->CTest->GetInstrumentation().GetPreTestStats();
|
||||
|
||||
@@ -995,6 +995,10 @@ bool cmCTestTestHandler::ComputeTestList()
|
||||
}
|
||||
}
|
||||
|
||||
if (this->TestOptions.OutOfDateOnly && !tp.IsOutOfDate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this->TestsToRunByName) {
|
||||
if (this->TestsToRunByName->find(tp.Name) ==
|
||||
this->TestsToRunByName->end()) {
|
||||
@@ -1057,11 +1061,11 @@ bool cmCTestTestHandler::ComputeTestListForRerunFailed()
|
||||
|
||||
void cmCTestTestHandler::ComputeOutOfDateTests()
|
||||
{
|
||||
ListOfTests finalList;
|
||||
std::string const stampDir = this->CTest->GetStampDir();
|
||||
cmSystemTools::MakeDirectory(stampDir);
|
||||
|
||||
for (cmCTestTestProperties& tp : this->TestList) {
|
||||
tp.IsOutOfDate = false;
|
||||
if (tp.BuildDepends.empty()) {
|
||||
continue;
|
||||
}
|
||||
@@ -1069,7 +1073,7 @@ void cmCTestTestHandler::ComputeOutOfDateTests()
|
||||
std::string const stampFile = cmStrCat(stampDir, '/', tp.GetStampFile());
|
||||
|
||||
if (!cmSystemTools::FileExists(stampFile)) {
|
||||
finalList.push_back(tp);
|
||||
tp.IsOutOfDate = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1080,8 +1084,7 @@ void cmCTestTestHandler::ComputeOutOfDateTests()
|
||||
continue;
|
||||
}
|
||||
if (!cmSystemTools::FileExists(dep)) {
|
||||
// If any dependencies don't exist, skip the test
|
||||
outOfDate = false;
|
||||
outOfDate = true;
|
||||
break;
|
||||
}
|
||||
int result = 0;
|
||||
@@ -1091,11 +1094,8 @@ void cmCTestTestHandler::ComputeOutOfDateTests()
|
||||
outOfDate = true;
|
||||
}
|
||||
}
|
||||
if (outOfDate) {
|
||||
finalList.push_back(tp);
|
||||
}
|
||||
tp.IsOutOfDate = outOfDate;
|
||||
}
|
||||
this->TestList = finalList;
|
||||
}
|
||||
|
||||
void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
|
||||
|
||||
@@ -191,6 +191,7 @@ public:
|
||||
std::map<std::string, std::string> CustomProperties;
|
||||
std::unordered_map<std::string, std::string> RawProperties;
|
||||
bool IsInBasedOnREOptions = true;
|
||||
bool IsOutOfDate = true;
|
||||
bool WillFail = false;
|
||||
std::string WillFailRaw;
|
||||
bool Disabled = false;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "cmDiscoverTestsCommand.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -15,6 +16,8 @@
|
||||
#include "cmArgumentParserTypes.h"
|
||||
#include "cmExecutionStatus.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
@@ -42,6 +45,42 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void Compute(cmLocalGenerator* lg) override
|
||||
{
|
||||
this->cmTestGenerator::Compute(lg);
|
||||
this->BuildDependenciesByConfig.clear();
|
||||
if (!lg->GetMakefile()->IsOn("CMAKE_TESTING_ENABLED")) {
|
||||
return;
|
||||
}
|
||||
bool const filterConfigs =
|
||||
!lg->GetMakefile()
|
||||
->GetGeneratorConfigs(cmMakefile::OnlyMultiConfig)
|
||||
.empty();
|
||||
for (std::string const& config : lg->GetMakefile()->GetGeneratorConfigs(
|
||||
cmMakefile::IncludeEmptyConfig)) {
|
||||
if (filterConfigs && !this->GeneratesForConfig(config)) {
|
||||
continue;
|
||||
}
|
||||
cmTestGenerator::BuildDependencies& deps =
|
||||
this->BuildDependenciesByConfig[config];
|
||||
if (!cmTestGenerator::EvaluateBuildDependencies(
|
||||
lg, config, this->Backtrace, "discover_tests", this->Args.Command,
|
||||
this->Args.BuildDepends, deps, lg->GetMakefile())) {
|
||||
deps = {};
|
||||
continue;
|
||||
}
|
||||
for (cmGeneratorTarget* target : deps.Targets) {
|
||||
lg->AddDirectoryTestPrepDependency(config,
|
||||
{ target->GetName(), target });
|
||||
}
|
||||
for (cmTestGenerator::BuildDependencies::FileDependency const& file :
|
||||
deps.Files) {
|
||||
lg->AddDirectoryTestPrepDependency(
|
||||
config, { file.Path, nullptr, file.Owner, file.Generated });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void GenerateProperties(std::ostream& os, Indent indent,
|
||||
std::vector<std::string> const& props,
|
||||
@@ -61,6 +100,10 @@ private:
|
||||
cmGeneratorExpression ge(*this->LG->GetMakefile()->GetCMakeInstance(),
|
||||
this->Backtrace);
|
||||
|
||||
std::vector<std::string> const buildDepends =
|
||||
this->LG->GetGlobalGenerator()->GetTestBuildDependencyPaths(
|
||||
config, this->BuildDependenciesByConfig.at(config));
|
||||
|
||||
auto const in = indent.Next();
|
||||
os << indent << "discover_tests(COMMAND ";
|
||||
this->GenerateCommand(os, this->Args.Command, config,
|
||||
@@ -85,11 +128,19 @@ private:
|
||||
ge);
|
||||
os << '\n' << in.Next();
|
||||
this->GenerateBacktrace(os, this->Backtrace);
|
||||
if (!buildDepends.empty()) {
|
||||
os << '\n' << in << "BUILD_DEPENDS";
|
||||
for (std::string const& dep : buildDepends) {
|
||||
os << ' ' << Quote(dep);
|
||||
}
|
||||
}
|
||||
os << '\n' << in << ")\n";
|
||||
}
|
||||
|
||||
Arguments Args;
|
||||
cmListFileBacktrace Backtrace;
|
||||
std::map<std::string, cmTestGenerator::BuildDependencies>
|
||||
BuildDependenciesByConfig;
|
||||
};
|
||||
|
||||
bool SetsFixtureRepeatMode(std::vector<std::string> const& properties)
|
||||
|
||||
@@ -1625,6 +1625,22 @@ void cmGlobalFastbuildGenerator::WriteTestPrepTargets()
|
||||
testPrepTarget.Dependencies.emplace(depFile.Path);
|
||||
}
|
||||
}
|
||||
cmLocalGenerator::DirectoryTestPrepTarget directoryTarget;
|
||||
if (localGen->GetDirectoryTestPrepTarget(
|
||||
directoryTarget,
|
||||
localGen->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"))) {
|
||||
TestPrepTarget& testPrepTarget = testPrepTargets[directoryTarget.Name];
|
||||
testPrepTarget.Comment = std::move(directoryTarget.Comment);
|
||||
|
||||
for (cmLocalGenerator::DirectoryTestPrepDependency const& dep :
|
||||
directoryTarget.Dependencies) {
|
||||
if (dep.Target) {
|
||||
testPrepTarget.Dependencies.emplace(dep.Target->GetName());
|
||||
} else {
|
||||
testPrepTarget.Dependencies.emplace(dep.Raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FastbuildAliasNode allAliasNode;
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTarget.h"
|
||||
#include "cmTargetExport.h"
|
||||
#include "cmTestGenerator.h"
|
||||
#include "cmUnreachable.h"
|
||||
#include "cmValue.h"
|
||||
#include "cmVersion.h"
|
||||
@@ -1870,6 +1871,14 @@ bool cmGlobalGenerator::Compute()
|
||||
localGen->ComputeTargetManifest();
|
||||
}
|
||||
|
||||
// Register test preparation dependencies after custom-command outputs are
|
||||
// known, but before generators compute their build graphs.
|
||||
for (auto const& localGen : this->LocalGenerators) {
|
||||
for (auto const& tester : localGen->GetMakefile()->GetTestGenerators()) {
|
||||
tester->Compute(localGen.get());
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the inter-target dependencies.
|
||||
if (!this->ComputeTargetDepends()) {
|
||||
return false;
|
||||
@@ -3248,11 +3257,17 @@ std::vector<std::string> cmGlobalGenerator::GetTestBuildDependencyPaths(
|
||||
}
|
||||
continue;
|
||||
}
|
||||
uniqueDeps.insert(target->GetFullPath(config));
|
||||
uniqueDeps.insert(this->GetTestBuildDependencyPath(target, config));
|
||||
}
|
||||
return { uniqueDeps.begin(), uniqueDeps.end() };
|
||||
}
|
||||
|
||||
std::string cmGlobalGenerator::GetTestBuildDependencyPath(
|
||||
cmGeneratorTarget const* target, std::string const& config) const
|
||||
{
|
||||
return target->GetFullPath(config);
|
||||
}
|
||||
|
||||
// If the file has no extension it's either a raw executable or might
|
||||
// be a direct reference to a binary within a framework (bad practice!).
|
||||
// This is where we change the path to point to the framework directory.
|
||||
|
||||
@@ -796,6 +796,9 @@ public:
|
||||
cmXcFrameworkPlist const& content);
|
||||
|
||||
protected:
|
||||
virtual std::string GetTestBuildDependencyPath(
|
||||
cmGeneratorTarget const* target, std::string const& config) const;
|
||||
|
||||
/** Get all targets produced under the given root, plus the transitive
|
||||
closure of targets on which they depend, possibly from other dirs. */
|
||||
TargetDependSet GetTargetsForProject(
|
||||
|
||||
@@ -1308,7 +1308,7 @@ void cmGlobalNinjaGenerator::WriteTestPrepTargets()
|
||||
|
||||
std::map<std::string, TestPrepTarget> testPrepTargets;
|
||||
for (auto const& localGen : this->LocalGenerators) {
|
||||
auto* lg = static_cast<cmLocalNinjaGenerator*>(localGen.get());
|
||||
cmLocalGenerator* lg = localGen.get();
|
||||
auto const& testGenerators = lg->GetMakefile()->GetTestGenerators();
|
||||
for (auto const& tester : testGenerators) {
|
||||
cmTestGenerator::BuildDependencies testDeps;
|
||||
@@ -1332,6 +1332,27 @@ void cmGlobalNinjaGenerator::WriteTestPrepTargets()
|
||||
this->ConvertToNinjaPath(file.Path));
|
||||
}
|
||||
}
|
||||
|
||||
cmLocalGenerator::DirectoryTestPrepTarget directoryTarget;
|
||||
if (!lg->GetDirectoryTestPrepTarget(directoryTarget, config)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string const depName =
|
||||
this->ConvertToNinjaPath(directoryTarget.Name);
|
||||
TestPrepTarget& testPrepTarget = testPrepTargets[depName];
|
||||
testPrepTarget.Comment = std::move(directoryTarget.Comment);
|
||||
|
||||
for (cmLocalGenerator::DirectoryTestPrepDependency const& dep :
|
||||
directoryTarget.Dependencies) {
|
||||
if (dep.Target) {
|
||||
this->AppendTargetOutputs(dep.Target, testPrepTarget.ExplicitDeps,
|
||||
config, DependOnTargetArtifact);
|
||||
} else {
|
||||
testPrepTarget.ExplicitDeps.push_back(
|
||||
this->ConvertToNinjaPath(dep.Raw));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> allDeps;
|
||||
@@ -1369,7 +1390,8 @@ void cmGlobalNinjaGenerator::WriteTestPrepTargets()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writeConfig(std::string(), *this->GetCommonFileStream());
|
||||
writeConfig(this->Makefiles.front()->GetSafeDefinition("CMAKE_BUILD_TYPE"),
|
||||
*this->GetCommonFileStream());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -115,8 +115,11 @@ void cmGlobalUnixMakefileGenerator3::Generate()
|
||||
this->ClangTidyExportFixesDirs.clear();
|
||||
this->ClangTidyExportFixesFiles.clear();
|
||||
|
||||
this->TestPrepTargets.clear();
|
||||
this->TestPrepEnabled = false;
|
||||
|
||||
// Compute the "test_prep/" targets before generating the local makefiles
|
||||
// so their convenience rules can be written into the top-level Makefile.
|
||||
// so they can be emitted in a single pass.
|
||||
this->ComputeTestPrepTargets();
|
||||
|
||||
// first do superclass method
|
||||
@@ -1064,10 +1067,12 @@ void cmGlobalUnixMakefileGenerator3::ComputeTestPrepTargets()
|
||||
|
||||
for (cmTestGenerator::BuildDependencies::FileDependency const& file :
|
||||
deps.Files) {
|
||||
if (file.Owner) {
|
||||
if (cmGeneratorTarget* owner = file.Owner
|
||||
? file.Owner
|
||||
: this->FindOutputOwningTarget(file.Path)) {
|
||||
// The file is the primary output of one build-system target; build
|
||||
// that target to produce the file.
|
||||
rules.push_back(targetAllRule(file.Owner));
|
||||
rules.push_back(targetAllRule(owner));
|
||||
} else if (file.Generated) {
|
||||
// The file is generated but cannot be attributed to a single owning
|
||||
// target (e.g. a byproduct or an ambiguous/shared output), so the
|
||||
@@ -1088,6 +1093,8 @@ void cmGlobalUnixMakefileGenerator3::ComputeTestPrepTargets()
|
||||
// file that already exists) and needs no build rule.
|
||||
}
|
||||
}
|
||||
|
||||
this->AddDirectoryTestPrepTargets(lg.get(), this->TestPrepTargets);
|
||||
}
|
||||
|
||||
// Sort and de-duplicate each rule list (as the Ninja generator does).
|
||||
@@ -1098,6 +1105,45 @@ void cmGlobalUnixMakefileGenerator3::ComputeTestPrepTargets()
|
||||
}
|
||||
}
|
||||
|
||||
void cmGlobalUnixMakefileGenerator3::AddDirectoryTestPrepTargets(
|
||||
cmLocalGenerator* lg,
|
||||
std::map<std::string, std::vector<std::string>>& testPrepTargets)
|
||||
{
|
||||
cmLocalGenerator::DirectoryTestPrepTarget directoryTarget;
|
||||
if (!lg->GetDirectoryTestPrepTarget(
|
||||
directoryTarget,
|
||||
lg->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string>& rules = testPrepTargets[directoryTarget.Name];
|
||||
|
||||
for (cmLocalGenerator::DirectoryTestPrepDependency const& dep :
|
||||
directoryTarget.Dependencies) {
|
||||
cmGeneratorTarget* target = dep.Target ? dep.Target : dep.Owner;
|
||||
if (!target) {
|
||||
target = this->FindOutputOwningTarget(dep.Raw);
|
||||
}
|
||||
if (target) {
|
||||
auto* lg3 = static_cast<cmLocalUnixMakefileGenerator3*>(
|
||||
target->GetLocalGenerator());
|
||||
rules.push_back(
|
||||
cmStrCat(lg3->GetRelativeTargetDirectory(target), "/all"));
|
||||
} else if (dep.Generated) {
|
||||
lg->GetMakefile()->IssueMessage(
|
||||
MessageType::WARNING,
|
||||
cmStrCat("Directory test prep dependency\n ", dep.Raw,
|
||||
"\nis generated but is not the unique output of a build "
|
||||
"target, so the \"",
|
||||
directoryTarget.Name,
|
||||
"\" target cannot build it with this generator. Depend "
|
||||
"on the target that produces it (for example one created "
|
||||
"with add_custom_target) instead."),
|
||||
lg->GetMakefile()->GetBacktrace());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmGlobalUnixMakefileGenerator3::WriteTestPrepRules(
|
||||
std::ostream& makefileStream, cmLocalUnixMakefileGenerator3& rootLG)
|
||||
{
|
||||
@@ -1142,24 +1188,29 @@ void cmGlobalUnixMakefileGenerator3::WriteTestPrepConvenienceRules(
|
||||
|
||||
std::vector<std::string> depends;
|
||||
std::vector<std::string> commands;
|
||||
auto writeForward = [&](std::string const& prepName) {
|
||||
depends.clear();
|
||||
if (regenerate) {
|
||||
depends.emplace_back("cmake_check_build_system");
|
||||
}
|
||||
commands.clear();
|
||||
commands.push_back(lg.GetRecursiveMakeCall(makefile2, prepName));
|
||||
lg.WriteMakeRule(ruleFileStream, "Build the dependencies of a test.",
|
||||
prepName, depends, commands, true);
|
||||
};
|
||||
|
||||
lg.WriteDivider(ruleFileStream);
|
||||
ruleFileStream << "# Convenience rules to build test dependencies.\n\n";
|
||||
|
||||
for (auto const& entry : this->TestPrepTargets) {
|
||||
writeForward(entry.first);
|
||||
depends.clear();
|
||||
if (regenerate) {
|
||||
depends.emplace_back("cmake_check_build_system");
|
||||
}
|
||||
commands.clear();
|
||||
commands.push_back(lg.GetRecursiveMakeCall(makefile2, entry.first));
|
||||
lg.WriteMakeRule(ruleFileStream, "Build the dependencies of a test.",
|
||||
entry.first, depends, commands, true);
|
||||
}
|
||||
writeForward("test_prep/all");
|
||||
|
||||
depends.clear();
|
||||
if (regenerate) {
|
||||
depends.emplace_back("cmake_check_build_system");
|
||||
}
|
||||
commands.clear();
|
||||
commands.push_back(lg.GetRecursiveMakeCall(makefile2, "test_prep/all"));
|
||||
lg.WriteMakeRule(ruleFileStream, "Build the dependencies of a test.",
|
||||
"test_prep/all", depends, commands, true);
|
||||
}
|
||||
|
||||
void cmGlobalUnixMakefileGenerator3::WriteHelpRule(
|
||||
|
||||
@@ -330,5 +330,8 @@ private:
|
||||
// rules that must be built to prepare the named test. Populated by
|
||||
// ComputeTestPrepTargets when CMAKE_TEST_BUILD_DEPENDS is enabled.
|
||||
std::map<std::string, std::vector<std::string>> TestPrepTargets;
|
||||
void AddDirectoryTestPrepTargets(
|
||||
cmLocalGenerator* lg,
|
||||
std::map<std::string, std::vector<std::string>>& testPrepTargets);
|
||||
bool TestPrepEnabled = false;
|
||||
};
|
||||
@@ -5248,6 +5248,30 @@ void cmGlobalXCodeGenerator::OutputXCodeProject(
|
||||
root->GetBinaryDirectory());
|
||||
}
|
||||
|
||||
std::string cmGlobalXCodeGenerator::GetTestBuildDependencyPath(
|
||||
cmGeneratorTarget const* target, std::string const& config) const
|
||||
{
|
||||
// Replicates the CMake-language logic that computes _test_bundle_dir in
|
||||
// xctest_add_test() in Modules/FindXCTest.cmake.
|
||||
if (!target->IsImported() && target->IsXCTestOnApple() &&
|
||||
this->XcodeVersion >= 73) {
|
||||
cmValue testeeName = target->GetProperty("XCTEST_TESTEE");
|
||||
cmGeneratorTarget const* testee = testeeName
|
||||
? target->GetLocalGenerator()->FindGeneratorTargetToUse(*testeeName)
|
||||
: nullptr;
|
||||
if (testee && testee->IsAppBundleOnApple()) {
|
||||
std::string path = testee->GetMacContentDirectory(
|
||||
config, cmStateEnums::RuntimeBinaryArtifact);
|
||||
if (!(this->XcodeBuildSystem == BuildSystem::Twelve &&
|
||||
this->XcodeVersion < 125 && this->SystemName != "Darwin"_s)) {
|
||||
path += "/PlugIns";
|
||||
}
|
||||
return cmStrCat(path, '/', target->GetFullName(config));
|
||||
}
|
||||
}
|
||||
return this->cmGlobalGenerator::GetTestBuildDependencyPath(target, config);
|
||||
}
|
||||
|
||||
bool cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
|
||||
std::string const& xcProjDir, cmLocalGenerator* root)
|
||||
{
|
||||
|
||||
@@ -143,6 +143,9 @@ public:
|
||||
};
|
||||
|
||||
protected:
|
||||
std::string GetTestBuildDependencyPath(
|
||||
cmGeneratorTarget const* target, std::string const& config) const override;
|
||||
|
||||
void AddExtraIDETargets() override;
|
||||
void Generate() override;
|
||||
|
||||
|
||||
@@ -243,6 +243,53 @@ cmLocalGenerator::CreateRulePlaceholderExpander(cmBuildStep buildStep) const
|
||||
: cmRulePlaceholderExpander::UseShortPaths::No);
|
||||
}
|
||||
|
||||
void cmLocalGenerator::AddDirectoryTestPrepDependency(
|
||||
std::string const& config, DirectoryTestPrepDependency dependency)
|
||||
{
|
||||
this->DiscoveryTestPrepDependencies[config].push_back(std::move(dependency));
|
||||
}
|
||||
|
||||
bool cmLocalGenerator::GetDirectoryTestPrepTarget(DirectoryTestPrepTarget& out,
|
||||
std::string const& config)
|
||||
{
|
||||
cmValue const directoryTestPrepDependencies =
|
||||
this->GetStateSnapshot().GetDirectory().GetProperty(
|
||||
"CMAKE_TEST_BUILD_DEPENDS");
|
||||
std::string const directoryId =
|
||||
cmCryptoHash(cmCryptoHash::AlgoMD5)
|
||||
.HashString(this->GetCurrentBinaryDirectory())
|
||||
.substr(0, 8);
|
||||
out.Name = cmStrCat("test_prep/directory_", directoryId);
|
||||
out.Comment =
|
||||
cmStrCat("Build extra dependencies for test prep in directory ",
|
||||
this->GetCurrentBinaryDirectory());
|
||||
out.Dependencies.clear();
|
||||
auto const discovery = this->DiscoveryTestPrepDependencies.find(config);
|
||||
if (discovery != this->DiscoveryTestPrepDependencies.end()) {
|
||||
out.Dependencies = discovery->second;
|
||||
}
|
||||
|
||||
cmList buildDepends;
|
||||
if (directoryTestPrepDependencies) {
|
||||
buildDepends.assign(
|
||||
cmList{ *directoryTestPrepDependencies, cmList::EmptyElements::Yes });
|
||||
}
|
||||
cmTestGenerator::BuildDependencies deps;
|
||||
cmTestGenerator::EvaluateBuildDependencies(
|
||||
this, config, this->Makefile->GetBacktrace(), "directory_test_prep", {},
|
||||
std::vector<std::string>(buildDepends.begin(), buildDepends.end()), deps,
|
||||
this->Makefile);
|
||||
for (cmGeneratorTarget* target : deps.Targets) {
|
||||
out.Dependencies.push_back({ target->GetName(), target });
|
||||
}
|
||||
for (cmTestGenerator::BuildDependencies::FileDependency const& file :
|
||||
deps.Files) {
|
||||
out.Dependencies.push_back(
|
||||
{ file.Path, nullptr, file.Owner, file.Generated });
|
||||
}
|
||||
return !out.Dependencies.empty();
|
||||
}
|
||||
|
||||
cmLocalGenerator::~cmLocalGenerator() = default;
|
||||
|
||||
void cmLocalGenerator::IssueMessage(MessageType type, std::string const& text,
|
||||
@@ -485,7 +532,6 @@ void cmLocalGenerator::GenerateTestFiles()
|
||||
|
||||
// Ask each test generator to write its code.
|
||||
for (auto const& tester : this->Makefile->GetTestGenerators()) {
|
||||
tester->Compute(this);
|
||||
tester->Generate(fout, config, configurationTypes);
|
||||
}
|
||||
using vec_t = std::vector<cmStateSnapshot>;
|
||||
|
||||
@@ -78,6 +78,31 @@ struct cmSourcesWithOutput
|
||||
class cmLocalGenerator : public cmOutputConverter
|
||||
{
|
||||
public:
|
||||
struct DirectoryTestPrepDependency
|
||||
{
|
||||
DirectoryTestPrepDependency(std::string raw, cmGeneratorTarget* target,
|
||||
cmGeneratorTarget* owner = nullptr,
|
||||
bool generated = false)
|
||||
: Raw(std::move(raw))
|
||||
, Target(target)
|
||||
, Owner(owner)
|
||||
, Generated(generated)
|
||||
{
|
||||
}
|
||||
|
||||
std::string Raw;
|
||||
cmGeneratorTarget* Target;
|
||||
cmGeneratorTarget* Owner;
|
||||
bool Generated;
|
||||
};
|
||||
|
||||
struct DirectoryTestPrepTarget
|
||||
{
|
||||
std::string Name;
|
||||
std::string Comment;
|
||||
std::vector<DirectoryTestPrepDependency> Dependencies;
|
||||
};
|
||||
|
||||
cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile);
|
||||
~cmLocalGenerator() override;
|
||||
|
||||
@@ -135,6 +160,11 @@ public:
|
||||
CreateRulePlaceholderExpander(
|
||||
cmBuildStep buildStep = cmBuildStep::Compile) const;
|
||||
|
||||
void AddDirectoryTestPrepDependency(std::string const& config,
|
||||
DirectoryTestPrepDependency dependency);
|
||||
bool GetDirectoryTestPrepTarget(DirectoryTestPrepTarget& out,
|
||||
std::string const& config);
|
||||
|
||||
std::string GetExeExportFlags(std::string const& linkLanguage,
|
||||
cmGeneratorTarget& tgt) const;
|
||||
|
||||
@@ -708,6 +738,8 @@ protected:
|
||||
#endif
|
||||
|
||||
private:
|
||||
std::map<std::string, std::vector<DirectoryTestPrepDependency>>
|
||||
DiscoveryTestPrepDependencies;
|
||||
/**
|
||||
* See LinearGetSourceFileWithOutput for background information
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,7 @@ struct cmTestDiscoveryArgs : ArgumentParser::ParseResult
|
||||
ArgumentParser::NonEmpty<std::vector<std::string>> DiscoveryArgs;
|
||||
ArgumentParser::NonEmpty<std::string> DiscoveryMatch;
|
||||
ArgumentParser::MaybeEmpty<std::vector<std::string>> DiscoveryProperties;
|
||||
ArgumentParser::MaybeEmpty<std::vector<std::string>> BuildDepends;
|
||||
ArgumentParser::NonEmpty<std::string> TestName;
|
||||
ArgumentParser::NonEmpty<std::vector<std::string>> TestArgs;
|
||||
ArgumentParser::MaybeEmpty<std::vector<std::string>> TestProperties;
|
||||
@@ -26,6 +27,7 @@ auto cmTestDiscoveryParser() -> cmArgumentParser<Args>
|
||||
.Bind("DISCOVERY_ARGS"_s, &Args::DiscoveryArgs)
|
||||
.Bind("DISCOVERY_MATCH"_s, &Args::DiscoveryMatch)
|
||||
.Bind("DISCOVERY_PROPERTIES"_s, &Args::DiscoveryProperties)
|
||||
.Bind("BUILD_DEPENDS"_s, &Args::BuildDepends)
|
||||
.Bind("TEST_NAME"_s, &Args::TestName)
|
||||
.Bind("TEST_ARGS"_s, &Args::TestArgs)
|
||||
.Bind("TEST_PROPERTIES"_s, &Args::TestProperties);
|
||||
|
||||
+30
-22
@@ -17,7 +17,6 @@
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmPolicies.h"
|
||||
#include "cmPropertyMap.h"
|
||||
#include "cmRange.h"
|
||||
@@ -114,24 +113,29 @@ cmTest* cmTestGenerator::GetTest() const
|
||||
return this->Test;
|
||||
}
|
||||
|
||||
bool cmTestGenerator::GetBuildDependencies(cmLocalGenerator* lg,
|
||||
std::string const& config,
|
||||
BuildDependencies& info)
|
||||
bool cmTestGenerator::EvaluateBuildDependencies(
|
||||
cmLocalGenerator* lg, std::string const& config,
|
||||
cmListFileBacktrace const& backtrace, std::string const& testName,
|
||||
std::vector<std::string> const& command,
|
||||
std::vector<std::string> const& buildDepends, BuildDependencies& info,
|
||||
cmMakefile* mf)
|
||||
{
|
||||
if (this->Test == nullptr ||
|
||||
!cmGeneratorExpression::IsValidTargetName(this->Test->GetName()) ||
|
||||
cmGlobalGenerator::IsReservedTarget(this->Test->GetName())) {
|
||||
if (!cmGeneratorExpression::IsValidTargetName(testName) ||
|
||||
cmGlobalGenerator::IsReservedTarget(testName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::set<cmGeneratorTarget*> dependencies;
|
||||
|
||||
// Get dependencies from generator expressions
|
||||
cmGeneratorExpression ge(*this->Test->GetMakefile()->GetCMakeInstance(),
|
||||
this->Test->GetBacktrace());
|
||||
for (std::string const& arg : this->Test->GetCommand()) {
|
||||
cmGeneratorExpression ge(*mf->GetCMakeInstance(), backtrace);
|
||||
std::string exe;
|
||||
for (std::string const& arg : command) {
|
||||
auto parsed = ge.Parse(arg);
|
||||
parsed->Evaluate(lg, config);
|
||||
std::string const& evaluated = parsed->Evaluate(lg, config);
|
||||
if (exe.empty()) {
|
||||
exe = evaluated;
|
||||
}
|
||||
for (cmGeneratorTarget* dep : parsed->GetTargets()) {
|
||||
if (dep && !dep->IsImported()) {
|
||||
dependencies.insert(dep);
|
||||
@@ -140,8 +144,7 @@ bool cmTestGenerator::GetBuildDependencies(cmLocalGenerator* lg,
|
||||
}
|
||||
|
||||
// Add target executed by test
|
||||
if (!this->Test->GetCommand().empty()) {
|
||||
std::string exe = this->Test->GetCommand().front();
|
||||
if (!exe.empty()) {
|
||||
cmGeneratorTarget* target = lg->FindGeneratorTargetToUse(exe);
|
||||
if (target && target->GetType() == cm::TargetType::EXECUTABLE &&
|
||||
!target->IsImported()) {
|
||||
@@ -150,7 +153,7 @@ bool cmTestGenerator::GetBuildDependencies(cmLocalGenerator* lg,
|
||||
}
|
||||
|
||||
// Add dependencies from BUILD_DEPENDS keyword
|
||||
for (auto const& depName : this->Test->GetDependencies()) {
|
||||
for (std::string const& depName : buildDepends) {
|
||||
if (depName.empty()) {
|
||||
continue;
|
||||
}
|
||||
@@ -164,14 +167,6 @@ bool cmTestGenerator::GetBuildDependencies(cmLocalGenerator* lg,
|
||||
info.Files.push_back(std::move(file));
|
||||
continue;
|
||||
}
|
||||
if (depTarget->IsImported()) {
|
||||
lg->GetMakefile()->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat("Test \"", this->Test->GetName(), "\" DEPENDS target \"",
|
||||
depName, "\" which is imported and cannot be built."),
|
||||
this->Test->GetBacktrace());
|
||||
return false;
|
||||
}
|
||||
dependencies.insert(depTarget);
|
||||
}
|
||||
|
||||
@@ -183,6 +178,19 @@ bool cmTestGenerator::GetBuildDependencies(cmLocalGenerator* lg,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmTestGenerator::GetBuildDependencies(cmLocalGenerator* lg,
|
||||
std::string const& config,
|
||||
BuildDependencies& info)
|
||||
{
|
||||
if (this->Test == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return EvaluateBuildDependencies(
|
||||
lg, config, this->Test->GetBacktrace(), this->Test->GetName(),
|
||||
this->Test->GetCommand(), this->Test->GetDependencies(), info,
|
||||
this->Test->GetMakefile());
|
||||
}
|
||||
|
||||
void cmTestGenerator::GenerateScriptActions(std::ostream& os, Indent indent)
|
||||
{
|
||||
if (this->ActionsPerConfig) {
|
||||
|
||||
@@ -15,6 +15,7 @@ class cmListFileBacktrace;
|
||||
class cmGeneratorExpression;
|
||||
class cmGeneratorTarget;
|
||||
class cmLocalGenerator;
|
||||
class cmMakefile;
|
||||
class cmTest;
|
||||
|
||||
/** \class cmTestGenerator
|
||||
@@ -43,6 +44,13 @@ public:
|
||||
std::vector<FileDependency> Files;
|
||||
};
|
||||
|
||||
static bool EvaluateBuildDependencies(
|
||||
cmLocalGenerator* lg, std::string const& config,
|
||||
cmListFileBacktrace const& backtrace, std::string const& testName,
|
||||
std::vector<std::string> const& command,
|
||||
std::vector<std::string> const& buildDepends, BuildDependencies& info,
|
||||
cmMakefile* mf);
|
||||
|
||||
cmTestGenerator(cmTest* test,
|
||||
std::vector<std::string> const& configurations =
|
||||
std::vector<std::string>());
|
||||
@@ -51,7 +59,7 @@ public:
|
||||
cmTestGenerator(cmTestGenerator const&) = delete;
|
||||
cmTestGenerator& operator=(cmTestGenerator const&) = delete;
|
||||
|
||||
void Compute(cmLocalGenerator* lg);
|
||||
virtual void Compute(cmLocalGenerator* lg);
|
||||
bool GetBuildDependencies(cmLocalGenerator* lg, std::string const& config,
|
||||
BuildDependencies& deps);
|
||||
|
||||
|
||||
@@ -865,6 +865,7 @@ add_RunCMake_test(string
|
||||
-DCMake_TEST_NO_64BIT_TIME=${CMake_TEST_NO_64BIT_TIME}
|
||||
)
|
||||
add_RunCMake_test(test_include_dirs)
|
||||
add_RunCMake_test(TestDependency)
|
||||
add_RunCMake_test(BundleUtilities)
|
||||
if(APPLE)
|
||||
add_RunCMake_test(INSTALL_NAME_DIR)
|
||||
|
||||
@@ -216,8 +216,15 @@ block()
|
||||
set(RunCMake_TEST_BINARY_DIR "${out_of_date_build_dir}")
|
||||
run_cmake(out-of-date-configure)
|
||||
run_cmake_command(out-of-date-build "${CMAKE_COMMAND}" --build "${out_of_date_build_dir}" ${out_of_date_build_config_args})
|
||||
# file_gen is created below, so file-test is initially Not Run.
|
||||
set(RunCMake_TEST_EXPECT_RESULT 8)
|
||||
set(RunCMake_TEST_EXPECT_stdout "file-test.*Not Run")
|
||||
set(RunCMake_TEST_EXPECT_stderr "Unable to find build dependency: [^\n]*file_gen")
|
||||
run_cmake_command(out-of-date-initial-test
|
||||
"${CMAKE_CTEST_COMMAND}" ${out_of_date_ctest_config_args} -V --test-dir "${out_of_date_build_dir}")
|
||||
unset(RunCMake_TEST_EXPECT_RESULT)
|
||||
unset(RunCMake_TEST_EXPECT_stdout)
|
||||
unset(RunCMake_TEST_EXPECT_stderr)
|
||||
|
||||
# Sleep for timestamp compare
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1.125)
|
||||
|
||||
@@ -4,4 +4,4 @@ Test project .*
|
||||
.*Start 3: shared-test.*
|
||||
.*Start 4: module-test.*
|
||||
.*Start 5: object-test.*
|
||||
.*Start 6: file-test.*
|
||||
.*Start 8: file-test.*
|
||||
@@ -0,0 +1,16 @@
|
||||
enable_language(CXX)
|
||||
include(GoogleTest)
|
||||
|
||||
enable_testing()
|
||||
|
||||
set(CMAKE_TEST_BUILD_DEPENDS ON)
|
||||
|
||||
add_executable(fake_gtest fake_gtest.cpp)
|
||||
|
||||
gtest_discover_tests(
|
||||
fake_gtest
|
||||
TEST_PREFIX PREP:
|
||||
TEST_FILTER basic*
|
||||
EXTRA_ARGS how now "\"brown\" cow"
|
||||
DISCOVERY_MODE POST_BUILD
|
||||
)
|
||||
@@ -492,6 +492,32 @@ function(run_GoogleTest_discovery_duplicate)
|
||||
unset(RunCMake_TEST_OUTPUT_MERGE)
|
||||
endfunction()
|
||||
|
||||
function(run_GoogleTest_build_depends)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/GoogleTest-build-depends-build)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
|
||||
set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
|
||||
endif()
|
||||
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
|
||||
|
||||
run_cmake(GoogleTestBuildDepends)
|
||||
|
||||
run_cmake_command(GoogleTest-build-depends-build
|
||||
${CMAKE_COMMAND}
|
||||
--build .
|
||||
--config Debug
|
||||
--target test_prep/all
|
||||
)
|
||||
|
||||
run_cmake_command(GoogleTest-build-depends-test
|
||||
${CMAKE_CTEST_COMMAND}
|
||||
-C Debug
|
||||
-R "^PREP:basic\\.case_(foo|bar)$"
|
||||
--no-label-summary
|
||||
)
|
||||
endfunction()
|
||||
|
||||
foreach(DISCOVERY_MODE POST_BUILD PRE_TEST)
|
||||
message(STATUS "Testing ${DISCOVERY_MODE} discovery mode via CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE global override...")
|
||||
run_GoogleTest(${DISCOVERY_MODE})
|
||||
@@ -546,3 +572,7 @@ if (NOT RunCMake_GENERATOR MATCHES "(Borland|NMake|Watcom)")
|
||||
endif()
|
||||
|
||||
run_GoogleTest_discovery_duplicate()
|
||||
|
||||
if(RunCMake_GENERATOR MATCHES "Ninja|FASTBuild|Makefiles")
|
||||
run_GoogleTest_build_depends()
|
||||
endif()
|
||||
@@ -0,0 +1,25 @@
|
||||
cmake_minimum_required(VERSION 4.3)
|
||||
project(TestDependencyAddTest C)
|
||||
|
||||
enable_testing()
|
||||
set(CMAKE_TEST_BUILD_DEPENDS ON)
|
||||
|
||||
add_executable(fake_discovery fake_discovery.c)
|
||||
# Ensure the timestamp check uses the artifact path, not the target name.
|
||||
set_target_properties(fake_discovery PROPERTIES OUTPUT_NAME renamed_discovery)
|
||||
|
||||
add_test(NAME ADD_TEST.command_genex
|
||||
COMMAND $<TARGET_FILE:fake_discovery> fake_discovery case_foo)
|
||||
set_tests_properties(ADD_TEST.command_genex PROPERTIES
|
||||
LABELS label_one)
|
||||
|
||||
add_test(NAME ADD_TEST.command_target
|
||||
COMMAND "$<1:fake_discovery>" case_bar)
|
||||
set_tests_properties(ADD_TEST.command_target PROPERTIES
|
||||
LABELS label_two)
|
||||
|
||||
add_test(NAME ADD_TEST.build_depends
|
||||
COMMAND ${CMAKE_COMMAND} -E true
|
||||
BUILD_DEPENDS fake_discovery)
|
||||
set_tests_properties(ADD_TEST.build_depends PROPERTIES
|
||||
LABELS label_three)
|
||||
@@ -0,0 +1,16 @@
|
||||
cmake_minimum_required(VERSION 4.3)
|
||||
|
||||
project(TestDependencyRunCMake NONE)
|
||||
|
||||
if(NOT DEFINED RunCMake_TEST)
|
||||
message(FATAL_ERROR "RunCMake_TEST not set")
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/${RunCMake_TEST}.cmake")
|
||||
|
||||
foreach(target IN ITEMS fake_discovery fake_gtest)
|
||||
if(TARGET ${target})
|
||||
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${target}-$<CONFIG>.txt"
|
||||
CONTENT "$<TARGET_FILE:${target}>")
|
||||
endif()
|
||||
endforeach()
|
||||
File renamed without changes.
@@ -0,0 +1,13 @@
|
||||
project(TestDependencyDirectoryGeneratedFile NONE)
|
||||
enable_testing()
|
||||
set(CMAKE_TEST_BUILD_DEPENDS ON)
|
||||
|
||||
set(output "${CMAKE_CURRENT_BINARY_DIR}/directory-generated.txt")
|
||||
add_custom_command(OUTPUT "${output}"
|
||||
COMMAND "${CMAKE_COMMAND}" -E touch "${output}"
|
||||
VERBATIM)
|
||||
add_custom_target(directory_generated_owner DEPENDS "${output}")
|
||||
set_property(DIRECTORY PROPERTY CMAKE_TEST_BUILD_DEPENDS "${output}")
|
||||
|
||||
add_test(NAME DirectoryGeneratedFileBuilt
|
||||
COMMAND "${CMAKE_COMMAND}" -E compare_files "${output}" "${output}")
|
||||
@@ -0,0 +1,17 @@
|
||||
cmake_minimum_required(VERSION 4.3)
|
||||
project(TestDependencyDiscoverGeneric C)
|
||||
|
||||
enable_testing()
|
||||
set(CMAKE_TEST_BUILD_DEPENDS ON)
|
||||
|
||||
add_executable(fake_discovery fake_discovery.c)
|
||||
|
||||
discover_tests(
|
||||
COMMAND fake_discovery
|
||||
DISCOVERY_ARGS --list_tests
|
||||
DISCOVERY_MATCH "^([^,]+),([^,]+)$"
|
||||
TEST_NAME "DISCOVER.\\1"
|
||||
TEST_ARGS "\\1"
|
||||
TEST_PROPERTIES
|
||||
LABELS "\\2"
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
cmake_minimum_required(VERSION 4.3)
|
||||
project(TestDependencyDiscoverGenericBuildDepends C)
|
||||
|
||||
enable_testing()
|
||||
set(CMAKE_TEST_BUILD_DEPENDS ON)
|
||||
|
||||
add_executable(fake_discovery fake_discovery.c)
|
||||
|
||||
discover_tests(
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/shared/fake_discovery_wrapper.cmake
|
||||
"$<TARGET_FILE:fake_discovery>"
|
||||
DISCOVERY_ARGS --list_tests
|
||||
DISCOVERY_MATCH "^([^,]+),([^,]+)$"
|
||||
TEST_NAME "DISCOVER.\\1"
|
||||
TEST_ARGS "\\1"
|
||||
TEST_PROPERTIES
|
||||
LABELS "\\2"
|
||||
BUILD_DEPENDS
|
||||
fake_discovery
|
||||
)
|
||||
@@ -0,0 +1,32 @@
|
||||
project(TestDependencyDiscoverCommands C)
|
||||
enable_testing()
|
||||
set(CMAKE_TEST_BUILD_DEPENDS ON)
|
||||
|
||||
add_executable(command_genex EXCLUDE_FROM_ALL fake_discovery.c)
|
||||
add_executable(command_wrapper EXCLUDE_FROM_ALL fake_discovery.c)
|
||||
add_executable(command_name EXCLUDE_FROM_ALL fake_discovery.c)
|
||||
|
||||
discover_tests(COMMAND "$<TARGET_FILE:command_genex>"
|
||||
DISCOVERY_ARGS --list_tests
|
||||
DISCOVERY_MATCH "^([^,]+),([^,]+)$"
|
||||
TEST_NAME "GENEX.\\1"
|
||||
TEST_ARGS "\\1")
|
||||
discover_tests(COMMAND "${CMAKE_COMMAND}" -P
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/shared/fake_discovery_wrapper.cmake"
|
||||
"$<TARGET_FILE:command_wrapper>"
|
||||
DISCOVERY_ARGS --list_tests
|
||||
DISCOVERY_MATCH "^([^,]+),([^,]+)$"
|
||||
TEST_NAME "WRAPPER.\\1"
|
||||
TEST_ARGS "\\1")
|
||||
discover_tests(COMMAND command_forward
|
||||
DISCOVERY_ARGS --list_tests
|
||||
DISCOVERY_MATCH "^([^,]+),([^,]+)$"
|
||||
TEST_NAME "FORWARD.\\1"
|
||||
TEST_ARGS "\\1")
|
||||
discover_tests(COMMAND "$<1:command_name>"
|
||||
DISCOVERY_ARGS --list_tests
|
||||
DISCOVERY_MATCH "^([^,]+),([^,]+)$"
|
||||
TEST_NAME "NAME.\\1"
|
||||
TEST_ARGS "\\1")
|
||||
|
||||
add_executable(command_forward EXCLUDE_FROM_ALL fake_discovery.c)
|
||||
@@ -0,0 +1,19 @@
|
||||
project(TestDependencyDiscoverGeneratedFile C)
|
||||
enable_testing()
|
||||
set(CMAKE_TEST_BUILD_DEPENDS ON)
|
||||
|
||||
add_executable(fake_discovery EXCLUDE_FROM_ALL fake_discovery.c)
|
||||
set(output "${CMAKE_CURRENT_BINARY_DIR}/generated.txt")
|
||||
add_custom_command(OUTPUT "${output}"
|
||||
COMMAND "${CMAKE_COMMAND}" -E touch "${output}"
|
||||
VERBATIM)
|
||||
add_custom_target(generated_owner DEPENDS "${output}")
|
||||
|
||||
discover_tests(COMMAND fake_discovery
|
||||
DISCOVERY_ARGS --list_tests
|
||||
DISCOVERY_MATCH "^([^,]+),([^,]+)$"
|
||||
TEST_NAME "GENERATED.\\1"
|
||||
TEST_ARGS "\\1"
|
||||
BUILD_DEPENDS "${output}")
|
||||
add_test(NAME GeneratedFileBuilt
|
||||
COMMAND "${CMAKE_COMMAND}" -E compare_files "${output}" "${output}")
|
||||
@@ -0,0 +1,19 @@
|
||||
project(TestDependencyDiscoverUtility C)
|
||||
enable_testing()
|
||||
set(CMAKE_TEST_BUILD_DEPENDS ON)
|
||||
|
||||
add_executable(fake_discovery EXCLUDE_FROM_ALL fake_discovery.c)
|
||||
add_custom_target(discovery_utility
|
||||
COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_CURRENT_BINARY_DIR}/utility-built.txt"
|
||||
VERBATIM)
|
||||
|
||||
discover_tests(COMMAND fake_discovery
|
||||
DISCOVERY_ARGS --list_tests
|
||||
DISCOVERY_MATCH "^([^,]+),([^,]+)$"
|
||||
TEST_NAME "UTILITY.\\1"
|
||||
TEST_ARGS "\\1"
|
||||
BUILD_DEPENDS discovery_utility)
|
||||
add_test(NAME UtilityBuilt
|
||||
COMMAND "${CMAKE_COMMAND}" -E compare_files
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/utility-built.txt"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/utility-built.txt")
|
||||
@@ -0,0 +1,16 @@
|
||||
cmake_minimum_required(VERSION 4.3)
|
||||
project(TestDependencyDiscoverPostBuild CXX)
|
||||
|
||||
include(GoogleTest)
|
||||
|
||||
enable_testing()
|
||||
set(CMAKE_TEST_BUILD_DEPENDS ON)
|
||||
|
||||
add_executable(fake_gtest fake_gtest_post_build.cpp)
|
||||
|
||||
gtest_discover_tests(
|
||||
fake_gtest
|
||||
TEST_PREFIX POST:
|
||||
TEST_FILTER basic*
|
||||
DISCOVERY_MODE POST_BUILD
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
cmake_minimum_required(VERSION 4.3)
|
||||
project(TestDependencyGoogleTestPreTest CXX)
|
||||
|
||||
include(GoogleTest)
|
||||
|
||||
enable_testing()
|
||||
set(CMAKE_TEST_BUILD_DEPENDS ON)
|
||||
|
||||
add_executable(fake_gtest fake_gtest_post_build.cpp)
|
||||
|
||||
gtest_discover_tests(
|
||||
fake_gtest
|
||||
TEST_PREFIX PRE:
|
||||
TEST_FILTER basic*
|
||||
DISCOVERY_MODE PRE_TEST
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
enable_testing()
|
||||
set(CMAKE_TEST_BUILD_DEPENDS ON)
|
||||
|
||||
add_test(NAME Direct
|
||||
COMMAND "${CMAKE_COMMAND}" -E true
|
||||
BUILD_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/dependency.txt")
|
||||
discover_tests(
|
||||
COMMAND "${CMAKE_COMMAND}" -E echo
|
||||
DISCOVERY_ARGS Discovered
|
||||
DISCOVERY_MATCH "Discovered"
|
||||
TEST_NAME Discovered
|
||||
TEST_ARGS Discovered
|
||||
BUILD_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/dependency.txt")
|
||||
File renamed without changes.
+1
-1
@@ -1,4 +1,4 @@
|
||||
CMake Warning at TestDependency-ON-byproduct\.cmake:[0-9]+ \(add_test\):
|
||||
CMake Warning at ON-byproduct\.cmake:[0-9]+ \(add_test\):
|
||||
Test "ByproductTest" BUILD_DEPENDS file
|
||||
|
||||
.*/TestDependencyByproduct-built\.txt
|
||||
+1
-1
@@ -5,7 +5,7 @@ project(TestDependencyByproduct C)
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_executable(TestDependencyByproductExe main.c)
|
||||
add_executable(TestDependencyByproductExe ../add_test/main.c)
|
||||
add_custom_command(TARGET TestDependencyByproductExe POST_BUILD
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}" -E touch
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
CMake Warning at TestDependency-ON-colon-name\.cmake:[0-9]+ \(add_test\):
|
||||
CMake Warning at ON-colon-name\.cmake:[0-9]+ \(add_test\):
|
||||
Test "Foo::Bar" has a name containing ':', which cannot be used as a
|
||||
Makefile build target\. No "test_prep/" target will be generated for it\.
|
||||
Use the Ninja generator or rename the test to build its dependencies with a
|
||||
File renamed without changes.
+1
-1
@@ -5,7 +5,7 @@ project(TestDependencyFileGenerateConfig C)
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_executable(TestDependencyGenexFileGenerate main.c)
|
||||
add_executable(TestDependencyGenexFileGenerate ../add_test/main.c)
|
||||
|
||||
set(rc_file
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/gen/TestDependencyGenexFileGenerate/$<CONFIG>/version.rc")
|
||||
@@ -0,0 +1,16 @@
|
||||
cmake_minimum_required(VERSION 4.3)
|
||||
set(CMAKE_TEST_BUILD_DEPENDS ON)
|
||||
|
||||
project(TestDependencyImported C)
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_executable(TestDependencyImportedExe ../add_test/main.c)
|
||||
|
||||
add_executable(TestDependencyImportedTool IMPORTED)
|
||||
set_target_properties(TestDependencyImportedTool PROPERTIES
|
||||
IMPORTED_LOCATION "${CMAKE_COMMAND}")
|
||||
|
||||
add_test(NAME ImportedTest
|
||||
COMMAND TestDependencyImportedExe
|
||||
BUILD_DEPENDS TestDependencyImportedTool)
|
||||
+1
-1
@@ -5,7 +5,7 @@ project(TestDependencyInterface C)
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_executable(TestDependencyInterfaceExe main.c)
|
||||
add_executable(TestDependencyInterfaceExe ../add_test/main.c)
|
||||
|
||||
# Header-only INTERFACE library is not part of the build system and must be
|
||||
# filtered out of the test_prep dependencies so that no dead
|
||||
File renamed without changes.
+2
-2
@@ -1,5 +1,5 @@
|
||||
CMake Error at TestDependency-ON-invalid-test-name\.cmake:[0-9]+ \(add_test\):
|
||||
CMake Error at ON-invalid-test-name\.cmake:[0-9]+ \(add_test\):
|
||||
add_test Cannot set build dependencies for a test with NAME "Target Build
|
||||
Test Invalid Name" which is not a valid target name\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:3 \(include\)
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
File renamed without changes.
+1
-1
@@ -1,4 +1,4 @@
|
||||
CMake Warning at TestDependency-ON-orphan\.cmake:[0-9]+ \(add_test\):
|
||||
CMake Warning at ON-orphan\.cmake:[0-9]+ \(add_test\):
|
||||
Test "OrphanTest" BUILD_DEPENDS file
|
||||
|
||||
.*/TestDependencyOrphan-built\.txt
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,18 @@
|
||||
project(TestDependencyObjectLibrary C)
|
||||
enable_testing()
|
||||
set(CMAKE_TEST_BUILD_DEPENDS ON)
|
||||
|
||||
add_executable(fake_discovery EXCLUDE_FROM_ALL fake_discovery.c)
|
||||
add_library(dependency_objects OBJECT EXCLUDE_FROM_ALL fake_discovery.c)
|
||||
file(GENERATE
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/dependency_objects-$<CONFIG>.txt"
|
||||
CONTENT "$<TARGET_OBJECTS:dependency_objects>")
|
||||
|
||||
add_test(NAME OBJECT.direct COMMAND "${CMAKE_COMMAND}" -E true
|
||||
BUILD_DEPENDS dependency_objects)
|
||||
discover_tests(COMMAND fake_discovery
|
||||
DISCOVERY_ARGS --list_tests
|
||||
DISCOVERY_MATCH "^([^,]+),([^,]+)$"
|
||||
TEST_NAME "OBJECT.\\1"
|
||||
TEST_ARGS "\\1"
|
||||
BUILD_DEPENDS dependency_objects)
|
||||
@@ -0,0 +1,289 @@
|
||||
include(RunCMake)
|
||||
|
||||
# Verify test_prep behavior
|
||||
function(run_testdependency_case CASE_NAME EXPECT_PRESENT)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${CASE_NAME}-build)
|
||||
|
||||
# 1. Configure
|
||||
run_cmake(${CASE_NAME})
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
|
||||
# 2. Verify build targets exist
|
||||
run_cmake_command(${CASE_NAME}-check
|
||||
${CMAKE_COMMAND}
|
||||
-DRunCMake_TEST_BINARY_DIR=${RunCMake_TEST_BINARY_DIR}
|
||||
-Dexpect_present=${EXPECT_PRESENT}
|
||||
-P ${RunCMake_SOURCE_DIR}/check-targets.cmake)
|
||||
|
||||
# If build targets enabled...
|
||||
if (EXPECT_PRESENT)
|
||||
|
||||
# Build test_prep target
|
||||
run_cmake_command(${CASE_NAME}-build
|
||||
${CMAKE_COMMAND} --build . ${TestDependency_BUILD_CONFIG_ARG}
|
||||
--target test_prep/TargetBuildTest)
|
||||
|
||||
# Verify building test_prep target built test dependencies
|
||||
run_cmake_command(${CASE_NAME}-build-check
|
||||
${CMAKE_COMMAND}
|
||||
-DRunCMake_TEST_BINARY_DIR=${RunCMake_TEST_BINARY_DIR}
|
||||
-P ${RunCMake_SOURCE_DIR}/build-check.cmake)
|
||||
endif()
|
||||
unset(RunCMake_TEST_NO_CLEAN)
|
||||
endfunction()
|
||||
|
||||
# Ensure generated test file includes BUILD_DEPENDs
|
||||
function(check_discovered_build_depends CASE_NAME TESTS_FILE)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
run_cmake_command(${CASE_NAME}-build-depends
|
||||
${CMAKE_COMMAND}
|
||||
-Dtests_file=${TESTS_FILE}
|
||||
-Ddependency_manifest=${TestDependency_DEPENDENCY_MANIFEST}
|
||||
-P ${RunCMake_SOURCE_DIR}/check-discovered-build-depends.cmake)
|
||||
unset(RunCMake_TEST_NO_CLEAN)
|
||||
endfunction()
|
||||
|
||||
# Find discovered test file for GTest
|
||||
function(find_discovered_tests_file OUT_VAR BINARY_DIR TARGET_NAME)
|
||||
file(GLOB discovered_tests_files
|
||||
"${BINARY_DIR}/${TARGET_NAME}*_tests.cmake")
|
||||
list(FILTER discovered_tests_files EXCLUDE REGEX [[.*_include\.cmake$]])
|
||||
list(LENGTH discovered_tests_files discovered_tests_files_length)
|
||||
if(NOT discovered_tests_files_length EQUAL 1)
|
||||
message(FATAL_ERROR
|
||||
"Expected exactly one discovered tests file for ${TARGET_NAME}, got: ${discovered_tests_files}")
|
||||
endif()
|
||||
set(${OUT_VAR} "${discovered_tests_files}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Verify ctest --out-of-date behavior
|
||||
function(run_discover_out_of_date_case CASE_NAME TARGET_NAME EXPECTED_TESTS_REGEX)
|
||||
cmake_parse_arguments(arg
|
||||
"ADD_TEST;GTEST"
|
||||
""
|
||||
""
|
||||
${ARGN})
|
||||
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${CASE_NAME}-build)
|
||||
|
||||
# 1. Configure
|
||||
run_cmake(${CASE_NAME})
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
|
||||
# 2. Build dependencies needed for the tests.
|
||||
run_cmake_command(${CASE_NAME}-build
|
||||
${CMAKE_COMMAND} --build . ${TestDependency_BUILD_CONFIG_ARG}
|
||||
--target test_prep/all)
|
||||
|
||||
# 3. Run ctest once, including any PRE_TEST discovery.
|
||||
# Ensure test stamps are newer than build dependencies even on filesystems
|
||||
# with one-second timestamp resolution. Equal timestamps are out of date.
|
||||
run_cmake_command(${CASE_NAME}-build-sleep
|
||||
${CMAKE_COMMAND} -E sleep 1.1)
|
||||
set(RunCMake_TEST_EXPECT_stderr ".*")
|
||||
run_cmake_command(${CASE_NAME}-initial
|
||||
${CMAKE_CTEST_COMMAND} ${TestDependency_CTEST_CONFIG_ARG})
|
||||
|
||||
# 4. Check that generated files include dependencies.
|
||||
if(arg_GTEST)
|
||||
find_discovered_tests_file(discovered_tests_file
|
||||
${RunCMake_TEST_BINARY_DIR} ${TARGET_NAME})
|
||||
check_discovered_build_depends(${CASE_NAME} ${discovered_tests_file})
|
||||
else()
|
||||
set(discovered_tests_file
|
||||
"${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake")
|
||||
check_discovered_build_depends(${CASE_NAME} ${discovered_tests_file})
|
||||
endif()
|
||||
|
||||
if(TestDependency_DEPENDENCY_MANIFEST)
|
||||
set(RunCMake_TEST_EXPECT_stdout "Total Tests: 0")
|
||||
run_cmake_command(${CASE_NAME}-up-to-date
|
||||
${CMAKE_CTEST_COMMAND} ${TestDependency_CTEST_CONFIG_ARG} --out-of-date -N)
|
||||
unset(RunCMake_TEST_EXPECT_stdout)
|
||||
endif()
|
||||
|
||||
# 5. Touch the actual generated artifact, after the last test timestamp.
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/${TARGET_NAME}-${TestDependency_CONFIG}.txt"
|
||||
dependent_files)
|
||||
foreach(dependent_file IN LISTS dependent_files)
|
||||
if(NOT EXISTS "${dependent_file}")
|
||||
message(FATAL_ERROR "Dependency was not built: ${dependent_file}")
|
||||
endif()
|
||||
endforeach()
|
||||
run_cmake_command(${CASE_NAME}-sleep
|
||||
${CMAKE_COMMAND} -E sleep 1.1)
|
||||
run_cmake_command(${CASE_NAME}-touch
|
||||
${CMAKE_COMMAND} -E touch ${dependent_files})
|
||||
|
||||
# 6. Run ctest --out-of-date and ensure test reruns
|
||||
set(RunCMake_TEST_EXPECT_stdout
|
||||
"${EXPECTED_TESTS_REGEX}")
|
||||
run_cmake_command(${CASE_NAME}-out-of-date
|
||||
${CMAKE_CTEST_COMMAND} ${TestDependency_CTEST_CONFIG_ARG} --out-of-date)
|
||||
unset(RunCMake_TEST_NO_CLEAN)
|
||||
unset(RunCMake_TEST_EXPECT_stderr)
|
||||
unset(RunCMake_TEST_EXPECT_stdout)
|
||||
endfunction()
|
||||
|
||||
if(RunCMake_GENERATOR MATCHES "Ninja|FASTBuild|Makefiles")
|
||||
block()
|
||||
# Use the same configuration for generated manifests, builds, and CTest,
|
||||
# including single-config generators whose default build type varies.
|
||||
set(TestDependency_CONFIG Debug)
|
||||
set(TestDependency_BUILD_CONFIG_ARG --config ${TestDependency_CONFIG})
|
||||
set(TestDependency_CTEST_CONFIG_ARG -C ${TestDependency_CONFIG})
|
||||
if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
|
||||
list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=${TestDependency_CONFIG})
|
||||
endif()
|
||||
|
||||
# Don't run tests with missing dependencies
|
||||
block()
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/MissingBuildDependency-build)
|
||||
run_cmake(MissingBuildDependency)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
block()
|
||||
set(RunCMake_TEST_EXPECT_RESULT 8)
|
||||
set(RunCMake_TEST_EXPECT_stdout "Direct[^\n]*Not Run.*Discovered[^\n]*Not Run")
|
||||
set(RunCMake_TEST_EXPECT_stderr "Unable to find build dependency: [^\n]*dependency.txt")
|
||||
run_cmake_command(MissingBuildDependency-test
|
||||
${CMAKE_CTEST_COMMAND} ${TestDependency_CTEST_CONFIG_ARG})
|
||||
run_cmake_command(MissingBuildDependency-out-of-date
|
||||
${CMAKE_CTEST_COMMAND} ${TestDependency_CTEST_CONFIG_ARG} --out-of-date)
|
||||
endblock()
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/dependency.txt" "ready\n")
|
||||
set(RunCMake_TEST_EXPECT_stdout "100% tests passed out of 2")
|
||||
run_cmake_command(MissingBuildDependency-available
|
||||
${CMAKE_CTEST_COMMAND} ${TestDependency_CTEST_CONFIG_ARG} --out-of-date)
|
||||
# Missing dependencies make tests out of date even with existing stamps.
|
||||
file(REMOVE "${RunCMake_TEST_BINARY_DIR}/dependency.txt")
|
||||
set(RunCMake_TEST_EXPECT_RESULT 8)
|
||||
set(RunCMake_TEST_EXPECT_stdout "Direct[^\n]*Not Run.*Discovered[^\n]*Not Run")
|
||||
set(RunCMake_TEST_EXPECT_stderr "Unable to find build dependency: [^\n]*dependency.txt")
|
||||
run_cmake_command(MissingBuildDependency-removed
|
||||
${CMAKE_CTEST_COMMAND} ${TestDependency_CTEST_CONFIG_ARG} --out-of-date)
|
||||
endblock()
|
||||
|
||||
# "Failure" cases, do not generate test dependencies
|
||||
block()
|
||||
run_testdependency_case(DEFAULT FALSE)
|
||||
run_testdependency_case(OFF FALSE)
|
||||
run_cmake(ON-invalid-test-name)
|
||||
endblock()
|
||||
|
||||
# A header-only INTERFACE library dependency is filtered out by the
|
||||
# generator-independent dependency resolution, so building the
|
||||
# test_prep target must not fail on a missing rule.
|
||||
block()
|
||||
set(RunCMake_TEST_BINARY_DIR
|
||||
${RunCMake_BINARY_DIR}/ON-interface-build)
|
||||
run_cmake(ON-interface)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
set(RunCMake_TEST_OUTPUT_MERGE 1)
|
||||
run_cmake_command(ON-interface-build
|
||||
${CMAKE_COMMAND} --build . ${TestDependency_BUILD_CONFIG_ARG}
|
||||
--target test_prep/InterfaceTest)
|
||||
unset(RunCMake_TEST_OUTPUT_MERGE)
|
||||
endblock()
|
||||
|
||||
# Imported dependencies are accepted without requiring a build rule.
|
||||
block()
|
||||
set(RunCMake_TEST_BINARY_DIR
|
||||
${RunCMake_BINARY_DIR}/ON-imported-build)
|
||||
run_cmake(ON-imported)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
set(RunCMake_TEST_OUTPUT_MERGE 1)
|
||||
run_cmake_command(ON-imported-build
|
||||
${CMAKE_COMMAND} --build . ${TestDependency_BUILD_CONFIG_ARG}
|
||||
--target test_prep/ImportedTest)
|
||||
unset(RunCMake_TEST_OUTPUT_MERGE)
|
||||
run_cmake_command(ON-imported-test
|
||||
${CMAKE_CTEST_COMMAND} ${TestDependency_CTEST_CONFIG_ARG}
|
||||
-R "^ImportedTest$")
|
||||
endblock()
|
||||
|
||||
# Exceptions for Makefile generator
|
||||
if(RunCMake_GENERATOR MATCHES Makefiles)
|
||||
# Diagnostics specific to the Makefile generators.
|
||||
block()
|
||||
# A ':' in a test name cannot be expressed as a Makefile target.
|
||||
set(RunCMake_TEST_BINARY_DIR
|
||||
${RunCMake_BINARY_DIR}/ON-colon-name-build)
|
||||
run_cmake(ON-colon-name)
|
||||
endblock()
|
||||
block()
|
||||
# A byproduct file cannot be built through a single owning target.
|
||||
set(RunCMake_TEST_BINARY_DIR
|
||||
${RunCMake_BINARY_DIR}/ON-byproduct-build)
|
||||
run_cmake(ON-byproduct)
|
||||
endblock()
|
||||
block()
|
||||
# A custom-command output owned by no target cannot be built.
|
||||
set(RunCMake_TEST_BINARY_DIR
|
||||
${RunCMake_BINARY_DIR}/ON-orphan-build)
|
||||
run_cmake(ON-orphan)
|
||||
endblock()
|
||||
endif()
|
||||
|
||||
# Verify successful behavior
|
||||
block()
|
||||
foreach(case IN ITEMS DiscoverTestsUtility DiscoverTestsCommands
|
||||
DiscoverTestsGeneratedFile DirectoryGeneratedFile)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build)
|
||||
run_cmake(${case})
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
run_cmake_command(${case}-build
|
||||
${CMAKE_COMMAND} --build . ${TestDependency_BUILD_CONFIG_ARG}
|
||||
--target test_prep/all)
|
||||
set(RunCMake_TEST_EXPECT_stdout "100% tests passed")
|
||||
run_cmake_command(${case}-test
|
||||
${CMAKE_CTEST_COMMAND} ${TestDependency_CTEST_CONFIG_ARG})
|
||||
unset(RunCMake_TEST_EXPECT_stdout)
|
||||
unset(RunCMake_TEST_NO_CLEAN)
|
||||
endforeach()
|
||||
|
||||
if(RunCMake_GENERATOR STREQUAL "Ninja Multi-Config")
|
||||
set(RunCMake_TEST_BINARY_DIR
|
||||
${RunCMake_BINARY_DIR}/ON-file-generate-config-build)
|
||||
run_cmake(ON-file-generate-config)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
run_cmake_command(ON-file-generate-config-build
|
||||
${CMAKE_COMMAND} --build . --config Debug
|
||||
--target test_prep/FileGenerateConfigTest)
|
||||
run_cmake_command(ON-file-generate-config-test
|
||||
${CMAKE_CTEST_COMMAND} -C Debug -R "^FileGenerateConfigTest$")
|
||||
unset(RunCMake_TEST_NO_CLEAN)
|
||||
endif()
|
||||
|
||||
block()
|
||||
set(TestDependency_DEPENDENCY_MANIFEST
|
||||
"${RunCMake_BINARY_DIR}/ObjectLibrary-build/dependency_objects-${TestDependency_CONFIG}.txt")
|
||||
run_discover_out_of_date_case(ObjectLibrary dependency_objects
|
||||
"OBJECT\\.direct.*OBJECT\\.case_foo.*OBJECT\\.case_bar")
|
||||
endblock()
|
||||
|
||||
# Verify test_depends
|
||||
run_testdependency_case(ON TRUE)
|
||||
|
||||
# Verify test_depends + --out-of-date for add_test
|
||||
run_discover_out_of_date_case(AddTest fake_discovery
|
||||
"ADD_TEST\\.command_genex.*ADD_TEST\\.command_target.*ADD_TEST\\.build_depends"
|
||||
ADD_TEST)
|
||||
|
||||
# Verify test_depends + --out-of-date for discover_tests
|
||||
run_discover_out_of_date_case(DiscoverTests fake_discovery
|
||||
"DISCOVER\\.case_foo.*DISCOVER\\.case_bar")
|
||||
|
||||
# Verify explicit BUILD_DEPENDS for discover_tests
|
||||
run_discover_out_of_date_case(DiscoverTestsBuildDepends fake_discovery
|
||||
"DISCOVER\\.case_foo.*DISCOVER\\.case_bar")
|
||||
|
||||
# Verify test_depends + --out-of-date for gtest_discover_tests
|
||||
run_discover_out_of_date_case(GoogleTest-PRE_TEST fake_gtest
|
||||
"PRE:basic\\.case_foo.*PRE:basic\\.case_bar"
|
||||
GTEST)
|
||||
run_discover_out_of_date_case(GoogleTest-POST_BUILD fake_gtest
|
||||
"POST:basic\\.case_foo.*POST:basic\\.case_bar"
|
||||
GTEST)
|
||||
endblock()
|
||||
endblock()
|
||||
endif()
|
||||
+2
-2
@@ -2,7 +2,7 @@ project(TestDependency C)
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_executable(TestDependencyExe main.c)
|
||||
add_executable(TestDependencyExe ../add_test/main.c)
|
||||
add_custom_command(TARGET TestDependencyExe POST_BUILD
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}" -E touch
|
||||
@@ -10,7 +10,7 @@ add_custom_command(TARGET TestDependencyExe POST_BUILD
|
||||
BYPRODUCTS
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/TestDependencyExe-built.txt")
|
||||
|
||||
add_executable(TestDependencyGenex main.c)
|
||||
add_executable(TestDependencyGenex ../add_test/main.c)
|
||||
add_custom_command(TARGET TestDependencyGenex POST_BUILD
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}" -E touch
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,33 @@
|
||||
if(NOT DEFINED tests_file)
|
||||
message(FATAL_ERROR "tests_file not set")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${tests_file}")
|
||||
message(FATAL_ERROR "Discovered tests file not found: ${tests_file}")
|
||||
endif()
|
||||
|
||||
file(READ "${tests_file}" content)
|
||||
|
||||
if(NOT content MATCHES "_CMAKE_TEST_BUILD_DEPENDS"
|
||||
AND NOT content MATCHES "BUILD_DEPENDS")
|
||||
message(FATAL_ERROR
|
||||
"Expected discovered tests to contain BUILD_DEPENDS metadata.")
|
||||
endif()
|
||||
|
||||
if(dependency_manifest)
|
||||
file(READ "${dependency_manifest}" dependencies)
|
||||
file(STRINGS "${tests_file}" metadata REGEX "BUILD_DEPENDS")
|
||||
foreach(dependency IN LISTS dependencies)
|
||||
set(count 0)
|
||||
foreach(line IN LISTS metadata)
|
||||
string(FIND "${line}" "${dependency}" pos)
|
||||
if(NOT pos EQUAL -1)
|
||||
math(EXPR count "${count} + 1")
|
||||
endif()
|
||||
endforeach()
|
||||
# Both add_test and discover_tests must record the object, not its target name.
|
||||
if(count LESS 2)
|
||||
message(FATAL_ERROR "Missing object file dependency metadata: ${dependency}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
+1
-1
@@ -16,7 +16,7 @@ file(GLOB build_files LIST_DIRECTORIES false
|
||||
set(found FALSE)
|
||||
foreach(build_file IN LISTS build_files)
|
||||
file(READ "${build_file}" content)
|
||||
if(content MATCHES "test_prep.all|test_prep.TargetBuildTest")
|
||||
if(content MATCHES "test_prep.all|test_prep.TargetBuildTest|test_prep.directory_")
|
||||
set(found TRUE)
|
||||
break()
|
||||
endif()
|
||||
@@ -0,0 +1,13 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc >= 2 && strcmp(argv[1], "--list_tests") == 0) {
|
||||
puts("case_foo,label_one");
|
||||
puts("case_bar,label_two");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc >= 2 && std::string(argv[1]) == "--gtest_list_tests") {
|
||||
bool saw_json = false;
|
||||
bool saw_basic_filter = false;
|
||||
for (int i = 2; i < argc; ++i) {
|
||||
std::string const arg = argv[i];
|
||||
if (arg.find("--gtest_output=json:") == 0) {
|
||||
saw_json = true;
|
||||
} else if (arg == "--gtest_filter=basic*") {
|
||||
saw_basic_filter = true;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (saw_json && argc >= 3) {
|
||||
for (int i = 2; i < argc; ++i) {
|
||||
std::string const arg = argv[i];
|
||||
if (arg.find("--gtest_output=json:") == 0) {
|
||||
std::string const json_path = arg.substr(20);
|
||||
std::ofstream json(json_path.c_str());
|
||||
json << "{\n"
|
||||
" \"name\": \"AllTests\",\n"
|
||||
" \"testsuites\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"basic\",\n"
|
||||
" \"tests\": 2,\n"
|
||||
" \"testsuite\": [\n"
|
||||
" { \"name\": \"case_foo\", \"file\": \"file1.cpp\", "
|
||||
"\"line\": 1 },\n"
|
||||
" { \"name\": \"case_bar\", \"file\": \"file1.cpp\", "
|
||||
"\"line\": 2 }\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
"}\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!saw_basic_filter && argc >= 3) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "basic.\n";
|
||||
std::cout << " case_foo\n";
|
||||
std::cout << " case_bar\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
set(args)
|
||||
math(EXPR last_arg_index "${CMAKE_ARGC} - 1")
|
||||
foreach(arg_index RANGE 4 ${last_arg_index})
|
||||
list(APPEND args "${CMAKE_ARGV${arg_index}}")
|
||||
endforeach()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_ARGV3}" ${args}
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
@@ -61,95 +61,3 @@ block()
|
||||
run_cmake_command(TestLauncher-test ${CMAKE_CTEST_COMMAND} -C Debug -V)
|
||||
endblock()
|
||||
unset(RunCMake_TEST_OPTIONS)
|
||||
|
||||
function(run_testdependency_case CASE_NAME EXPECT_PRESENT)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/TestDependency-${CASE_NAME}-build)
|
||||
run_cmake(TestDependency-${CASE_NAME})
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
run_cmake_command(TestDependency-${CASE_NAME}-check
|
||||
${CMAKE_COMMAND}
|
||||
-DRunCMake_TEST_BINARY_DIR=${RunCMake_TEST_BINARY_DIR}
|
||||
-Dexpect_present=${EXPECT_PRESENT}
|
||||
-P ${RunCMake_SOURCE_DIR}/TestDependency-check-targets.cmake)
|
||||
unset(RunCMake_TEST_NO_CLEAN)
|
||||
endfunction()
|
||||
|
||||
if(RunCMake_GENERATOR MATCHES "Ninja|FASTBuild|Makefiles")
|
||||
block()
|
||||
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
|
||||
set(TestDependency_BUILD_CONFIG_ARG --config Debug)
|
||||
else()
|
||||
set(TestDependency_BUILD_CONFIG_ARG)
|
||||
endif()
|
||||
|
||||
run_testdependency_case(DEFAULT FALSE)
|
||||
run_testdependency_case(OFF FALSE)
|
||||
run_cmake(TestDependency-ON-invalid-test-name)
|
||||
|
||||
block()
|
||||
# A header-only INTERFACE library dependency is filtered out by the
|
||||
# generator-independent dependency resolution, so building the
|
||||
# test_prep target must not fail on a missing rule.
|
||||
set(RunCMake_TEST_BINARY_DIR
|
||||
${RunCMake_BINARY_DIR}/TestDependency-ON-interface-build)
|
||||
run_cmake(TestDependency-ON-interface)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
set(RunCMake_TEST_OUTPUT_MERGE 1)
|
||||
run_cmake_command(TestDependency-ON-interface-build
|
||||
${CMAKE_COMMAND} --build . ${TestDependency_BUILD_CONFIG_ARG}
|
||||
--target test_prep/InterfaceTest)
|
||||
endblock()
|
||||
|
||||
if(RunCMake_GENERATOR MATCHES Makefiles)
|
||||
# Diagnostics specific to the Makefile generators.
|
||||
block()
|
||||
# A ':' in a test name cannot be expressed as a Makefile target.
|
||||
set(RunCMake_TEST_BINARY_DIR
|
||||
${RunCMake_BINARY_DIR}/TestDependency-ON-colon-name-build)
|
||||
run_cmake(TestDependency-ON-colon-name)
|
||||
endblock()
|
||||
block()
|
||||
# A byproduct file cannot be built through a single owning target.
|
||||
set(RunCMake_TEST_BINARY_DIR
|
||||
${RunCMake_BINARY_DIR}/TestDependency-ON-byproduct-build)
|
||||
run_cmake(TestDependency-ON-byproduct)
|
||||
endblock()
|
||||
block()
|
||||
# A custom-command output owned by no target cannot be built.
|
||||
set(RunCMake_TEST_BINARY_DIR
|
||||
${RunCMake_BINARY_DIR}/TestDependency-ON-orphan-build)
|
||||
run_cmake(TestDependency-ON-orphan)
|
||||
endblock()
|
||||
endif()
|
||||
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/TestDependency-ON-build)
|
||||
run_testdependency_case(ON TRUE)
|
||||
|
||||
if(RunCMake_GENERATOR MATCHES "Ninja" AND RunCMake_GENERATOR_IS_MULTI_CONFIG)
|
||||
block()
|
||||
set(RunCMake_TEST_BINARY_DIR
|
||||
${RunCMake_BINARY_DIR}/TestDependency-ON-file-generate-config-build)
|
||||
run_cmake(TestDependency-ON-file-generate-config)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
run_cmake_command(TestDependency-ON-file-generate-config-build
|
||||
${CMAKE_COMMAND} --build . --config Debug
|
||||
--target test_prep/FileGenerateConfigTest)
|
||||
endblock()
|
||||
endif()
|
||||
|
||||
set(RunCMake_TEST_OUTPUT_MERGE 1)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
run_cmake_command(TestDependency-ON-all
|
||||
${CMAKE_COMMAND} --build . ${TestDependency_BUILD_CONFIG_ARG}
|
||||
--target test_prep/all)
|
||||
run_cmake_command(TestDependency-ON-build
|
||||
${CMAKE_COMMAND} --build . ${TestDependency_BUILD_CONFIG_ARG}
|
||||
--target test_prep/TargetBuildTest)
|
||||
run_cmake_command(TestDependency-ON-build-check
|
||||
${CMAKE_COMMAND}
|
||||
-DRunCMake_TEST_BINARY_DIR=${RunCMake_TEST_BINARY_DIR}
|
||||
-P ${RunCMake_SOURCE_DIR}/TestDependency-build-check.cmake)
|
||||
unset(RunCMake_TEST_OUTPUT_MERGE)
|
||||
unset(RunCMake_TEST_NO_CLEAN)
|
||||
endblock()
|
||||
endif()
|
||||
Reference in new issue
Block a user