cmCMakePresetsGraphReadJSON.cxx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include <algorithm>
  4. #include <functional>
  5. #include <map>
  6. #include <string>
  7. #include <unordered_set>
  8. #include <utility>
  9. #include <vector>
  10. #include <cm/memory>
  11. #include <cm/optional>
  12. #include <cmext/string_view>
  13. #include <cm3p/json/reader.h>
  14. #include <cm3p/json/value.h>
  15. #include "cmsys/FStream.hxx"
  16. #include "cmCMakePresetsGraph.h"
  17. #include "cmCMakePresetsGraphInternal.h"
  18. #include "cmJSONHelpers.h"
  19. #include "cmStringAlgorithms.h"
  20. #include "cmSystemTools.h"
  21. #include "cmVersion.h"
  22. namespace {
  23. using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
  24. using CacheVariable = cmCMakePresetsGraph::CacheVariable;
  25. using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
  26. using BuildPreset = cmCMakePresetsGraph::BuildPreset;
  27. using TestPreset = cmCMakePresetsGraph::TestPreset;
  28. using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy;
  29. constexpr int MIN_VERSION = 1;
  30. constexpr int MAX_VERSION = 5;
  31. struct CMakeVersion
  32. {
  33. unsigned int Major = 0;
  34. unsigned int Minor = 0;
  35. unsigned int Patch = 0;
  36. };
  37. struct RootPresets
  38. {
  39. CMakeVersion CMakeMinimumRequired;
  40. std::vector<cmCMakePresetsGraph::ConfigurePreset> ConfigurePresets;
  41. std::vector<cmCMakePresetsGraph::BuildPreset> BuildPresets;
  42. std::vector<cmCMakePresetsGraph::TestPreset> TestPresets;
  43. std::vector<std::string> Include;
  44. };
  45. std::unique_ptr<cmCMakePresetsGraphInternal::NotCondition> InvertCondition(
  46. std::unique_ptr<cmCMakePresetsGraph::Condition> condition)
  47. {
  48. auto retval = cm::make_unique<cmCMakePresetsGraphInternal::NotCondition>();
  49. retval->SubCondition = std::move(condition);
  50. return retval;
  51. }
  52. auto const ConditionStringHelper = cmJSONStringHelper<ReadFileResult>(
  53. ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION);
  54. auto const ConditionBoolHelper = cmJSONBoolHelper<ReadFileResult>(
  55. ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION);
  56. auto const ConditionStringListHelper =
  57. cmJSONVectorHelper<std::string, ReadFileResult>(
  58. ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION,
  59. ConditionStringHelper);
  60. auto const ConstConditionHelper =
  61. cmJSONObjectHelper<cmCMakePresetsGraphInternal::ConstCondition,
  62. ReadFileResult>(ReadFileResult::READ_OK,
  63. ReadFileResult::INVALID_CONDITION, false)
  64. .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
  65. .Bind("value"_s, &cmCMakePresetsGraphInternal::ConstCondition::Value,
  66. ConditionBoolHelper, true);
  67. auto const EqualsConditionHelper =
  68. cmJSONObjectHelper<cmCMakePresetsGraphInternal::EqualsCondition,
  69. ReadFileResult>(ReadFileResult::READ_OK,
  70. ReadFileResult::INVALID_CONDITION, false)
  71. .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
  72. .Bind("lhs"_s, &cmCMakePresetsGraphInternal::EqualsCondition::Lhs,
  73. ConditionStringHelper, true)
  74. .Bind("rhs"_s, &cmCMakePresetsGraphInternal::EqualsCondition::Rhs,
  75. ConditionStringHelper, true);
  76. auto const InListConditionHelper =
  77. cmJSONObjectHelper<cmCMakePresetsGraphInternal::InListCondition,
  78. ReadFileResult>(ReadFileResult::READ_OK,
  79. ReadFileResult::INVALID_CONDITION, false)
  80. .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
  81. .Bind("string"_s, &cmCMakePresetsGraphInternal::InListCondition::String,
  82. ConditionStringHelper, true)
  83. .Bind("list"_s, &cmCMakePresetsGraphInternal::InListCondition::List,
  84. ConditionStringListHelper, true);
  85. auto const MatchesConditionHelper =
  86. cmJSONObjectHelper<cmCMakePresetsGraphInternal::MatchesCondition,
  87. ReadFileResult>(ReadFileResult::READ_OK,
  88. ReadFileResult::INVALID_CONDITION, false)
  89. .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
  90. .Bind("string"_s, &cmCMakePresetsGraphInternal::MatchesCondition::String,
  91. ConditionStringHelper, true)
  92. .Bind("regex"_s, &cmCMakePresetsGraphInternal::MatchesCondition::Regex,
  93. ConditionStringHelper, true);
  94. ReadFileResult SubConditionHelper(
  95. std::unique_ptr<cmCMakePresetsGraph::Condition>& out,
  96. const Json::Value* value);
  97. auto const ListConditionVectorHelper =
  98. cmJSONVectorHelper<std::unique_ptr<cmCMakePresetsGraph::Condition>,
  99. ReadFileResult>(ReadFileResult::READ_OK,
  100. ReadFileResult::INVALID_CONDITION,
  101. SubConditionHelper);
  102. auto const AnyAllOfConditionHelper =
  103. cmJSONObjectHelper<cmCMakePresetsGraphInternal::AnyAllOfCondition,
  104. ReadFileResult>(ReadFileResult::READ_OK,
  105. ReadFileResult::INVALID_CONDITION, false)
  106. .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
  107. .Bind("conditions"_s,
  108. &cmCMakePresetsGraphInternal::AnyAllOfCondition::Conditions,
  109. ListConditionVectorHelper);
  110. auto const NotConditionHelper =
  111. cmJSONObjectHelper<cmCMakePresetsGraphInternal::NotCondition,
  112. ReadFileResult>(ReadFileResult::READ_OK,
  113. ReadFileResult::INVALID_CONDITION, false)
  114. .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
  115. .Bind("condition"_s,
  116. &cmCMakePresetsGraphInternal::NotCondition::SubCondition,
  117. SubConditionHelper);
  118. ReadFileResult ConditionHelper(
  119. std::unique_ptr<cmCMakePresetsGraph::Condition>& out,
  120. const Json::Value* value)
  121. {
  122. if (!value) {
  123. out.reset();
  124. return ReadFileResult::READ_OK;
  125. }
  126. if (value->isBool()) {
  127. auto c = cm::make_unique<cmCMakePresetsGraphInternal::ConstCondition>();
  128. c->Value = value->asBool();
  129. out = std::move(c);
  130. return ReadFileResult::READ_OK;
  131. }
  132. if (value->isNull()) {
  133. out = cm::make_unique<cmCMakePresetsGraphInternal::NullCondition>();
  134. return ReadFileResult::READ_OK;
  135. }
  136. if (value->isObject()) {
  137. if (!value->isMember("type")) {
  138. return ReadFileResult::INVALID_CONDITION;
  139. }
  140. if (!(*value)["type"].isString()) {
  141. return ReadFileResult::INVALID_CONDITION;
  142. }
  143. auto type = (*value)["type"].asString();
  144. if (type == "const") {
  145. auto c = cm::make_unique<cmCMakePresetsGraphInternal::ConstCondition>();
  146. CHECK_OK(ConstConditionHelper(*c, value));
  147. out = std::move(c);
  148. return ReadFileResult::READ_OK;
  149. }
  150. if (type == "equals" || type == "notEquals") {
  151. auto c = cm::make_unique<cmCMakePresetsGraphInternal::EqualsCondition>();
  152. CHECK_OK(EqualsConditionHelper(*c, value));
  153. out = std::move(c);
  154. if (type == "notEquals") {
  155. out = InvertCondition(std::move(out));
  156. }
  157. return ReadFileResult::READ_OK;
  158. }
  159. if (type == "inList" || type == "notInList") {
  160. auto c = cm::make_unique<cmCMakePresetsGraphInternal::InListCondition>();
  161. CHECK_OK(InListConditionHelper(*c, value));
  162. out = std::move(c);
  163. if (type == "notInList") {
  164. out = InvertCondition(std::move(out));
  165. }
  166. return ReadFileResult::READ_OK;
  167. }
  168. if (type == "matches" || type == "notMatches") {
  169. auto c =
  170. cm::make_unique<cmCMakePresetsGraphInternal::MatchesCondition>();
  171. CHECK_OK(MatchesConditionHelper(*c, value));
  172. out = std::move(c);
  173. if (type == "notMatches") {
  174. out = InvertCondition(std::move(out));
  175. }
  176. return ReadFileResult::READ_OK;
  177. }
  178. if (type == "anyOf" || type == "allOf") {
  179. auto c =
  180. cm::make_unique<cmCMakePresetsGraphInternal::AnyAllOfCondition>();
  181. c->StopValue = (type == "anyOf");
  182. CHECK_OK(AnyAllOfConditionHelper(*c, value));
  183. out = std::move(c);
  184. return ReadFileResult::READ_OK;
  185. }
  186. if (type == "not") {
  187. auto c = cm::make_unique<cmCMakePresetsGraphInternal::NotCondition>();
  188. CHECK_OK(NotConditionHelper(*c, value));
  189. out = std::move(c);
  190. return ReadFileResult::READ_OK;
  191. }
  192. }
  193. return ReadFileResult::INVALID_CONDITION;
  194. }
  195. ReadFileResult SubConditionHelper(
  196. std::unique_ptr<cmCMakePresetsGraph::Condition>& out,
  197. const Json::Value* value)
  198. {
  199. std::unique_ptr<cmCMakePresetsGraph::Condition> ptr;
  200. auto result = ConditionHelper(ptr, value);
  201. if (ptr && ptr->IsNull()) {
  202. return ReadFileResult::INVALID_CONDITION;
  203. }
  204. out = std::move(ptr);
  205. return result;
  206. }
  207. ReadFileResult EnvironmentHelper(cm::optional<std::string>& out,
  208. const Json::Value* value)
  209. {
  210. if (!value || value->isNull()) {
  211. out = cm::nullopt;
  212. return ReadFileResult::READ_OK;
  213. }
  214. if (value->isString()) {
  215. out = value->asString();
  216. return ReadFileResult::READ_OK;
  217. }
  218. return ReadFileResult::INVALID_PRESET;
  219. }
  220. auto const VersionIntHelper = cmJSONIntHelper<ReadFileResult>(
  221. ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
  222. auto const VersionHelper = cmJSONRequiredHelper<int, ReadFileResult>(
  223. ReadFileResult::NO_VERSION, VersionIntHelper);
  224. auto const RootVersionHelper =
  225. cmJSONObjectHelper<int, ReadFileResult>(ReadFileResult::READ_OK,
  226. ReadFileResult::INVALID_ROOT)
  227. .Bind("version"_s, VersionHelper, false);
  228. auto const CMakeVersionUIntHelper = cmJSONUIntHelper<ReadFileResult>(
  229. ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
  230. auto const CMakeVersionHelper =
  231. cmJSONObjectHelper<CMakeVersion, ReadFileResult>(
  232. ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false)
  233. .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false)
  234. .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false)
  235. .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false);
  236. auto const IncludeHelper = cmJSONStringHelper<ReadFileResult>(
  237. ReadFileResult::READ_OK, ReadFileResult::INVALID_INCLUDE);
  238. auto const IncludeVectorHelper =
  239. cmJSONVectorHelper<std::string, ReadFileResult>(
  240. ReadFileResult::READ_OK, ReadFileResult::INVALID_INCLUDE, IncludeHelper);
  241. auto const RootPresetsHelper =
  242. cmJSONObjectHelper<RootPresets, ReadFileResult>(
  243. ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false)
  244. .Bind<int>("version"_s, nullptr, VersionHelper)
  245. .Bind("configurePresets"_s, &RootPresets::ConfigurePresets,
  246. cmCMakePresetsGraphInternal::ConfigurePresetsHelper, false)
  247. .Bind("buildPresets"_s, &RootPresets::BuildPresets,
  248. cmCMakePresetsGraphInternal::BuildPresetsHelper, false)
  249. .Bind("testPresets"_s, &RootPresets::TestPresets,
  250. cmCMakePresetsGraphInternal::TestPresetsHelper, false)
  251. .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired,
  252. CMakeVersionHelper, false)
  253. .Bind("include"_s, &RootPresets::Include, IncludeVectorHelper, false)
  254. .Bind<std::nullptr_t>(
  255. "vendor"_s, nullptr,
  256. cmCMakePresetsGraphInternal::VendorHelper(ReadFileResult::INVALID_ROOT),
  257. false);
  258. }
  259. namespace cmCMakePresetsGraphInternal {
  260. cmCMakePresetsGraph::ReadFileResult PresetStringHelper(
  261. std::string& out, const Json::Value* value)
  262. {
  263. static auto const helper = cmJSONStringHelper<ReadFileResult>(
  264. ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
  265. return helper(out, value);
  266. }
  267. cmCMakePresetsGraph::ReadFileResult PresetVectorStringHelper(
  268. std::vector<std::string>& out, const Json::Value* value)
  269. {
  270. static auto const helper = cmJSONVectorHelper<std::string, ReadFileResult>(
  271. ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
  272. cmCMakePresetsGraphInternal::PresetStringHelper);
  273. return helper(out, value);
  274. }
  275. cmCMakePresetsGraph::ReadFileResult PresetBoolHelper(bool& out,
  276. const Json::Value* value)
  277. {
  278. static auto const helper = cmJSONBoolHelper<ReadFileResult>(
  279. ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
  280. return helper(out, value);
  281. }
  282. cmCMakePresetsGraph::ReadFileResult PresetOptionalBoolHelper(
  283. cm::optional<bool>& out, const Json::Value* value)
  284. {
  285. static auto const helper = cmJSONOptionalHelper<bool, ReadFileResult>(
  286. ReadFileResult::READ_OK, PresetBoolHelper);
  287. return helper(out, value);
  288. }
  289. cmCMakePresetsGraph::ReadFileResult PresetIntHelper(int& out,
  290. const Json::Value* value)
  291. {
  292. static auto const helper = cmJSONIntHelper<ReadFileResult>(
  293. ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
  294. return helper(out, value);
  295. }
  296. cmCMakePresetsGraph::ReadFileResult PresetOptionalIntHelper(
  297. cm::optional<int>& out, const Json::Value* value)
  298. {
  299. static auto const helper = cmJSONOptionalHelper<int, ReadFileResult>(
  300. ReadFileResult::READ_OK, PresetIntHelper);
  301. return helper(out, value);
  302. }
  303. cmCMakePresetsGraph::ReadFileResult PresetVectorIntHelper(
  304. std::vector<int>& out, const Json::Value* value)
  305. {
  306. static auto const helper = cmJSONVectorHelper<int, ReadFileResult>(
  307. ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper);
  308. return helper(out, value);
  309. }
  310. cmJSONHelper<std::nullptr_t, ReadFileResult> VendorHelper(ReadFileResult error)
  311. {
  312. return [error](std::nullptr_t& /*out*/,
  313. const Json::Value* value) -> ReadFileResult {
  314. if (!value) {
  315. return ReadFileResult::READ_OK;
  316. }
  317. if (!value->isObject()) {
  318. return error;
  319. }
  320. return ReadFileResult::READ_OK;
  321. };
  322. }
  323. ReadFileResult PresetConditionHelper(
  324. std::shared_ptr<cmCMakePresetsGraph::Condition>& out,
  325. const Json::Value* value)
  326. {
  327. std::unique_ptr<cmCMakePresetsGraph::Condition> ptr;
  328. auto result = ConditionHelper(ptr, value);
  329. out = std::move(ptr);
  330. return result;
  331. }
  332. ReadFileResult PresetVectorOneOrMoreStringHelper(std::vector<std::string>& out,
  333. const Json::Value* value)
  334. {
  335. out.clear();
  336. if (!value) {
  337. return ReadFileResult::READ_OK;
  338. }
  339. if (value->isString()) {
  340. out.push_back(value->asString());
  341. return ReadFileResult::READ_OK;
  342. }
  343. return PresetVectorStringHelper(out, value);
  344. }
  345. cmCMakePresetsGraph::ReadFileResult EnvironmentMapHelper(
  346. std::map<std::string, cm::optional<std::string>>& out,
  347. const Json::Value* value)
  348. {
  349. static auto const helper =
  350. cmJSONMapHelper<cm::optional<std::string>, ReadFileResult>(
  351. ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
  352. EnvironmentHelper);
  353. return helper(out, value);
  354. }
  355. }
  356. cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
  357. const std::string& filename, RootType rootType, ReadReason readReason,
  358. std::vector<File*>& inProgressFiles, File*& file)
  359. {
  360. ReadFileResult result;
  361. for (auto const& f : this->Files) {
  362. if (cmSystemTools::SameFile(filename, f->Filename)) {
  363. file = f.get();
  364. auto fileIt =
  365. std::find(inProgressFiles.begin(), inProgressFiles.end(), file);
  366. if (fileIt != inProgressFiles.end()) {
  367. return cmCMakePresetsGraph::ReadFileResult::CYCLIC_INCLUDE;
  368. }
  369. return cmCMakePresetsGraph::ReadFileResult::READ_OK;
  370. }
  371. }
  372. cmsys::ifstream fin(filename.c_str());
  373. if (!fin) {
  374. return ReadFileResult::FILE_NOT_FOUND;
  375. }
  376. // If there's a BOM, toss it.
  377. cmsys::FStream::ReadBOM(fin);
  378. Json::Value root;
  379. Json::CharReaderBuilder builder;
  380. Json::CharReaderBuilder::strictMode(&builder.settings_);
  381. if (!Json::parseFromStream(builder, fin, &root, nullptr)) {
  382. return ReadFileResult::JSON_PARSE_ERROR;
  383. }
  384. int v = 0;
  385. if ((result = RootVersionHelper(v, &root)) != ReadFileResult::READ_OK) {
  386. return result;
  387. }
  388. if (v < MIN_VERSION || v > MAX_VERSION) {
  389. return ReadFileResult::UNRECOGNIZED_VERSION;
  390. }
  391. // Support for build and test presets added in version 2.
  392. if (v < 2 &&
  393. (root.isMember("buildPresets") || root.isMember("testPresets"))) {
  394. return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED;
  395. }
  396. // Support for include added in version 4.
  397. if (v < 4 && root.isMember("include")) {
  398. return ReadFileResult::INCLUDE_UNSUPPORTED;
  399. }
  400. RootPresets presets;
  401. if ((result = RootPresetsHelper(presets, &root)) !=
  402. ReadFileResult::READ_OK) {
  403. return result;
  404. }
  405. unsigned int currentMajor = cmVersion::GetMajorVersion();
  406. unsigned int currentMinor = cmVersion::GetMinorVersion();
  407. unsigned int currentPatch = cmVersion::GetPatchVersion();
  408. auto const& required = presets.CMakeMinimumRequired;
  409. if (required.Major > currentMajor ||
  410. (required.Major == currentMajor &&
  411. (required.Minor > currentMinor ||
  412. (required.Minor == currentMinor &&
  413. (required.Patch > currentPatch))))) {
  414. return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION;
  415. }
  416. auto filePtr = cm::make_unique<File>();
  417. file = filePtr.get();
  418. this->Files.emplace_back(std::move(filePtr));
  419. inProgressFiles.emplace_back(file);
  420. file->Filename = filename;
  421. file->Version = v;
  422. file->ReachableFiles.insert(file);
  423. for (auto& preset : presets.ConfigurePresets) {
  424. preset.OriginFile = file;
  425. if (preset.Name.empty()) {
  426. return ReadFileResult::INVALID_PRESET;
  427. }
  428. PresetPair<ConfigurePreset> presetPair;
  429. presetPair.Unexpanded = preset;
  430. presetPair.Expanded = cm::nullopt;
  431. if (!this->ConfigurePresets
  432. .emplace(std::make_pair(preset.Name, presetPair))
  433. .second) {
  434. return ReadFileResult::DUPLICATE_PRESETS;
  435. }
  436. // Support for installDir presets added in version 3.
  437. if (v < 3 && !preset.InstallDir.empty()) {
  438. return ReadFileResult::INSTALL_PREFIX_UNSUPPORTED;
  439. }
  440. // Support for conditions added in version 3.
  441. if (v < 3 && preset.ConditionEvaluator) {
  442. return ReadFileResult::CONDITION_UNSUPPORTED;
  443. }
  444. // Support for toolchainFile presets added in version 3.
  445. if (v < 3 && !preset.ToolchainFile.empty()) {
  446. return ReadFileResult::TOOLCHAIN_FILE_UNSUPPORTED;
  447. }
  448. this->ConfigurePresetOrder.push_back(preset.Name);
  449. }
  450. for (auto& preset : presets.BuildPresets) {
  451. preset.OriginFile = file;
  452. if (preset.Name.empty()) {
  453. return ReadFileResult::INVALID_PRESET;
  454. }
  455. PresetPair<BuildPreset> presetPair;
  456. presetPair.Unexpanded = preset;
  457. presetPair.Expanded = cm::nullopt;
  458. if (!this->BuildPresets.emplace(preset.Name, presetPair).second) {
  459. return ReadFileResult::DUPLICATE_PRESETS;
  460. }
  461. // Support for conditions added in version 3.
  462. if (v < 3 && preset.ConditionEvaluator) {
  463. return ReadFileResult::CONDITION_UNSUPPORTED;
  464. }
  465. this->BuildPresetOrder.push_back(preset.Name);
  466. }
  467. for (auto& preset : presets.TestPresets) {
  468. preset.OriginFile = file;
  469. if (preset.Name.empty()) {
  470. return ReadFileResult::INVALID_PRESET;
  471. }
  472. PresetPair<TestPreset> presetPair;
  473. presetPair.Unexpanded = preset;
  474. presetPair.Expanded = cm::nullopt;
  475. if (!this->TestPresets.emplace(preset.Name, presetPair).second) {
  476. return ReadFileResult::DUPLICATE_PRESETS;
  477. }
  478. // Support for conditions added in version 3.
  479. if (v < 3 && preset.ConditionEvaluator) {
  480. return ReadFileResult::CONDITION_UNSUPPORTED;
  481. }
  482. // Support for TestOutputTruncation added in version 5.
  483. if (v < 5 && preset.Output) {
  484. return ReadFileResult::TEST_OUTPUT_TRUNCATION_UNSUPPORTED;
  485. }
  486. this->TestPresetOrder.push_back(preset.Name);
  487. }
  488. auto const includeFile = [this, &inProgressFiles, file](
  489. const std::string& include, RootType rootType2,
  490. ReadReason readReason2) -> ReadFileResult {
  491. ReadFileResult r;
  492. File* includedFile;
  493. if ((r = this->ReadJSONFile(include, rootType2, readReason2,
  494. inProgressFiles, includedFile)) !=
  495. ReadFileResult::READ_OK) {
  496. return r;
  497. }
  498. file->ReachableFiles.insert(includedFile->ReachableFiles.begin(),
  499. includedFile->ReachableFiles.end());
  500. return ReadFileResult::READ_OK;
  501. };
  502. for (auto include : presets.Include) {
  503. if (!cmSystemTools::FileIsFullPath(include)) {
  504. auto directory = cmSystemTools::GetFilenamePath(filename);
  505. include = cmStrCat(directory, '/', include);
  506. }
  507. if ((result = includeFile(include, rootType, ReadReason::Included)) !=
  508. ReadFileResult::READ_OK) {
  509. return result;
  510. }
  511. }
  512. if (rootType == RootType::User && readReason == ReadReason::Root) {
  513. auto cmakePresetsFilename = GetFilename(this->SourceDir);
  514. if (cmSystemTools::FileExists(cmakePresetsFilename)) {
  515. if ((result = includeFile(cmakePresetsFilename, RootType::Project,
  516. ReadReason::Root)) !=
  517. ReadFileResult::READ_OK) {
  518. return result;
  519. }
  520. }
  521. }
  522. inProgressFiles.pop_back();
  523. return ReadFileResult::READ_OK;
  524. }