Files
CMake/Source/cmCMakePresetsFile.h
friendlyanon 06e6981336 cmake-presets: Make generator and binaryDir fields optional
In v3 of the presets, generator and buildDir can be omitted to fall
back to regular cmake behavior when these values are not explicitly
provided by the user.

Fixes: #21987
2021-04-07 01:24:44 +02:00

363 lines
10 KiB
C++

/* 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 <functional>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <cm/optional>
class cmCMakePresetsFile
{
public:
enum class ReadFileResult
{
READ_OK,
FILE_NOT_FOUND,
JSON_PARSE_ERROR,
INVALID_ROOT,
NO_VERSION,
INVALID_VERSION,
UNRECOGNIZED_VERSION,
INVALID_CMAKE_VERSION,
UNRECOGNIZED_CMAKE_VERSION,
INVALID_PRESETS,
INVALID_PRESET,
INVALID_VARIABLE,
DUPLICATE_PRESETS,
CYCLIC_PRESET_INHERITANCE,
USER_PRESET_INHERITANCE,
INVALID_MACRO_EXPANSION,
BUILD_TEST_PRESETS_UNSUPPORTED,
INVALID_CONFIGURE_PRESET,
INSTALL_PREFIX_UNSUPPORTED,
INVALID_CONDITION,
CONDITION_UNSUPPORTED,
};
enum class ArchToolsetStrategy
{
Set,
External,
};
class CacheVariable
{
public:
std::string Type;
std::string Value;
};
class Condition;
class Preset
{
public:
#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
// The move assignment operators for several STL classes did not become
// noexcept until C++17, which causes some tools to warn about this move
// assignment operator throwing an exception when it shouldn't. Disable the
// move assignment operator until C++17 is enabled.
// Explicitly defining a copy assignment operator prevents the compiler
// from automatically generating a move assignment operator.
Preset& operator=(const Preset& /*other*/) = default;
#endif
virtual ~Preset() = default;
std::string Name;
std::vector<std::string> Inherits;
bool Hidden;
bool User;
std::string DisplayName;
std::string Description;
std::shared_ptr<Condition> ConditionEvaluator;
bool ConditionResult = true;
std::map<std::string, cm::optional<std::string>> Environment;
virtual ReadFileResult VisitPresetInherit(const Preset& parent) = 0;
virtual ReadFileResult VisitPresetBeforeInherit()
{
return ReadFileResult::READ_OK;
}
virtual ReadFileResult VisitPresetAfterInherit(int /* version */)
{
return ReadFileResult::READ_OK;
}
};
class ConfigurePreset : public Preset
{
public:
#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
// The move assignment operators for several STL classes did not become
// noexcept until C++17, which causes some tools to warn about this move
// assignment operator throwing an exception when it shouldn't. Disable the
// move assignment operator until C++17 is enabled.
// Explicitly defining a copy assignment operator prevents the compiler
// from automatically generating a move assignment operator.
ConfigurePreset& operator=(const ConfigurePreset& /*other*/) = default;
#endif
std::string Generator;
std::string Architecture;
cm::optional<ArchToolsetStrategy> ArchitectureStrategy;
std::string Toolset;
cm::optional<ArchToolsetStrategy> ToolsetStrategy;
std::string BinaryDir;
std::string InstallDir;
std::map<std::string, cm::optional<CacheVariable>> CacheVariables;
cm::optional<bool> WarnDev;
cm::optional<bool> ErrorDev;
cm::optional<bool> WarnDeprecated;
cm::optional<bool> ErrorDeprecated;
cm::optional<bool> WarnUninitialized;
cm::optional<bool> WarnUnusedCli;
cm::optional<bool> WarnSystemVars;
cm::optional<bool> DebugOutput;
cm::optional<bool> DebugTryCompile;
cm::optional<bool> DebugFind;
ReadFileResult VisitPresetInherit(const Preset& parent) override;
ReadFileResult VisitPresetBeforeInherit() override;
ReadFileResult VisitPresetAfterInherit(int version) override;
};
class BuildPreset : public Preset
{
public:
#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
// The move assignment operators for several STL classes did not become
// noexcept until C++17, which causes some tools to warn about this move
// assignment operator throwing an exception when it shouldn't. Disable the
// move assignment operator until C++17 is enabled.
// Explicitly defining a copy assignment operator prevents the compiler
// from automatically generating a move assignment operator.
BuildPreset& operator=(const BuildPreset& /*other*/) = default;
#endif
std::string ConfigurePreset;
cm::optional<bool> InheritConfigureEnvironment;
cm::optional<int> Jobs;
std::vector<std::string> Targets;
std::string Configuration;
cm::optional<bool> CleanFirst;
cm::optional<bool> Verbose;
std::vector<std::string> NativeToolOptions;
ReadFileResult VisitPresetInherit(const Preset& parent) override;
ReadFileResult VisitPresetAfterInherit(int /* version */) override;
};
class TestPreset : public Preset
{
public:
#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
// The move assignment operators for several STL classes did not become
// noexcept until C++17, which causes some tools to warn about this move
// assignment operator throwing an exception when it shouldn't. Disable the
// move assignment operator until C++17 is enabled.
// Explicitly defining a copy assignment operator prevents the compiler
// from automatically generating a move assignment operator.
TestPreset& operator=(const TestPreset& /*other*/) = default;
#endif
struct OutputOptions
{
enum class VerbosityEnum
{
Default,
Verbose,
Extra
};
cm::optional<bool> ShortProgress;
cm::optional<VerbosityEnum> Verbosity;
cm::optional<bool> Debug;
cm::optional<bool> OutputOnFailure;
cm::optional<bool> Quiet;
std::string OutputLogFile;
cm::optional<bool> LabelSummary;
cm::optional<bool> SubprojectSummary;
cm::optional<int> MaxPassedTestOutputSize;
cm::optional<int> MaxFailedTestOutputSize;
cm::optional<int> MaxTestNameWidth;
};
struct IncludeOptions
{
struct IndexOptions
{
cm::optional<int> Start;
cm::optional<int> End;
cm::optional<int> Stride;
std::vector<int> SpecificTests;
std::string IndexFile;
};
std::string Name;
std::string Label;
cm::optional<IndexOptions> Index;
cm::optional<bool> UseUnion;
};
struct ExcludeOptions
{
struct FixturesOptions
{
std::string Any;
std::string Setup;
std::string Cleanup;
};
std::string Name;
std::string Label;
cm::optional<FixturesOptions> Fixtures;
};
struct FilterOptions
{
cm::optional<IncludeOptions> Include;
cm::optional<ExcludeOptions> Exclude;
};
struct ExecutionOptions
{
enum class ShowOnlyEnum
{
Human,
JsonV1
};
struct RepeatOptions
{
enum class ModeEnum
{
UntilFail,
UntilPass,
AfterTimeout
};
ModeEnum Mode;
int Count;
};
enum class NoTestsActionEnum
{
Default,
Error,
Ignore
};
cm::optional<bool> StopOnFailure;
cm::optional<bool> EnableFailover;
cm::optional<int> Jobs;
std::string ResourceSpecFile;
cm::optional<int> TestLoad;
cm::optional<ShowOnlyEnum> ShowOnly;
cm::optional<RepeatOptions> Repeat;
cm::optional<bool> InteractiveDebugging;
cm::optional<bool> ScheduleRandom;
cm::optional<int> Timeout;
cm::optional<NoTestsActionEnum> NoTestsAction;
};
std::string ConfigurePreset;
cm::optional<bool> InheritConfigureEnvironment;
std::string Configuration;
std::vector<std::string> OverwriteConfigurationFile;
cm::optional<OutputOptions> Output;
cm::optional<FilterOptions> Filter;
cm::optional<ExecutionOptions> Execution;
ReadFileResult VisitPresetInherit(const Preset& parent) override;
ReadFileResult VisitPresetAfterInherit(int /* version */) override;
};
template <class T>
class PresetPair
{
public:
T Unexpanded;
cm::optional<T> Expanded;
};
std::map<std::string, PresetPair<ConfigurePreset>> ConfigurePresets;
std::map<std::string, PresetPair<BuildPreset>> BuildPresets;
std::map<std::string, PresetPair<TestPreset>> TestPresets;
std::vector<std::string> ConfigurePresetOrder;
std::vector<std::string> BuildPresetOrder;
std::vector<std::string> TestPresetOrder;
std::string SourceDir;
int Version;
int UserVersion;
int GetVersion(const Preset& preset) const
{
return preset.User ? this->UserVersion : this->Version;
}
static std::string GetFilename(const std::string& sourceDir);
static std::string GetUserFilename(const std::string& sourceDir);
ReadFileResult ReadProjectPresets(const std::string& sourceDir,
bool allowNoFiles = false);
static const char* ResultToString(ReadFileResult result);
std::string GetGeneratorForPreset(const std::string& presetName) const
{
auto configurePresetName = presetName;
auto buildPresetIterator = this->BuildPresets.find(presetName);
if (buildPresetIterator != this->BuildPresets.end()) {
configurePresetName =
buildPresetIterator->second.Unexpanded.ConfigurePreset;
} else {
auto testPresetIterator = this->TestPresets.find(presetName);
if (testPresetIterator != this->TestPresets.end()) {
configurePresetName =
testPresetIterator->second.Unexpanded.ConfigurePreset;
}
}
auto configurePresetIterator =
this->ConfigurePresets.find(configurePresetName);
if (configurePresetIterator != this->ConfigurePresets.end()) {
return configurePresetIterator->second.Unexpanded.Generator;
}
// This should only happen if the preset is hidden
// or (for build or test presets) if ConfigurePreset is invalid.
return "";
}
static void PrintPresets(
const std::vector<const cmCMakePresetsFile::Preset*>& presets);
void PrintConfigurePresetList() const;
void PrintConfigurePresetList(
const std::function<bool(const ConfigurePreset&)>& filter) const;
void PrintBuildPresetList() const;
void PrintTestPresetList() const;
void PrintAllPresets() const;
private:
ReadFileResult ReadProjectPresetsInternal(bool allowNoFiles);
ReadFileResult ReadJSONFile(const std::string& filename, bool user);
void ClearPresets();
};