1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2 file Copyright.txt or https://cmake.org/licensing for details. */ 3 #pragma once 4 5 #include "cmConfigure.h" // IWYU pragma: keep 6 7 #include <functional> 8 #include <map> 9 #include <memory> 10 #include <string> 11 #include <utility> 12 #include <vector> 13 14 #include <cm/optional> 15 16 class cmCMakePresetsFile 17 { 18 public: 19 enum class ReadFileResult 20 { 21 READ_OK, 22 FILE_NOT_FOUND, 23 JSON_PARSE_ERROR, 24 INVALID_ROOT, 25 NO_VERSION, 26 INVALID_VERSION, 27 UNRECOGNIZED_VERSION, 28 INVALID_CMAKE_VERSION, 29 UNRECOGNIZED_CMAKE_VERSION, 30 INVALID_PRESETS, 31 INVALID_PRESET, 32 INVALID_VARIABLE, 33 DUPLICATE_PRESETS, 34 CYCLIC_PRESET_INHERITANCE, 35 USER_PRESET_INHERITANCE, 36 INVALID_MACRO_EXPANSION, 37 BUILD_TEST_PRESETS_UNSUPPORTED, 38 INVALID_CONFIGURE_PRESET, 39 INSTALL_PREFIX_UNSUPPORTED, 40 INVALID_CONDITION, 41 CONDITION_UNSUPPORTED, 42 TOOLCHAIN_FILE_UNSUPPORTED, 43 }; 44 45 enum class ArchToolsetStrategy 46 { 47 Set, 48 External, 49 }; 50 51 class CacheVariable 52 { 53 public: 54 std::string Type; 55 std::string Value; 56 }; 57 58 class Condition; 59 60 class Preset 61 { 62 public: 63 #if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L) 64 // The move assignment operators for several STL classes did not become 65 // noexcept until C++17, which causes some tools to warn about this move 66 // assignment operator throwing an exception when it shouldn't. Disable the 67 // move assignment operator until C++17 is enabled. 68 // Explicitly defining a copy assignment operator prevents the compiler 69 // from automatically generating a move assignment operator. 70 Preset& operator=(const Preset& /*other*/) = default; 71 #endif 72 73 virtual ~Preset() = default; 74 75 std::string Name; 76 std::vector<std::string> Inherits; 77 bool Hidden; 78 bool User; 79 std::string DisplayName; 80 std::string Description; 81 82 std::shared_ptr<Condition> ConditionEvaluator; 83 bool ConditionResult = true; 84 85 std::map<std::string, cm::optional<std::string>> Environment; 86 87 virtual ReadFileResult VisitPresetInherit(const Preset& parent) = 0; VisitPresetBeforeInherit()88 virtual ReadFileResult VisitPresetBeforeInherit() 89 { 90 return ReadFileResult::READ_OK; 91 } 92 VisitPresetAfterInherit(int)93 virtual ReadFileResult VisitPresetAfterInherit(int /* version */) 94 { 95 return ReadFileResult::READ_OK; 96 } 97 }; 98 99 class ConfigurePreset : public Preset 100 { 101 public: 102 #if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L) 103 // The move assignment operators for several STL classes did not become 104 // noexcept until C++17, which causes some tools to warn about this move 105 // assignment operator throwing an exception when it shouldn't. Disable the 106 // move assignment operator until C++17 is enabled. 107 // Explicitly defining a copy assignment operator prevents the compiler 108 // from automatically generating a move assignment operator. 109 ConfigurePreset& operator=(const ConfigurePreset& /*other*/) = default; 110 #endif 111 112 std::string Generator; 113 std::string Architecture; 114 cm::optional<ArchToolsetStrategy> ArchitectureStrategy; 115 std::string Toolset; 116 cm::optional<ArchToolsetStrategy> ToolsetStrategy; 117 std::string ToolchainFile; 118 std::string BinaryDir; 119 std::string InstallDir; 120 121 std::map<std::string, cm::optional<CacheVariable>> CacheVariables; 122 123 cm::optional<bool> WarnDev; 124 cm::optional<bool> ErrorDev; 125 cm::optional<bool> WarnDeprecated; 126 cm::optional<bool> ErrorDeprecated; 127 cm::optional<bool> WarnUninitialized; 128 cm::optional<bool> WarnUnusedCli; 129 cm::optional<bool> WarnSystemVars; 130 131 cm::optional<bool> DebugOutput; 132 cm::optional<bool> DebugTryCompile; 133 cm::optional<bool> DebugFind; 134 135 ReadFileResult VisitPresetInherit(const Preset& parent) override; 136 ReadFileResult VisitPresetBeforeInherit() override; 137 ReadFileResult VisitPresetAfterInherit(int version) override; 138 }; 139 140 class BuildPreset : public Preset 141 { 142 public: 143 #if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L) 144 // The move assignment operators for several STL classes did not become 145 // noexcept until C++17, which causes some tools to warn about this move 146 // assignment operator throwing an exception when it shouldn't. Disable the 147 // move assignment operator until C++17 is enabled. 148 // Explicitly defining a copy assignment operator prevents the compiler 149 // from automatically generating a move assignment operator. 150 BuildPreset& operator=(const BuildPreset& /*other*/) = default; 151 #endif 152 153 std::string ConfigurePreset; 154 cm::optional<bool> InheritConfigureEnvironment; 155 cm::optional<int> Jobs; 156 std::vector<std::string> Targets; 157 std::string Configuration; 158 cm::optional<bool> CleanFirst; 159 cm::optional<bool> Verbose; 160 std::vector<std::string> NativeToolOptions; 161 162 ReadFileResult VisitPresetInherit(const Preset& parent) override; 163 ReadFileResult VisitPresetAfterInherit(int /* version */) override; 164 }; 165 166 class TestPreset : public Preset 167 { 168 public: 169 #if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L) 170 // The move assignment operators for several STL classes did not become 171 // noexcept until C++17, which causes some tools to warn about this move 172 // assignment operator throwing an exception when it shouldn't. Disable the 173 // move assignment operator until C++17 is enabled. 174 // Explicitly defining a copy assignment operator prevents the compiler 175 // from automatically generating a move assignment operator. 176 TestPreset& operator=(const TestPreset& /*other*/) = default; 177 #endif 178 179 struct OutputOptions 180 { 181 enum class VerbosityEnum 182 { 183 Default, 184 Verbose, 185 Extra 186 }; 187 188 cm::optional<bool> ShortProgress; 189 cm::optional<VerbosityEnum> Verbosity; 190 cm::optional<bool> Debug; 191 cm::optional<bool> OutputOnFailure; 192 cm::optional<bool> Quiet; 193 std::string OutputLogFile; 194 cm::optional<bool> LabelSummary; 195 cm::optional<bool> SubprojectSummary; 196 cm::optional<int> MaxPassedTestOutputSize; 197 cm::optional<int> MaxFailedTestOutputSize; 198 cm::optional<int> MaxTestNameWidth; 199 }; 200 201 struct IncludeOptions 202 { 203 struct IndexOptions 204 { 205 cm::optional<int> Start; 206 cm::optional<int> End; 207 cm::optional<int> Stride; 208 std::vector<int> SpecificTests; 209 210 std::string IndexFile; 211 }; 212 213 std::string Name; 214 std::string Label; 215 cm::optional<IndexOptions> Index; 216 cm::optional<bool> UseUnion; 217 }; 218 219 struct ExcludeOptions 220 { 221 struct FixturesOptions 222 { 223 std::string Any; 224 std::string Setup; 225 std::string Cleanup; 226 }; 227 228 std::string Name; 229 std::string Label; 230 cm::optional<FixturesOptions> Fixtures; 231 }; 232 233 struct FilterOptions 234 { 235 cm::optional<IncludeOptions> Include; 236 cm::optional<ExcludeOptions> Exclude; 237 }; 238 239 struct ExecutionOptions 240 { 241 enum class ShowOnlyEnum 242 { 243 Human, 244 JsonV1 245 }; 246 247 struct RepeatOptions 248 { 249 enum class ModeEnum 250 { 251 UntilFail, 252 UntilPass, 253 AfterTimeout 254 }; 255 256 ModeEnum Mode; 257 int Count; 258 }; 259 260 enum class NoTestsActionEnum 261 { 262 Default, 263 Error, 264 Ignore 265 }; 266 267 cm::optional<bool> StopOnFailure; 268 cm::optional<bool> EnableFailover; 269 cm::optional<int> Jobs; 270 std::string ResourceSpecFile; 271 cm::optional<int> TestLoad; 272 cm::optional<ShowOnlyEnum> ShowOnly; 273 274 cm::optional<RepeatOptions> Repeat; 275 cm::optional<bool> InteractiveDebugging; 276 cm::optional<bool> ScheduleRandom; 277 cm::optional<int> Timeout; 278 cm::optional<NoTestsActionEnum> NoTestsAction; 279 }; 280 281 std::string ConfigurePreset; 282 cm::optional<bool> InheritConfigureEnvironment; 283 std::string Configuration; 284 std::vector<std::string> OverwriteConfigurationFile; 285 cm::optional<OutputOptions> Output; 286 cm::optional<FilterOptions> Filter; 287 cm::optional<ExecutionOptions> Execution; 288 289 ReadFileResult VisitPresetInherit(const Preset& parent) override; 290 ReadFileResult VisitPresetAfterInherit(int /* version */) override; 291 }; 292 293 template <class T> 294 class PresetPair 295 { 296 public: 297 T Unexpanded; 298 cm::optional<T> Expanded; 299 }; 300 301 std::map<std::string, PresetPair<ConfigurePreset>> ConfigurePresets; 302 std::map<std::string, PresetPair<BuildPreset>> BuildPresets; 303 std::map<std::string, PresetPair<TestPreset>> TestPresets; 304 305 std::vector<std::string> ConfigurePresetOrder; 306 std::vector<std::string> BuildPresetOrder; 307 std::vector<std::string> TestPresetOrder; 308 309 std::string SourceDir; 310 int Version; 311 int UserVersion; 312 GetVersion(const Preset & preset)313 int GetVersion(const Preset& preset) const 314 { 315 return preset.User ? this->UserVersion : this->Version; 316 } 317 318 static std::string GetFilename(const std::string& sourceDir); 319 static std::string GetUserFilename(const std::string& sourceDir); 320 ReadFileResult ReadProjectPresets(const std::string& sourceDir, 321 bool allowNoFiles = false); 322 static const char* ResultToString(ReadFileResult result); 323 GetGeneratorForPreset(const std::string & presetName)324 std::string GetGeneratorForPreset(const std::string& presetName) const 325 { 326 auto configurePresetName = presetName; 327 328 auto buildPresetIterator = this->BuildPresets.find(presetName); 329 if (buildPresetIterator != this->BuildPresets.end()) { 330 configurePresetName = 331 buildPresetIterator->second.Unexpanded.ConfigurePreset; 332 } else { 333 auto testPresetIterator = this->TestPresets.find(presetName); 334 if (testPresetIterator != this->TestPresets.end()) { 335 configurePresetName = 336 testPresetIterator->second.Unexpanded.ConfigurePreset; 337 } 338 } 339 340 auto configurePresetIterator = 341 this->ConfigurePresets.find(configurePresetName); 342 if (configurePresetIterator != this->ConfigurePresets.end()) { 343 return configurePresetIterator->second.Unexpanded.Generator; 344 } 345 346 // This should only happen if the preset is hidden 347 // or (for build or test presets) if ConfigurePreset is invalid. 348 return ""; 349 } 350 351 static void PrintPresets( 352 const std::vector<const cmCMakePresetsFile::Preset*>& presets); 353 void PrintConfigurePresetList() const; 354 void PrintConfigurePresetList( 355 const std::function<bool(const ConfigurePreset&)>& filter) const; 356 void PrintBuildPresetList() const; 357 void PrintTestPresetList() const; 358 void PrintAllPresets() const; 359 360 private: 361 ReadFileResult ReadProjectPresetsInternal(bool allowNoFiles); 362 ReadFileResult ReadJSONFile(const std::string& filename, bool user); 363 void ClearPresets(); 364 }; 365