cmCMakePresetsGraph.cxx 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file LICENSE.rst or https://cmake.org/licensing for details. */
  3. #include "cmCMakePresetsGraph.h"
  4. #include <algorithm>
  5. #include <cassert>
  6. #include <cstddef>
  7. #include <functional>
  8. #include <iostream>
  9. #include <iterator>
  10. #include <utility>
  11. #include <cm/memory>
  12. #include "cmsys/RegularExpression.hxx"
  13. #include "cmCMakePresetsErrors.h"
  14. #include "cmCMakePresetsGraphInternal.h"
  15. #include "cmStringAlgorithms.h"
  16. #include "cmSystemTools.h"
  17. #define CHECK_EXPAND(out, field, expanders, version) \
  18. do { \
  19. switch (ExpandMacros(field, expanders, version)) { \
  20. case ExpandMacroResult::Error: \
  21. return false; \
  22. case ExpandMacroResult::Ignore: \
  23. out.reset(); \
  24. return true; \
  25. case ExpandMacroResult::Ok: \
  26. break; \
  27. } \
  28. } while (false)
  29. namespace {
  30. enum class CycleStatus
  31. {
  32. Unvisited,
  33. InProgress,
  34. Verified,
  35. };
  36. using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
  37. using BuildPreset = cmCMakePresetsGraph::BuildPreset;
  38. using TestPreset = cmCMakePresetsGraph::TestPreset;
  39. using PackagePreset = cmCMakePresetsGraph::PackagePreset;
  40. using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset;
  41. template <typename T>
  42. using PresetPair = cmCMakePresetsGraph::PresetPair<T>;
  43. using ExpandMacroResult = cmCMakePresetsGraphInternal::ExpandMacroResult;
  44. using MacroExpander = cmCMakePresetsGraphInternal::MacroExpander;
  45. using MacroExpanderVector = cmCMakePresetsGraphInternal::MacroExpanderVector;
  46. using BaseMacroExpander = cmCMakePresetsGraphInternal::BaseMacroExpander;
  47. template <typename T>
  48. using PresetMacroExpander =
  49. cmCMakePresetsGraphInternal::PresetMacroExpander<T>;
  50. using cmCMakePresetsGraphInternal::ExpandMacros;
  51. void InheritString(std::string& child, std::string const& parent)
  52. {
  53. if (child.empty()) {
  54. child = parent;
  55. }
  56. }
  57. template <typename T>
  58. void InheritOptionalValue(cm::optional<T>& child,
  59. cm::optional<T> const& parent)
  60. {
  61. if (!child) {
  62. child = parent;
  63. }
  64. }
  65. template <typename T>
  66. void InheritVector(std::vector<T>& child, std::vector<T> const& parent)
  67. {
  68. if (child.empty()) {
  69. child = parent;
  70. }
  71. }
  72. /**
  73. * Check preset inheritance for cycles (using a DAG check algorithm) while
  74. * also bubbling up fields through the inheritance hierarchy, then verify
  75. * that each preset has the required fields, either directly or through
  76. * inheritance.
  77. */
  78. template <class T>
  79. bool VisitPreset(
  80. T& preset,
  81. std::map<std::string, cmCMakePresetsGraph::PresetPair<T>>& presets,
  82. std::map<std::string, CycleStatus> cycleStatus, cmCMakePresetsGraph& graph)
  83. {
  84. switch (cycleStatus[preset.Name]) {
  85. case CycleStatus::InProgress:
  86. cmCMakePresetsErrors::CYCLIC_PRESET_INHERITANCE(preset.Name,
  87. &graph.parseState);
  88. return false;
  89. case CycleStatus::Verified:
  90. return true;
  91. default:
  92. break;
  93. }
  94. cycleStatus[preset.Name] = CycleStatus::InProgress;
  95. if (preset.Environment.count("") != 0) {
  96. cmCMakePresetsErrors::INVALID_PRESET_NAMED(preset.Name, &graph.parseState);
  97. return false;
  98. }
  99. bool result = preset.VisitPresetBeforeInherit();
  100. if (!result) {
  101. cmCMakePresetsErrors::INVALID_PRESET_NAMED(preset.Name, &graph.parseState);
  102. return false;
  103. }
  104. for (auto const& i : preset.Inherits) {
  105. auto parent = presets.find(i);
  106. if (parent == presets.end()) {
  107. cmCMakePresetsErrors::INVALID_PRESET_NAMED(preset.Name,
  108. &graph.parseState);
  109. return false;
  110. }
  111. auto& parentPreset = parent->second.Unexpanded;
  112. if (!preset.OriginFile->ReachableFiles.count(parentPreset.OriginFile)) {
  113. cmCMakePresetsErrors::INHERITED_PRESET_UNREACHABLE_FROM_FILE(
  114. preset.Name, &graph.parseState);
  115. return false;
  116. }
  117. if (!VisitPreset(parentPreset, presets, cycleStatus, graph)) {
  118. return false;
  119. }
  120. result = preset.VisitPresetInherit(parentPreset);
  121. if (!result) {
  122. cmCMakePresetsErrors::INVALID_PRESET_NAMED(preset.Name,
  123. &graph.parseState);
  124. return false;
  125. }
  126. for (auto const& v : parentPreset.Environment) {
  127. preset.Environment.insert(v);
  128. }
  129. if (!preset.ConditionEvaluator) {
  130. preset.ConditionEvaluator = parentPreset.ConditionEvaluator;
  131. }
  132. }
  133. if (preset.ConditionEvaluator && preset.ConditionEvaluator->IsNull()) {
  134. preset.ConditionEvaluator.reset();
  135. }
  136. result = preset.VisitPresetAfterInherit(graph.GetVersion(preset),
  137. &graph.parseState);
  138. if (!result) {
  139. cmCMakePresetsErrors::INVALID_PRESET_NAMED(preset.Name, &graph.parseState);
  140. return false;
  141. }
  142. cycleStatus[preset.Name] = CycleStatus::Verified;
  143. return true;
  144. }
  145. template <class T>
  146. bool ComputePresetInheritance(
  147. std::map<std::string, cmCMakePresetsGraph::PresetPair<T>>& presets,
  148. cmCMakePresetsGraph& graph)
  149. {
  150. std::map<std::string, CycleStatus> cycleStatus;
  151. for (auto const& it : presets) {
  152. cycleStatus[it.first] = CycleStatus::Unvisited;
  153. }
  154. for (auto& it : presets) {
  155. auto& preset = it.second.Unexpanded;
  156. if (!VisitPreset<T>(preset, presets, cycleStatus, graph)) {
  157. return false;
  158. }
  159. }
  160. return true;
  161. }
  162. constexpr char const* ValidPrefixes[] = {
  163. "",
  164. "env",
  165. "penv",
  166. "vendor",
  167. };
  168. bool PrefixesValidMacroNamespace(std::string const& str)
  169. {
  170. return std::any_of(
  171. std::begin(ValidPrefixes), std::end(ValidPrefixes),
  172. [&str](char const* prefix) -> bool { return cmHasPrefix(prefix, str); });
  173. }
  174. bool IsValidMacroNamespace(std::string const& str)
  175. {
  176. return std::any_of(
  177. std::begin(ValidPrefixes), std::end(ValidPrefixes),
  178. [&str](char const* prefix) -> bool { return str == prefix; });
  179. }
  180. ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
  181. MacroExpanderVector const& macroExpanders,
  182. int version);
  183. template <class T>
  184. class EnvironmentMacroExpander : public MacroExpander
  185. {
  186. std::map<std::string, CycleStatus>& EnvCycles;
  187. cm::optional<T>& Out;
  188. MacroExpanderVector& MacroExpanders;
  189. public:
  190. EnvironmentMacroExpander(MacroExpanderVector& macroExpanders,
  191. cm::optional<T>& out,
  192. std::map<std::string, CycleStatus>& envCycles)
  193. : EnvCycles(envCycles)
  194. , Out(out)
  195. , MacroExpanders(macroExpanders)
  196. {
  197. }
  198. ExpandMacroResult operator()(std::string const& macroNamespace,
  199. std::string const& macroName,
  200. std::string& macroOut,
  201. int version) const override
  202. {
  203. if (macroNamespace == "env" && !macroName.empty() && Out) {
  204. auto v = Out->Environment.find(macroName);
  205. if (v != Out->Environment.end() && v->second) {
  206. auto e =
  207. VisitEnv(*v->second, EnvCycles[macroName], MacroExpanders, version);
  208. if (e != ExpandMacroResult::Ok) {
  209. return e;
  210. }
  211. macroOut += *v->second;
  212. return ExpandMacroResult::Ok;
  213. }
  214. }
  215. if (macroNamespace == "env" || macroNamespace == "penv") {
  216. if (macroName.empty()) {
  217. return ExpandMacroResult::Error;
  218. }
  219. if (cm::optional<std::string> value =
  220. cmSystemTools::GetEnvVar(macroName)) {
  221. macroOut += *value;
  222. }
  223. return ExpandMacroResult::Ok;
  224. }
  225. return ExpandMacroResult::Ignore;
  226. }
  227. };
  228. bool ExpandMacros(cmCMakePresetsGraph const& graph,
  229. ConfigurePreset const& preset,
  230. cm::optional<ConfigurePreset>& out,
  231. MacroExpanderVector const& macroExpanders)
  232. {
  233. std::string binaryDir = preset.BinaryDir;
  234. CHECK_EXPAND(out, binaryDir, macroExpanders, graph.GetVersion(preset));
  235. if (!binaryDir.empty()) {
  236. if (!cmSystemTools::FileIsFullPath(binaryDir)) {
  237. binaryDir = cmStrCat(graph.SourceDir, '/', binaryDir);
  238. }
  239. out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir);
  240. cmSystemTools::ConvertToUnixSlashes(out->BinaryDir);
  241. }
  242. if (!preset.InstallDir.empty()) {
  243. std::string installDir = preset.InstallDir;
  244. CHECK_EXPAND(out, installDir, macroExpanders, graph.GetVersion(preset));
  245. if (!cmSystemTools::FileIsFullPath(installDir)) {
  246. installDir = cmStrCat(graph.SourceDir, '/', installDir);
  247. }
  248. out->InstallDir = cmSystemTools::CollapseFullPath(installDir);
  249. cmSystemTools::ConvertToUnixSlashes(out->InstallDir);
  250. }
  251. if (!preset.ToolchainFile.empty()) {
  252. std::string toolchain = preset.ToolchainFile;
  253. CHECK_EXPAND(out, toolchain, macroExpanders, graph.GetVersion(preset));
  254. out->ToolchainFile = toolchain;
  255. }
  256. if (!preset.GraphVizFile.empty()) {
  257. std::string graphVizFile = preset.GraphVizFile;
  258. CHECK_EXPAND(out, graphVizFile, macroExpanders, graph.GetVersion(preset));
  259. out->GraphVizFile = graphVizFile;
  260. }
  261. for (auto& variable : out->CacheVariables) {
  262. if (variable.second) {
  263. CHECK_EXPAND(out, variable.second->Value, macroExpanders,
  264. graph.GetVersion(preset));
  265. }
  266. }
  267. return true;
  268. }
  269. bool ExpandMacros(cmCMakePresetsGraph const& graph, BuildPreset const& preset,
  270. cm::optional<BuildPreset>& out,
  271. MacroExpanderVector const& macroExpanders)
  272. {
  273. for (auto& target : out->Targets) {
  274. CHECK_EXPAND(out, target, macroExpanders, graph.GetVersion(preset));
  275. }
  276. for (auto& nativeToolOption : out->NativeToolOptions) {
  277. CHECK_EXPAND(out, nativeToolOption, macroExpanders,
  278. graph.GetVersion(preset));
  279. }
  280. return true;
  281. }
  282. bool ExpandMacros(cmCMakePresetsGraph const& graph, TestPreset const& preset,
  283. cm::optional<TestPreset>& out,
  284. MacroExpanderVector const& macroExpanders)
  285. {
  286. for (auto& overwrite : out->OverwriteConfigurationFile) {
  287. CHECK_EXPAND(out, overwrite, macroExpanders, graph.GetVersion(preset));
  288. }
  289. if (out->Output) {
  290. CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders,
  291. graph.GetVersion(preset));
  292. CHECK_EXPAND(out, out->Output->OutputJUnitFile, macroExpanders,
  293. graph.GetVersion(preset));
  294. }
  295. if (out->Filter) {
  296. if (out->Filter->Include) {
  297. CHECK_EXPAND(out, out->Filter->Include->Name, macroExpanders,
  298. graph.GetVersion(preset));
  299. CHECK_EXPAND(out, out->Filter->Include->Label, macroExpanders,
  300. graph.GetVersion(preset));
  301. if (out->Filter->Include->Index) {
  302. CHECK_EXPAND(out, out->Filter->Include->Index->IndexFile,
  303. macroExpanders, graph.GetVersion(preset));
  304. }
  305. }
  306. if (out->Filter->Exclude) {
  307. CHECK_EXPAND(out, out->Filter->Exclude->Name, macroExpanders,
  308. graph.GetVersion(preset));
  309. CHECK_EXPAND(out, out->Filter->Exclude->Label, macroExpanders,
  310. graph.GetVersion(preset));
  311. if (out->Filter->Exclude->Fixtures) {
  312. CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Any, macroExpanders,
  313. graph.GetVersion(preset));
  314. CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Setup,
  315. macroExpanders, graph.GetVersion(preset));
  316. CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Cleanup,
  317. macroExpanders, graph.GetVersion(preset));
  318. }
  319. }
  320. }
  321. if (out->Execution) {
  322. CHECK_EXPAND(out, out->Execution->ResourceSpecFile, macroExpanders,
  323. graph.GetVersion(preset));
  324. }
  325. return true;
  326. }
  327. bool ExpandMacros(cmCMakePresetsGraph const& graph,
  328. PackagePreset const& preset,
  329. cm::optional<PackagePreset>& out,
  330. MacroExpanderVector const& macroExpanders)
  331. {
  332. for (auto& variable : out->Variables) {
  333. CHECK_EXPAND(out, variable.second, macroExpanders,
  334. graph.GetVersion(preset));
  335. }
  336. CHECK_EXPAND(out, out->ConfigFile, macroExpanders, graph.GetVersion(preset));
  337. CHECK_EXPAND(out, out->PackageName, macroExpanders,
  338. graph.GetVersion(preset));
  339. CHECK_EXPAND(out, out->PackageVersion, macroExpanders,
  340. graph.GetVersion(preset));
  341. CHECK_EXPAND(out, out->PackageDirectory, macroExpanders,
  342. graph.GetVersion(preset));
  343. CHECK_EXPAND(out, out->VendorName, macroExpanders, graph.GetVersion(preset));
  344. return true;
  345. }
  346. bool ExpandMacros(cmCMakePresetsGraph const& /*graph*/,
  347. WorkflowPreset const& /*preset*/,
  348. cm::optional<WorkflowPreset>& /*out*/,
  349. MacroExpanderVector const& /*macroExpanders*/)
  350. {
  351. return true;
  352. }
  353. template <class T>
  354. bool ExpandMacros(cmCMakePresetsGraph& graph, T const& preset,
  355. cm::optional<T>& out)
  356. {
  357. out.emplace(preset);
  358. std::map<std::string, CycleStatus> envCycles;
  359. for (auto const& v : out->Environment) {
  360. envCycles[v.first] = CycleStatus::Unvisited;
  361. }
  362. MacroExpanderVector macroExpanders{};
  363. macroExpanders.push_back(cm::make_unique<BaseMacroExpander>(graph));
  364. macroExpanders.push_back(
  365. cm::make_unique<PresetMacroExpander<T>>(graph, preset));
  366. macroExpanders.push_back(cm::make_unique<EnvironmentMacroExpander<T>>(
  367. macroExpanders, out, envCycles));
  368. for (auto& v : out->Environment) {
  369. if (v.second) {
  370. switch (VisitEnv(*v.second, envCycles[v.first], macroExpanders,
  371. graph.GetVersion(preset))) {
  372. case ExpandMacroResult::Error:
  373. cmCMakePresetsErrors::INVALID_PRESET_NAMED(preset.Name,
  374. &graph.parseState);
  375. return false;
  376. case ExpandMacroResult::Ignore:
  377. out.reset();
  378. return true;
  379. case ExpandMacroResult::Ok:
  380. break;
  381. }
  382. }
  383. }
  384. if (preset.ConditionEvaluator) {
  385. cm::optional<bool> result;
  386. if (!preset.ConditionEvaluator->Evaluate(
  387. macroExpanders, graph.GetVersion(preset), result)) {
  388. cmCMakePresetsErrors::INVALID_PRESET_NAMED(preset.Name,
  389. &graph.parseState);
  390. return false;
  391. }
  392. if (!result) {
  393. out.reset();
  394. return true;
  395. }
  396. out->ConditionResult = *result;
  397. }
  398. return ExpandMacros(graph, preset, out, macroExpanders);
  399. }
  400. ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
  401. MacroExpanderVector const& macroExpanders,
  402. int version)
  403. {
  404. if (status == CycleStatus::Verified) {
  405. return ExpandMacroResult::Ok;
  406. }
  407. if (status == CycleStatus::InProgress) {
  408. return ExpandMacroResult::Error;
  409. }
  410. status = CycleStatus::InProgress;
  411. auto e = ExpandMacros(value, macroExpanders, version);
  412. if (e != ExpandMacroResult::Ok) {
  413. return e;
  414. }
  415. status = CycleStatus::Verified;
  416. return ExpandMacroResult::Ok;
  417. }
  418. }
  419. ExpandMacroResult cmCMakePresetsGraphInternal::ExpandMacros(
  420. std::string& out, MacroExpanderVector const& macroExpanders, int version)
  421. {
  422. std::string result;
  423. std::string macroNamespace;
  424. std::string macroName;
  425. enum class State
  426. {
  427. Default,
  428. MacroNamespace,
  429. MacroName,
  430. } state = State::Default;
  431. for (auto c : out) {
  432. switch (state) {
  433. case State::Default:
  434. if (c == '$') {
  435. state = State::MacroNamespace;
  436. } else {
  437. result += c;
  438. }
  439. break;
  440. case State::MacroNamespace:
  441. if (c == '{') {
  442. if (IsValidMacroNamespace(macroNamespace)) {
  443. state = State::MacroName;
  444. } else {
  445. result += '$';
  446. result += macroNamespace;
  447. result += '{';
  448. macroNamespace.clear();
  449. state = State::Default;
  450. }
  451. } else {
  452. macroNamespace += c;
  453. if (!PrefixesValidMacroNamespace(macroNamespace)) {
  454. result += '$';
  455. result += macroNamespace;
  456. macroNamespace.clear();
  457. state = State::Default;
  458. }
  459. }
  460. break;
  461. case State::MacroName:
  462. if (c == '}') {
  463. auto e = ExpandMacro(result, macroNamespace, macroName,
  464. macroExpanders, version);
  465. if (e != ExpandMacroResult::Ok) {
  466. return e;
  467. }
  468. macroNamespace.clear();
  469. macroName.clear();
  470. state = State::Default;
  471. } else {
  472. macroName += c;
  473. }
  474. break;
  475. }
  476. }
  477. switch (state) {
  478. case State::Default:
  479. break;
  480. case State::MacroNamespace:
  481. result += '$';
  482. result += macroNamespace;
  483. break;
  484. case State::MacroName:
  485. return ExpandMacroResult::Error;
  486. }
  487. out = std::move(result);
  488. return ExpandMacroResult::Ok;
  489. }
  490. ExpandMacroResult cmCMakePresetsGraphInternal::ExpandMacro(
  491. std::string& out, std::string const& macroNamespace,
  492. std::string const& macroName, MacroExpanderVector const& macroExpanders,
  493. int version)
  494. {
  495. for (auto const& macroExpander : macroExpanders) {
  496. auto result = (*macroExpander)(macroNamespace, macroName, out, version);
  497. if (result != ExpandMacroResult::Ignore) {
  498. return result;
  499. }
  500. }
  501. if (macroNamespace == "vendor") {
  502. return ExpandMacroResult::Ignore;
  503. }
  504. return ExpandMacroResult::Error;
  505. }
  506. namespace {
  507. template <typename T>
  508. bool SetupWorkflowConfigurePreset(T const& preset,
  509. ConfigurePreset const*& configurePreset,
  510. cmJSONState* state)
  511. {
  512. if (preset.ConfigurePreset != configurePreset->Name) {
  513. cmCMakePresetsErrors::INVALID_WORKFLOW_STEPS(configurePreset->Name, state);
  514. return false;
  515. }
  516. return true;
  517. }
  518. template <>
  519. bool SetupWorkflowConfigurePreset<ConfigurePreset>(
  520. ConfigurePreset const& preset, ConfigurePreset const*& configurePreset,
  521. cmJSONState*)
  522. {
  523. configurePreset = &preset;
  524. return true;
  525. }
  526. template <typename T>
  527. bool TryReachPresetFromWorkflow(
  528. WorkflowPreset const& origin,
  529. std::map<std::string, PresetPair<T>> const& presets, std::string const& name,
  530. ConfigurePreset const*& configurePreset, cmJSONState* state)
  531. {
  532. auto it = presets.find(name);
  533. if (it == presets.end()) {
  534. cmCMakePresetsErrors::INVALID_WORKFLOW_STEPS(name, state);
  535. return false;
  536. }
  537. if (!origin.OriginFile->ReachableFiles.count(
  538. it->second.Unexpanded.OriginFile)) {
  539. cmCMakePresetsErrors::WORKFLOW_STEP_UNREACHABLE_FROM_FILE(name, state);
  540. return false;
  541. }
  542. return SetupWorkflowConfigurePreset<T>(it->second.Unexpanded,
  543. configurePreset, state);
  544. }
  545. }
  546. ExpandMacroResult BaseMacroExpander::operator()(
  547. std::string const& macroNamespace, std::string const& macroName,
  548. std::string& macroOut, int version) const
  549. {
  550. if (macroNamespace.empty()) {
  551. if (macroName == "sourceDir") {
  552. macroOut += Graph.SourceDir;
  553. return ExpandMacroResult::Ok;
  554. }
  555. if (macroName == "sourceParentDir") {
  556. macroOut += cmSystemTools::GetParentDirectory(Graph.SourceDir);
  557. return ExpandMacroResult::Ok;
  558. }
  559. if (macroName == "sourceDirName") {
  560. macroOut += cmSystemTools::GetFilenameName(Graph.SourceDir);
  561. return ExpandMacroResult::Ok;
  562. }
  563. if (macroName == "dollar") {
  564. macroOut += '$';
  565. return ExpandMacroResult::Ok;
  566. }
  567. if (macroName == "hostSystemName") {
  568. if (version < 3) {
  569. return ExpandMacroResult::Error;
  570. }
  571. macroOut += cmSystemTools::GetSystemName();
  572. return ExpandMacroResult::Ok;
  573. }
  574. // Enable fileDir macro expansion for non-preset expanders
  575. if (macroName == "fileDir" && File) {
  576. if (version < 4) {
  577. return ExpandMacroResult::Error;
  578. }
  579. macroOut += cmSystemTools::GetParentDirectory(File.value());
  580. return ExpandMacroResult::Ok;
  581. }
  582. if (macroName == "pathListSep") {
  583. if (version < 5) {
  584. return ExpandMacroResult::Error;
  585. }
  586. macroOut += cmSystemTools::GetSystemPathlistSeparator();
  587. return ExpandMacroResult::Ok;
  588. }
  589. }
  590. return ExpandMacroResult::Ignore;
  591. }
  592. bool cmCMakePresetsGraphInternal::EqualsCondition::Evaluate(
  593. MacroExpanderVector const& expanders, int version,
  594. cm::optional<bool>& out) const
  595. {
  596. std::string lhs = this->Lhs;
  597. CHECK_EXPAND(out, lhs, expanders, version);
  598. std::string rhs = this->Rhs;
  599. CHECK_EXPAND(out, rhs, expanders, version);
  600. out = (lhs == rhs);
  601. return true;
  602. }
  603. bool cmCMakePresetsGraphInternal::InListCondition::Evaluate(
  604. MacroExpanderVector const& expanders, int version,
  605. cm::optional<bool>& out) const
  606. {
  607. std::string str = this->String;
  608. CHECK_EXPAND(out, str, expanders, version);
  609. for (auto item : this->List) {
  610. CHECK_EXPAND(out, item, expanders, version);
  611. if (str == item) {
  612. out = true;
  613. return true;
  614. }
  615. }
  616. out = false;
  617. return true;
  618. }
  619. bool cmCMakePresetsGraphInternal::MatchesCondition::Evaluate(
  620. MacroExpanderVector const& expanders, int version,
  621. cm::optional<bool>& out) const
  622. {
  623. std::string str = this->String;
  624. CHECK_EXPAND(out, str, expanders, version);
  625. std::string regexStr = this->Regex;
  626. CHECK_EXPAND(out, regexStr, expanders, version);
  627. cmsys::RegularExpression regex;
  628. if (!regex.compile(regexStr)) {
  629. return false;
  630. }
  631. out = regex.find(str);
  632. return true;
  633. }
  634. bool cmCMakePresetsGraphInternal::AnyAllOfCondition::Evaluate(
  635. MacroExpanderVector const& expanders, int version,
  636. cm::optional<bool>& out) const
  637. {
  638. for (auto const& condition : this->Conditions) {
  639. cm::optional<bool> result;
  640. if (!condition->Evaluate(expanders, version, result)) {
  641. out.reset();
  642. return false;
  643. }
  644. if (!result) {
  645. out.reset();
  646. return true;
  647. }
  648. if (result == this->StopValue) {
  649. out = result;
  650. return true;
  651. }
  652. }
  653. out = !this->StopValue;
  654. return true;
  655. }
  656. bool cmCMakePresetsGraphInternal::NotCondition::Evaluate(
  657. MacroExpanderVector const& expanders, int version,
  658. cm::optional<bool>& out) const
  659. {
  660. out.reset();
  661. if (!this->SubCondition->Evaluate(expanders, version, out)) {
  662. out.reset();
  663. return false;
  664. }
  665. if (out) {
  666. *out = !*out;
  667. }
  668. return true;
  669. }
  670. bool cmCMakePresetsGraph::ConfigurePreset::VisitPresetInherit(
  671. cmCMakePresetsGraph::Preset const& parentPreset)
  672. {
  673. auto& preset = *this;
  674. ConfigurePreset const& parent =
  675. static_cast<ConfigurePreset const&>(parentPreset);
  676. InheritString(preset.Generator, parent.Generator);
  677. InheritString(preset.Architecture, parent.Architecture);
  678. InheritString(preset.Toolset, parent.Toolset);
  679. if (!preset.ArchitectureStrategy) {
  680. preset.ArchitectureStrategy = parent.ArchitectureStrategy;
  681. }
  682. if (!preset.ToolsetStrategy) {
  683. preset.ToolsetStrategy = parent.ToolsetStrategy;
  684. }
  685. InheritString(preset.BinaryDir, parent.BinaryDir);
  686. InheritString(preset.InstallDir, parent.InstallDir);
  687. InheritString(preset.ToolchainFile, parent.ToolchainFile);
  688. InheritString(preset.GraphVizFile, parent.GraphVizFile);
  689. InheritOptionalValue(preset.WarnDev, parent.WarnDev);
  690. InheritOptionalValue(preset.ErrorDev, parent.ErrorDev);
  691. InheritOptionalValue(preset.WarnDeprecated, parent.WarnDeprecated);
  692. InheritOptionalValue(preset.ErrorDeprecated, parent.ErrorDeprecated);
  693. InheritOptionalValue(preset.WarnUninitialized, parent.WarnUninitialized);
  694. InheritOptionalValue(preset.WarnUnusedCli, parent.WarnUnusedCli);
  695. InheritOptionalValue(preset.WarnSystemVars, parent.WarnSystemVars);
  696. for (auto const& v : parent.CacheVariables) {
  697. preset.CacheVariables.insert(v);
  698. }
  699. return true;
  700. }
  701. bool cmCMakePresetsGraph::ConfigurePreset::VisitPresetBeforeInherit()
  702. {
  703. auto& preset = *this;
  704. if (preset.Environment.count("") != 0) {
  705. return false;
  706. }
  707. return true;
  708. }
  709. bool cmCMakePresetsGraph::ConfigurePreset::VisitPresetAfterInherit(
  710. int version, cmJSONState* state)
  711. {
  712. auto& preset = *this;
  713. if (!preset.Hidden) {
  714. if (version < 3) {
  715. if (preset.Generator.empty()) {
  716. cmCMakePresetsErrors::PRESET_MISSING_FIELD(preset.Name, "generator",
  717. state);
  718. return false;
  719. }
  720. if (preset.BinaryDir.empty()) {
  721. cmCMakePresetsErrors::PRESET_MISSING_FIELD(preset.Name, "binaryDir",
  722. state);
  723. return false;
  724. }
  725. }
  726. if (preset.WarnDev == false && preset.ErrorDev == true) {
  727. return false;
  728. }
  729. if (preset.WarnDeprecated == false && preset.ErrorDeprecated == true) {
  730. return false;
  731. }
  732. if (preset.CacheVariables.count("") != 0) {
  733. return false;
  734. }
  735. }
  736. return true;
  737. }
  738. bool cmCMakePresetsGraph::BuildPreset::VisitPresetInherit(
  739. cmCMakePresetsGraph::Preset const& parentPreset)
  740. {
  741. auto& preset = *this;
  742. BuildPreset const& parent = static_cast<BuildPreset const&>(parentPreset);
  743. InheritString(preset.ConfigurePreset, parent.ConfigurePreset);
  744. InheritOptionalValue(preset.InheritConfigureEnvironment,
  745. parent.InheritConfigureEnvironment);
  746. InheritOptionalValue(preset.Jobs, parent.Jobs);
  747. InheritVector(preset.Targets, parent.Targets);
  748. InheritString(preset.Configuration, parent.Configuration);
  749. InheritOptionalValue(preset.CleanFirst, parent.CleanFirst);
  750. InheritOptionalValue(preset.Verbose, parent.Verbose);
  751. InheritVector(preset.NativeToolOptions, parent.NativeToolOptions);
  752. if (!preset.ResolvePackageReferences) {
  753. preset.ResolvePackageReferences = parent.ResolvePackageReferences;
  754. }
  755. return true;
  756. }
  757. bool cmCMakePresetsGraph::BuildPreset::VisitPresetAfterInherit(
  758. int /* version */, cmJSONState* /*stat*/)
  759. {
  760. auto& preset = *this;
  761. if (!preset.Hidden && preset.ConfigurePreset.empty()) {
  762. return false;
  763. }
  764. return true;
  765. }
  766. bool cmCMakePresetsGraph::TestPreset::VisitPresetInherit(
  767. cmCMakePresetsGraph::Preset const& parentPreset)
  768. {
  769. auto& preset = *this;
  770. TestPreset const& parent = static_cast<TestPreset const&>(parentPreset);
  771. InheritString(preset.ConfigurePreset, parent.ConfigurePreset);
  772. InheritOptionalValue(preset.InheritConfigureEnvironment,
  773. parent.InheritConfigureEnvironment);
  774. InheritString(preset.Configuration, parent.Configuration);
  775. InheritVector(preset.OverwriteConfigurationFile,
  776. parent.OverwriteConfigurationFile);
  777. if (parent.Output) {
  778. if (preset.Output) {
  779. auto& output = preset.Output.value();
  780. auto const& parentOutput = parent.Output.value();
  781. InheritOptionalValue(output.ShortProgress, parentOutput.ShortProgress);
  782. InheritOptionalValue(output.Verbosity, parentOutput.Verbosity);
  783. InheritOptionalValue(output.Debug, parentOutput.Debug);
  784. InheritOptionalValue(output.OutputOnFailure,
  785. parentOutput.OutputOnFailure);
  786. InheritOptionalValue(output.Quiet, parentOutput.Quiet);
  787. InheritString(output.OutputLogFile, parentOutput.OutputLogFile);
  788. InheritString(output.OutputJUnitFile, parentOutput.OutputJUnitFile);
  789. InheritOptionalValue(output.LabelSummary, parentOutput.LabelSummary);
  790. InheritOptionalValue(output.SubprojectSummary,
  791. parentOutput.SubprojectSummary);
  792. InheritOptionalValue(output.MaxPassedTestOutputSize,
  793. parentOutput.MaxPassedTestOutputSize);
  794. InheritOptionalValue(output.MaxFailedTestOutputSize,
  795. parentOutput.MaxFailedTestOutputSize);
  796. InheritOptionalValue(output.TestOutputTruncation,
  797. parentOutput.TestOutputTruncation);
  798. InheritOptionalValue(output.MaxTestNameWidth,
  799. parentOutput.MaxTestNameWidth);
  800. } else {
  801. preset.Output = parent.Output;
  802. }
  803. }
  804. if (parent.Filter) {
  805. if (parent.Filter->Include) {
  806. if (preset.Filter && preset.Filter->Include) {
  807. auto& include = *preset.Filter->Include;
  808. auto const& parentInclude = *parent.Filter->Include;
  809. InheritString(include.Name, parentInclude.Name);
  810. InheritString(include.Label, parentInclude.Label);
  811. InheritOptionalValue(include.Index, parentInclude.Index);
  812. } else {
  813. if (!preset.Filter) {
  814. preset.Filter.emplace();
  815. }
  816. preset.Filter->Include = parent.Filter->Include;
  817. }
  818. }
  819. if (parent.Filter->Exclude) {
  820. if (preset.Filter && preset.Filter->Exclude) {
  821. auto& exclude = *preset.Filter->Exclude;
  822. auto const& parentExclude = *parent.Filter->Exclude;
  823. InheritString(exclude.Name, parentExclude.Name);
  824. InheritString(exclude.Label, parentExclude.Label);
  825. InheritOptionalValue(exclude.Fixtures, parentExclude.Fixtures);
  826. } else {
  827. if (!preset.Filter) {
  828. preset.Filter.emplace();
  829. }
  830. preset.Filter->Exclude = parent.Filter->Exclude;
  831. }
  832. }
  833. }
  834. if (parent.Execution) {
  835. if (preset.Execution) {
  836. auto& execution = *preset.Execution;
  837. auto const& parentExecution = *parent.Execution;
  838. InheritOptionalValue(execution.StopOnFailure,
  839. parentExecution.StopOnFailure);
  840. InheritOptionalValue(execution.EnableFailover,
  841. parentExecution.EnableFailover);
  842. InheritOptionalValue(execution.Jobs, parentExecution.Jobs);
  843. InheritString(execution.ResourceSpecFile,
  844. parentExecution.ResourceSpecFile);
  845. InheritOptionalValue(execution.TestLoad, parentExecution.TestLoad);
  846. InheritOptionalValue(execution.ShowOnly, parentExecution.ShowOnly);
  847. InheritOptionalValue(execution.Repeat, parentExecution.Repeat);
  848. InheritOptionalValue(execution.InteractiveDebugging,
  849. parentExecution.InteractiveDebugging);
  850. InheritOptionalValue(execution.ScheduleRandom,
  851. parentExecution.ScheduleRandom);
  852. InheritOptionalValue(execution.Timeout, parentExecution.Timeout);
  853. InheritOptionalValue(execution.NoTestsAction,
  854. parentExecution.NoTestsAction);
  855. } else {
  856. preset.Execution = parent.Execution;
  857. }
  858. }
  859. return true;
  860. }
  861. bool cmCMakePresetsGraph::TestPreset::VisitPresetAfterInherit(
  862. int /* version */, cmJSONState* /*state*/)
  863. {
  864. auto& preset = *this;
  865. if (!preset.Hidden && preset.ConfigurePreset.empty()) {
  866. return false;
  867. }
  868. return true;
  869. }
  870. bool cmCMakePresetsGraph::PackagePreset::VisitPresetInherit(
  871. cmCMakePresetsGraph::Preset const& parentPreset)
  872. {
  873. auto& preset = *this;
  874. PackagePreset const& parent =
  875. static_cast<PackagePreset const&>(parentPreset);
  876. InheritString(preset.ConfigurePreset, parent.ConfigurePreset);
  877. InheritOptionalValue(preset.InheritConfigureEnvironment,
  878. parent.InheritConfigureEnvironment);
  879. InheritVector(preset.Generators, parent.Generators);
  880. InheritVector(preset.Configurations, parent.Configurations);
  881. for (auto const& v : parent.Variables) {
  882. preset.Variables.insert(v);
  883. }
  884. InheritOptionalValue(preset.DebugOutput, parent.DebugOutput);
  885. InheritOptionalValue(preset.VerboseOutput, parent.VerboseOutput);
  886. InheritString(preset.PackageName, parent.PackageName);
  887. InheritString(preset.PackageVersion, parent.PackageVersion);
  888. InheritString(preset.PackageDirectory, parent.PackageDirectory);
  889. InheritString(preset.VendorName, parent.VendorName);
  890. return true;
  891. }
  892. bool cmCMakePresetsGraph::PackagePreset::VisitPresetAfterInherit(
  893. int /* version */, cmJSONState* /*state*/)
  894. {
  895. auto& preset = *this;
  896. if (!preset.Hidden && preset.ConfigurePreset.empty()) {
  897. return false;
  898. }
  899. return true;
  900. }
  901. bool cmCMakePresetsGraph::WorkflowPreset::VisitPresetInherit(
  902. cmCMakePresetsGraph::Preset const& /*parentPreset*/)
  903. {
  904. return true;
  905. }
  906. bool cmCMakePresetsGraph::WorkflowPreset::VisitPresetAfterInherit(
  907. int /* version */, cmJSONState* /*state*/)
  908. {
  909. return true;
  910. }
  911. std::string cmCMakePresetsGraph::GetFilename(std::string const& sourceDir)
  912. {
  913. return cmStrCat(sourceDir, "/CMakePresets.json");
  914. }
  915. std::string cmCMakePresetsGraph::GetUserFilename(std::string const& sourceDir)
  916. {
  917. return cmStrCat(sourceDir, "/CMakeUserPresets.json");
  918. }
  919. bool cmCMakePresetsGraph::ReadProjectPresets(std::string const& sourceDir,
  920. bool allowNoFiles)
  921. {
  922. this->SourceDir = sourceDir;
  923. this->ClearPresets();
  924. if (!this->ReadProjectPresetsInternal(allowNoFiles)) {
  925. this->ClearPresets();
  926. return false;
  927. }
  928. return true;
  929. }
  930. bool cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
  931. {
  932. bool haveOneFile = false;
  933. File* file;
  934. std::string filename = GetUserFilename(this->SourceDir);
  935. std::vector<File*> inProgressFiles;
  936. if (cmSystemTools::FileExists(filename)) {
  937. if (!this->ReadJSONFile(filename, RootType::User, ReadReason::Root,
  938. inProgressFiles, file, this->errors)) {
  939. return false;
  940. }
  941. haveOneFile = true;
  942. } else {
  943. filename = GetFilename(this->SourceDir);
  944. if (cmSystemTools::FileExists(filename)) {
  945. if (!this->ReadJSONFile(filename, RootType::Project, ReadReason::Root,
  946. inProgressFiles, file, this->errors)) {
  947. return false;
  948. }
  949. haveOneFile = true;
  950. }
  951. }
  952. assert(inProgressFiles.empty());
  953. if (!haveOneFile) {
  954. if (allowNoFiles) {
  955. return true;
  956. }
  957. cmCMakePresetsErrors::FILE_NOT_FOUND(filename, &this->parseState);
  958. return false;
  959. }
  960. bool result = ComputePresetInheritance(this->ConfigurePresets, *this) &&
  961. ComputePresetInheritance(this->BuildPresets, *this) &&
  962. ComputePresetInheritance(this->TestPresets, *this) &&
  963. ComputePresetInheritance(this->PackagePresets, *this) &&
  964. ComputePresetInheritance(this->WorkflowPresets, *this);
  965. if (!result) {
  966. return false;
  967. }
  968. for (auto& it : this->ConfigurePresets) {
  969. if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
  970. cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(it.first,
  971. &this->parseState);
  972. return false;
  973. }
  974. }
  975. for (auto& it : this->BuildPresets) {
  976. if (!it.second.Unexpanded.Hidden) {
  977. auto const configurePreset =
  978. this->ConfigurePresets.find(it.second.Unexpanded.ConfigurePreset);
  979. if (configurePreset == this->ConfigurePresets.end()) {
  980. cmCMakePresetsErrors::INVALID_CONFIGURE_PRESET(it.first,
  981. &this->parseState);
  982. return false;
  983. }
  984. if (!it.second.Unexpanded.OriginFile->ReachableFiles.count(
  985. configurePreset->second.Unexpanded.OriginFile)) {
  986. cmCMakePresetsErrors::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE(
  987. it.first, &this->parseState);
  988. return false;
  989. }
  990. if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) {
  991. it.second.Unexpanded.Environment.insert(
  992. configurePreset->second.Unexpanded.Environment.begin(),
  993. configurePreset->second.Unexpanded.Environment.end());
  994. }
  995. }
  996. if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
  997. cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(it.first,
  998. &this->parseState);
  999. return false;
  1000. }
  1001. }
  1002. for (auto& it : this->TestPresets) {
  1003. if (!it.second.Unexpanded.Hidden) {
  1004. auto const configurePreset =
  1005. this->ConfigurePresets.find(it.second.Unexpanded.ConfigurePreset);
  1006. if (configurePreset == this->ConfigurePresets.end()) {
  1007. cmCMakePresetsErrors::INVALID_CONFIGURE_PRESET(it.first,
  1008. &this->parseState);
  1009. return false;
  1010. }
  1011. if (!it.second.Unexpanded.OriginFile->ReachableFiles.count(
  1012. configurePreset->second.Unexpanded.OriginFile)) {
  1013. cmCMakePresetsErrors::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE(
  1014. it.first, &this->parseState);
  1015. return false;
  1016. }
  1017. if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) {
  1018. it.second.Unexpanded.Environment.insert(
  1019. configurePreset->second.Unexpanded.Environment.begin(),
  1020. configurePreset->second.Unexpanded.Environment.end());
  1021. }
  1022. }
  1023. if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
  1024. cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(it.first,
  1025. &this->parseState);
  1026. return false;
  1027. }
  1028. }
  1029. for (auto& it : this->PackagePresets) {
  1030. if (!it.second.Unexpanded.Hidden) {
  1031. auto const configurePreset =
  1032. this->ConfigurePresets.find(it.second.Unexpanded.ConfigurePreset);
  1033. if (configurePreset == this->ConfigurePresets.end()) {
  1034. cmCMakePresetsErrors::INVALID_CONFIGURE_PRESET(it.first,
  1035. &this->parseState);
  1036. return false;
  1037. }
  1038. if (!it.second.Unexpanded.OriginFile->ReachableFiles.count(
  1039. configurePreset->second.Unexpanded.OriginFile)) {
  1040. cmCMakePresetsErrors::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE(
  1041. it.first, &this->parseState);
  1042. return false;
  1043. }
  1044. if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) {
  1045. it.second.Unexpanded.Environment.insert(
  1046. configurePreset->second.Unexpanded.Environment.begin(),
  1047. configurePreset->second.Unexpanded.Environment.end());
  1048. }
  1049. }
  1050. if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
  1051. cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(it.first,
  1052. &this->parseState);
  1053. return false;
  1054. }
  1055. }
  1056. for (auto& it : this->WorkflowPresets) {
  1057. using Type = WorkflowPreset::WorkflowStep::Type;
  1058. ConfigurePreset const* configurePreset = nullptr;
  1059. for (auto const& step : it.second.Unexpanded.Steps) {
  1060. if (!configurePreset && step.PresetType != Type::Configure) {
  1061. cmCMakePresetsErrors::FIRST_WORKFLOW_STEP_NOT_CONFIGURE(
  1062. step.PresetName, &this->parseState);
  1063. return false;
  1064. }
  1065. if (configurePreset && step.PresetType == Type::Configure) {
  1066. cmCMakePresetsErrors::CONFIGURE_WORKFLOW_STEP_NOT_FIRST(
  1067. step.PresetName, &this->parseState);
  1068. return false;
  1069. }
  1070. switch (step.PresetType) {
  1071. case Type::Configure:
  1072. result = TryReachPresetFromWorkflow(
  1073. it.second.Unexpanded, this->ConfigurePresets, step.PresetName,
  1074. configurePreset, &this->parseState);
  1075. break;
  1076. case Type::Build:
  1077. result = TryReachPresetFromWorkflow(
  1078. it.second.Unexpanded, this->BuildPresets, step.PresetName,
  1079. configurePreset, &this->parseState);
  1080. break;
  1081. case Type::Test:
  1082. result = TryReachPresetFromWorkflow(
  1083. it.second.Unexpanded, this->TestPresets, step.PresetName,
  1084. configurePreset, &this->parseState);
  1085. break;
  1086. case Type::Package:
  1087. result = TryReachPresetFromWorkflow(
  1088. it.second.Unexpanded, this->PackagePresets, step.PresetName,
  1089. configurePreset, &this->parseState);
  1090. break;
  1091. }
  1092. if (!result) {
  1093. return false;
  1094. }
  1095. }
  1096. if (!configurePreset) {
  1097. cmCMakePresetsErrors::NO_WORKFLOW_STEPS(it.first, &this->parseState);
  1098. return false;
  1099. }
  1100. if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
  1101. cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(it.first,
  1102. &this->parseState);
  1103. return false;
  1104. }
  1105. }
  1106. return true;
  1107. }
  1108. void cmCMakePresetsGraph::ClearPresets()
  1109. {
  1110. this->ConfigurePresets.clear();
  1111. this->BuildPresets.clear();
  1112. this->TestPresets.clear();
  1113. this->PackagePresets.clear();
  1114. this->WorkflowPresets.clear();
  1115. this->ConfigurePresetOrder.clear();
  1116. this->BuildPresetOrder.clear();
  1117. this->TestPresetOrder.clear();
  1118. this->PackagePresetOrder.clear();
  1119. this->WorkflowPresetOrder.clear();
  1120. this->Files.clear();
  1121. }
  1122. void cmCMakePresetsGraph::printPrecedingNewline(PrintPrecedingNewline* newline)
  1123. {
  1124. if (newline) {
  1125. if (*newline == PrintPrecedingNewline::True) {
  1126. std::cout << std::endl;
  1127. }
  1128. *newline = PrintPrecedingNewline::True;
  1129. }
  1130. }
  1131. void cmCMakePresetsGraph::PrintPresets(
  1132. std::vector<cmCMakePresetsGraph::Preset const*> const& presets)
  1133. {
  1134. if (presets.empty()) {
  1135. return;
  1136. }
  1137. auto longestPresetName =
  1138. std::max_element(presets.begin(), presets.end(),
  1139. [](cmCMakePresetsGraph::Preset const* a,
  1140. cmCMakePresetsGraph::Preset const* b) {
  1141. return a->Name.length() < b->Name.length();
  1142. });
  1143. auto longestLength = (*longestPresetName)->Name.length();
  1144. for (auto const* preset : presets) {
  1145. std::cout << " \"" << preset->Name << '"';
  1146. auto const& description = preset->DisplayName;
  1147. if (!description.empty()) {
  1148. for (std::size_t i = 0; i < longestLength - preset->Name.length(); ++i) {
  1149. std::cout << ' ';
  1150. }
  1151. std::cout << " - " << description;
  1152. }
  1153. std::cout << '\n';
  1154. }
  1155. }
  1156. void cmCMakePresetsGraph::PrintConfigurePresetList(
  1157. PrintPrecedingNewline* newline) const
  1158. {
  1159. PrintConfigurePresetList([](ConfigurePreset const&) { return true; },
  1160. newline);
  1161. }
  1162. void cmCMakePresetsGraph::PrintConfigurePresetList(
  1163. std::function<bool(ConfigurePreset const&)> const& filter,
  1164. PrintPrecedingNewline* newline) const
  1165. {
  1166. std::vector<cmCMakePresetsGraph::Preset const*> presets;
  1167. for (auto const& p : this->ConfigurePresetOrder) {
  1168. auto const& preset = this->ConfigurePresets.at(p);
  1169. if (!preset.Unexpanded.Hidden && preset.Expanded &&
  1170. preset.Expanded->ConditionResult && filter(preset.Unexpanded)) {
  1171. presets.push_back(
  1172. static_cast<cmCMakePresetsGraph::Preset const*>(&preset.Unexpanded));
  1173. }
  1174. }
  1175. if (!presets.empty()) {
  1176. printPrecedingNewline(newline);
  1177. std::cout << "Available configure presets:\n\n";
  1178. cmCMakePresetsGraph::PrintPresets(presets);
  1179. }
  1180. }
  1181. void cmCMakePresetsGraph::PrintBuildPresetList(
  1182. PrintPrecedingNewline* newline) const
  1183. {
  1184. std::vector<cmCMakePresetsGraph::Preset const*> presets;
  1185. for (auto const& p : this->BuildPresetOrder) {
  1186. auto const& preset = this->BuildPresets.at(p);
  1187. if (!preset.Unexpanded.Hidden && preset.Expanded &&
  1188. preset.Expanded->ConditionResult) {
  1189. presets.push_back(
  1190. static_cast<cmCMakePresetsGraph::Preset const*>(&preset.Unexpanded));
  1191. }
  1192. }
  1193. if (!presets.empty()) {
  1194. printPrecedingNewline(newline);
  1195. std::cout << "Available build presets:\n\n";
  1196. cmCMakePresetsGraph::PrintPresets(presets);
  1197. }
  1198. }
  1199. void cmCMakePresetsGraph::PrintTestPresetList(
  1200. PrintPrecedingNewline* newline) const
  1201. {
  1202. std::vector<cmCMakePresetsGraph::Preset const*> presets;
  1203. for (auto const& p : this->TestPresetOrder) {
  1204. auto const& preset = this->TestPresets.at(p);
  1205. if (!preset.Unexpanded.Hidden && preset.Expanded &&
  1206. preset.Expanded->ConditionResult) {
  1207. presets.push_back(
  1208. static_cast<cmCMakePresetsGraph::Preset const*>(&preset.Unexpanded));
  1209. }
  1210. }
  1211. if (!presets.empty()) {
  1212. printPrecedingNewline(newline);
  1213. std::cout << "Available test presets:\n\n";
  1214. cmCMakePresetsGraph::PrintPresets(presets);
  1215. }
  1216. }
  1217. void cmCMakePresetsGraph::PrintPackagePresetList(
  1218. PrintPrecedingNewline* newline) const
  1219. {
  1220. this->PrintPackagePresetList([](PackagePreset const&) { return true; },
  1221. newline);
  1222. }
  1223. void cmCMakePresetsGraph::PrintPackagePresetList(
  1224. std::function<bool(PackagePreset const&)> const& filter,
  1225. PrintPrecedingNewline* newline) const
  1226. {
  1227. std::vector<cmCMakePresetsGraph::Preset const*> presets;
  1228. for (auto const& p : this->PackagePresetOrder) {
  1229. auto const& preset = this->PackagePresets.at(p);
  1230. if (!preset.Unexpanded.Hidden && preset.Expanded &&
  1231. preset.Expanded->ConditionResult && filter(preset.Unexpanded)) {
  1232. presets.push_back(
  1233. static_cast<cmCMakePresetsGraph::Preset const*>(&preset.Unexpanded));
  1234. }
  1235. }
  1236. if (!presets.empty()) {
  1237. printPrecedingNewline(newline);
  1238. std::cout << "Available package presets:\n\n";
  1239. cmCMakePresetsGraph::PrintPresets(presets);
  1240. }
  1241. }
  1242. void cmCMakePresetsGraph::PrintWorkflowPresetList(
  1243. PrintPrecedingNewline* newline) const
  1244. {
  1245. std::vector<cmCMakePresetsGraph::Preset const*> presets;
  1246. for (auto const& p : this->WorkflowPresetOrder) {
  1247. auto const& preset = this->WorkflowPresets.at(p);
  1248. if (!preset.Unexpanded.Hidden && preset.Expanded &&
  1249. preset.Expanded->ConditionResult) {
  1250. presets.push_back(
  1251. static_cast<cmCMakePresetsGraph::Preset const*>(&preset.Unexpanded));
  1252. }
  1253. }
  1254. if (!presets.empty()) {
  1255. printPrecedingNewline(newline);
  1256. std::cout << "Available workflow presets:\n\n";
  1257. cmCMakePresetsGraph::PrintPresets(presets);
  1258. }
  1259. }
  1260. void cmCMakePresetsGraph::PrintAllPresets() const
  1261. {
  1262. PrintPrecedingNewline newline = PrintPrecedingNewline::False;
  1263. this->PrintConfigurePresetList(&newline);
  1264. this->PrintBuildPresetList(&newline);
  1265. this->PrintTestPresetList(&newline);
  1266. this->PrintPackagePresetList(&newline);
  1267. this->PrintWorkflowPresetList(&newline);
  1268. }