mirror of
https://github.com/Kitware/CMake.git
synced 2026-08-04 14:50:23 +00:00
ctest_build: add PRESET option
Allow users to specify a build preset when using CTest dashboard scripts. Issue: #27630
This commit is contained in:
committed by
Brad King
parent
de52c08ba2
commit
348ff1938b
@@ -15,6 +15,7 @@ Perform the :ref:`CTest Build Step` as a :ref:`Dashboard Client`.
|
||||
[NUMBER_WARNINGS <num-warn-var>]
|
||||
[RETURN_VALUE <result-var>]
|
||||
[CAPTURE_CMAKE_ERROR <result-var>]
|
||||
[PRESET <preset>]
|
||||
)
|
||||
|
||||
Build the project and store results in ``Build.xml``
|
||||
@@ -75,6 +76,15 @@ The options are:
|
||||
``NUMBER_WARNINGS <num-warn-var>``
|
||||
Store the number of build warnings detected in the given variable.
|
||||
|
||||
``PRESET <preset>``
|
||||
.. versionadded:: 4.4
|
||||
|
||||
Specify a :manual:`preset <cmake-presets(7)>` to use when building the
|
||||
project. Any value set in the CTest script will take priority over a
|
||||
corresponding setting from the preset. For example, the ``TARGET``
|
||||
argument will override the :preset:`buildPresets.targets` setting from
|
||||
the chosen preset.
|
||||
|
||||
``RETURN_VALUE <result-var>``
|
||||
Store the return value of the native build tool in the given variable.
|
||||
|
||||
|
||||
5
Help/release/dev/ctest_build_preset_option.rst
Normal file
5
Help/release/dev/ctest_build_preset_option.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
ctest_build_preset_option
|
||||
-------------------------
|
||||
|
||||
* The :command:`ctest_build` command gained a ``PRESET`` option
|
||||
drive the build through a build preset.
|
||||
@@ -6,14 +6,17 @@
|
||||
#include <utility>
|
||||
|
||||
#include <cm/memory>
|
||||
#include <cm/optional>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmArgumentParser.h"
|
||||
#include "cmCMakePresetsGraph.h"
|
||||
#include "cmCTest.h"
|
||||
#include "cmCTestBuildHandler.h"
|
||||
#include "cmCTestGenericHandler.h"
|
||||
#include "cmExecutionStatus.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmJSONState.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
@@ -21,6 +24,8 @@
|
||||
#include "cmValue.h"
|
||||
#include "cmake.h"
|
||||
|
||||
using BuildPreset = cmCMakePresetsGraph::BuildPreset;
|
||||
|
||||
bool cmCTestBuildCommand::InitialPass(std::vector<std::string> const& args,
|
||||
cmExecutionStatus& status) const
|
||||
{
|
||||
@@ -32,7 +37,8 @@ bool cmCTestBuildCommand::InitialPass(std::vector<std::string> const& args,
|
||||
.Bind("CONFIGURATION"_s, &BuildArguments::Configuration)
|
||||
.Bind("FLAGS"_s, &BuildArguments::Flags)
|
||||
.Bind("PROJECT_NAME"_s, &BuildArguments::ProjectName)
|
||||
.Bind("PARALLEL_LEVEL"_s, &BuildArguments::ParallelLevel);
|
||||
.Bind("PARALLEL_LEVEL"_s, &BuildArguments::ParallelLevel)
|
||||
.Bind("PRESET"_s, &BuildArguments::Preset);
|
||||
|
||||
return this->Invoke(parser, args, status, [&](BuildArguments& a) {
|
||||
return this->ExecuteHandlerCommand(a, status);
|
||||
@@ -46,32 +52,87 @@ std::unique_ptr<cmCTestGenericHandler> cmCTestBuildCommand::InitializeHandler(
|
||||
auto const& args = static_cast<BuildArguments&>(arguments);
|
||||
auto handler = cm::make_unique<cmCTestBuildHandler>(this->CTest);
|
||||
|
||||
// Build configuration is set according to the following priority order:
|
||||
// 1) The CONFIGURATION option to ctest_build()
|
||||
// 2) CTEST_BUILD_CONFIGURATION script variable
|
||||
// 3) CTEST_CONFIGURATION_TYPE script variable
|
||||
// 4) The ctest -C command line argument
|
||||
// 5) The configuration entry from the build preset
|
||||
cmValue ctestBuildConfiguration =
|
||||
mf.GetDefinition("CTEST_BUILD_CONFIGURATION");
|
||||
std::string cmakeBuildConfiguration = cmNonempty(args.Configuration)
|
||||
? args.Configuration
|
||||
: cmNonempty(ctestBuildConfiguration) ? *ctestBuildConfiguration
|
||||
: this->CTest->GetConfigType();
|
||||
|
||||
std::string const& cmakeBuildAdditionalFlags = cmNonempty(args.Flags)
|
||||
? args.Flags
|
||||
: mf.GetSafeDefinition("CTEST_BUILD_FLAGS");
|
||||
std::string const& cmakeBuildTarget = cmNonempty(args.Target)
|
||||
? args.Target
|
||||
: mf.GetSafeDefinition("CTEST_BUILD_TARGET");
|
||||
|
||||
cmValue ctestBuildCommand = mf.GetDefinition("CTEST_BUILD_COMMAND");
|
||||
if (cmNonempty(ctestBuildCommand)) {
|
||||
this->CTest->SetCTestConfiguration("MakeCommand", *ctestBuildCommand,
|
||||
args.Quiet);
|
||||
} else if (!args.Preset.empty()) {
|
||||
std::string const sourceDirectory =
|
||||
mf.GetSafeDefinition("CTEST_SOURCE_DIRECTORY");
|
||||
|
||||
cmCMakePresetsGraph presetsGraph;
|
||||
if (!presetsGraph.ReadProjectPresets(sourceDirectory)) {
|
||||
status.SetError(
|
||||
cmStrCat("Could not read presets from \"", sourceDirectory,
|
||||
"\": ", presetsGraph.parseState.GetErrorMessage()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto resolveResult =
|
||||
presetsGraph.ResolvePreset(args.Preset, presetsGraph.BuildPresets);
|
||||
auto resolveError = cmCMakePresetsGraph::FormatPresetError<BuildPreset>(
|
||||
resolveResult.StatusCode, resolveResult.ErrorPresetName,
|
||||
sourceDirectory);
|
||||
if (resolveError) {
|
||||
status.SetError(*resolveError);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string buildCommand =
|
||||
cmStrCat('"', cmSystemTools::GetCMakeCommand(), '"');
|
||||
buildCommand += " --build . --preset \"";
|
||||
buildCommand += args.Preset;
|
||||
buildCommand += "\"";
|
||||
|
||||
if (!cmakeBuildConfiguration.empty()) {
|
||||
buildCommand += " --config \"";
|
||||
buildCommand += cmakeBuildConfiguration;
|
||||
buildCommand += "\"";
|
||||
}
|
||||
|
||||
if (!cmakeBuildTarget.empty()) {
|
||||
buildCommand += " --target \"";
|
||||
buildCommand += cmakeBuildTarget;
|
||||
buildCommand += "\"";
|
||||
}
|
||||
|
||||
if (!args.ParallelLevel.empty()) {
|
||||
buildCommand += " --parallel ";
|
||||
buildCommand += args.ParallelLevel;
|
||||
}
|
||||
|
||||
if (!cmakeBuildAdditionalFlags.empty()) {
|
||||
buildCommand += " -- ";
|
||||
buildCommand += cmakeBuildAdditionalFlags;
|
||||
}
|
||||
|
||||
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
|
||||
"SetMakeCommand:" << buildCommand << "\n", args.Quiet);
|
||||
this->CTest->SetCTestConfiguration("MakeCommand", buildCommand,
|
||||
args.Quiet);
|
||||
} else {
|
||||
cmValue cmakeGeneratorName = mf.GetDefinition("CTEST_CMAKE_GENERATOR");
|
||||
|
||||
// Build configuration is determined by: CONFIGURATION argument,
|
||||
// or CTEST_BUILD_CONFIGURATION script variable, or
|
||||
// CTEST_CONFIGURATION_TYPE script variable, or ctest -C command
|
||||
// line argument... in that order.
|
||||
//
|
||||
cmValue ctestBuildConfiguration =
|
||||
mf.GetDefinition("CTEST_BUILD_CONFIGURATION");
|
||||
std::string cmakeBuildConfiguration = cmNonempty(args.Configuration)
|
||||
? args.Configuration
|
||||
: cmNonempty(ctestBuildConfiguration) ? *ctestBuildConfiguration
|
||||
: this->CTest->GetConfigType();
|
||||
|
||||
std::string const& cmakeBuildAdditionalFlags = cmNonempty(args.Flags)
|
||||
? args.Flags
|
||||
: mf.GetSafeDefinition("CTEST_BUILD_FLAGS");
|
||||
std::string const& cmakeBuildTarget = cmNonempty(args.Target)
|
||||
? args.Target
|
||||
: mf.GetSafeDefinition("CTEST_BUILD_TARGET");
|
||||
|
||||
if (cmNonempty(cmakeGeneratorName)) {
|
||||
if (cmakeBuildConfiguration.empty()) {
|
||||
cmakeBuildConfiguration = "Release";
|
||||
|
||||
@@ -23,6 +23,7 @@ protected:
|
||||
std::string Flags;
|
||||
std::string ProjectName;
|
||||
std::string ParallelLevel;
|
||||
std::string Preset;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
10
Tests/RunCMake/ctest_build/BuildPreset-check.cmake
Normal file
10
Tests/RunCMake/ctest_build/BuildPreset-check.cmake
Normal file
@@ -0,0 +1,10 @@
|
||||
file(GLOB build_xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/Build.xml")
|
||||
if(build_xml_file)
|
||||
file(READ "${build_xml_file}" build_xml)
|
||||
if(NOT build_xml MATCHES "--preset.*my-build-preset")
|
||||
set(RunCMake_TEST_FAILED
|
||||
"Build.xml does not contain the expected --preset argument")
|
||||
endif()
|
||||
else()
|
||||
set(RunCMake_TEST_FAILED "Build.xml not found")
|
||||
endif()
|
||||
21
Tests/RunCMake/ctest_build/CMakePresets.json.in
Normal file
21
Tests/RunCMake/ctest_build/CMakePresets.json.in
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"version": 2,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 20,
|
||||
"patch": 0
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "my-configure-preset",
|
||||
"generator": "@RunCMake_GENERATOR@",
|
||||
"binaryDir": "${sourceDir}/../BuildPreset-build"
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "my-build-preset",
|
||||
"configurePreset": "my-configure-preset"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -71,6 +71,15 @@ set(RunCMake_BUILD_COMMAND "${COLOR_WARNING}")
|
||||
run_ctest(IgnoreColor)
|
||||
unset(RunCMake_BUILD_COMMAND)
|
||||
|
||||
set(RunCMake_USE_CUSTOM_BUILD_COMMAND FALSE)
|
||||
set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/BuildPreset")
|
||||
configure_file(
|
||||
"${RunCMake_SOURCE_DIR}/CMakePresets.json.in"
|
||||
"${RunCMake_TEST_SOURCE_DIR}/CMakePresets.json"
|
||||
@ONLY)
|
||||
run_ctest_build(BuildPreset PRESET my-build-preset)
|
||||
unset(RunCMake_TEST_SOURCE_DIR)
|
||||
|
||||
set(RunCMake_USE_CUSTOM_BUILD_COMMAND FALSE)
|
||||
if(RunCMake_GENERATOR MATCHES "Ninja")
|
||||
function(run_NinjaLauncherSingleBuildFailure)
|
||||
|
||||
Reference in New Issue
Block a user