cmCMakePresetsGraphReadJSON.cxx 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  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 = 4;
  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. if (rootType == RootType::Project) {
  362. auto normalizedFilename = cmSystemTools::CollapseFullPath(filename);
  363. auto normalizedProjectDir =
  364. cmSystemTools::CollapseFullPath(this->SourceDir);
  365. if (!cmSystemTools::IsSubDirectory(normalizedFilename,
  366. normalizedProjectDir)) {
  367. return ReadFileResult::INCLUDE_OUTSIDE_PROJECT;
  368. }
  369. }
  370. for (auto const& f : this->Files) {
  371. if (cmSystemTools::SameFile(filename, f->Filename)) {
  372. file = f.get();
  373. auto fileIt =
  374. std::find(inProgressFiles.begin(), inProgressFiles.end(), file);
  375. if (fileIt != inProgressFiles.end()) {
  376. return cmCMakePresetsGraph::ReadFileResult::CYCLIC_INCLUDE;
  377. }
  378. // Check files included by this file again to make sure they're in the
  379. // project directory.
  380. if (rootType == RootType::Project) {
  381. for (auto* f2 : file->ReachableFiles) {
  382. if (!cmSystemTools::SameFile(filename, f2->Filename)) {
  383. File* file2;
  384. if ((result = this->ReadJSONFile(
  385. f2->Filename, rootType, ReadReason::Included,
  386. inProgressFiles, file2)) != ReadFileResult::READ_OK) {
  387. return result;
  388. }
  389. }
  390. }
  391. }
  392. return cmCMakePresetsGraph::ReadFileResult::READ_OK;
  393. }
  394. }
  395. cmsys::ifstream fin(filename.c_str());
  396. if (!fin) {
  397. return ReadFileResult::FILE_NOT_FOUND;
  398. }
  399. // If there's a BOM, toss it.
  400. cmsys::FStream::ReadBOM(fin);
  401. Json::Value root;
  402. Json::CharReaderBuilder builder;
  403. Json::CharReaderBuilder::strictMode(&builder.settings_);
  404. if (!Json::parseFromStream(builder, fin, &root, nullptr)) {
  405. return ReadFileResult::JSON_PARSE_ERROR;
  406. }
  407. int v = 0;
  408. if ((result = RootVersionHelper(v, &root)) != ReadFileResult::READ_OK) {
  409. return result;
  410. }
  411. if (v < MIN_VERSION || v > MAX_VERSION) {
  412. return ReadFileResult::UNRECOGNIZED_VERSION;
  413. }
  414. // Support for build and test presets added in version 2.
  415. if (v < 2 &&
  416. (root.isMember("buildPresets") || root.isMember("testPresets"))) {
  417. return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED;
  418. }
  419. // Support for include added in version 4.
  420. if (v < 4 && root.isMember("include")) {
  421. return ReadFileResult::INCLUDE_UNSUPPORTED;
  422. }
  423. RootPresets presets;
  424. if ((result = RootPresetsHelper(presets, &root)) !=
  425. ReadFileResult::READ_OK) {
  426. return result;
  427. }
  428. unsigned int currentMajor = cmVersion::GetMajorVersion();
  429. unsigned int currentMinor = cmVersion::GetMinorVersion();
  430. unsigned int currentPatch = cmVersion::GetPatchVersion();
  431. auto const& required = presets.CMakeMinimumRequired;
  432. if (required.Major > currentMajor ||
  433. (required.Major == currentMajor &&
  434. (required.Minor > currentMinor ||
  435. (required.Minor == currentMinor &&
  436. (required.Patch > currentPatch))))) {
  437. return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION;
  438. }
  439. auto filePtr = cm::make_unique<File>();
  440. file = filePtr.get();
  441. this->Files.emplace_back(std::move(filePtr));
  442. inProgressFiles.emplace_back(file);
  443. file->Filename = filename;
  444. file->Version = v;
  445. file->ReachableFiles.insert(file);
  446. for (auto& preset : presets.ConfigurePresets) {
  447. preset.OriginFile = file;
  448. if (preset.Name.empty()) {
  449. return ReadFileResult::INVALID_PRESET;
  450. }
  451. PresetPair<ConfigurePreset> presetPair;
  452. presetPair.Unexpanded = preset;
  453. presetPair.Expanded = cm::nullopt;
  454. if (!this->ConfigurePresets
  455. .emplace(std::make_pair(preset.Name, presetPair))
  456. .second) {
  457. return ReadFileResult::DUPLICATE_PRESETS;
  458. }
  459. // Support for installDir presets added in version 3.
  460. if (v < 3 && !preset.InstallDir.empty()) {
  461. return ReadFileResult::INSTALL_PREFIX_UNSUPPORTED;
  462. }
  463. // Support for conditions added in version 3.
  464. if (v < 3 && preset.ConditionEvaluator) {
  465. return ReadFileResult::CONDITION_UNSUPPORTED;
  466. }
  467. // Support for toolchainFile presets added in version 3.
  468. if (v < 3 && !preset.ToolchainFile.empty()) {
  469. return ReadFileResult::TOOLCHAIN_FILE_UNSUPPORTED;
  470. }
  471. this->ConfigurePresetOrder.push_back(preset.Name);
  472. }
  473. for (auto& preset : presets.BuildPresets) {
  474. preset.OriginFile = file;
  475. if (preset.Name.empty()) {
  476. return ReadFileResult::INVALID_PRESET;
  477. }
  478. PresetPair<BuildPreset> presetPair;
  479. presetPair.Unexpanded = preset;
  480. presetPair.Expanded = cm::nullopt;
  481. if (!this->BuildPresets.emplace(preset.Name, presetPair).second) {
  482. return ReadFileResult::DUPLICATE_PRESETS;
  483. }
  484. // Support for conditions added in version 3.
  485. if (v < 3 && preset.ConditionEvaluator) {
  486. return ReadFileResult::CONDITION_UNSUPPORTED;
  487. }
  488. this->BuildPresetOrder.push_back(preset.Name);
  489. }
  490. for (auto& preset : presets.TestPresets) {
  491. preset.OriginFile = file;
  492. if (preset.Name.empty()) {
  493. return ReadFileResult::INVALID_PRESET;
  494. }
  495. PresetPair<TestPreset> presetPair;
  496. presetPair.Unexpanded = preset;
  497. presetPair.Expanded = cm::nullopt;
  498. if (!this->TestPresets.emplace(preset.Name, presetPair).second) {
  499. return ReadFileResult::DUPLICATE_PRESETS;
  500. }
  501. // Support for conditions added in version 3.
  502. if (v < 3 && preset.ConditionEvaluator) {
  503. return ReadFileResult::CONDITION_UNSUPPORTED;
  504. }
  505. this->TestPresetOrder.push_back(preset.Name);
  506. }
  507. auto const includeFile = [this, &inProgressFiles, file](
  508. const std::string& include, RootType rootType2,
  509. ReadReason readReason2) -> ReadFileResult {
  510. ReadFileResult r;
  511. File* includedFile;
  512. if ((r = this->ReadJSONFile(include, rootType2, readReason2,
  513. inProgressFiles, includedFile)) !=
  514. ReadFileResult::READ_OK) {
  515. return r;
  516. }
  517. file->ReachableFiles.insert(includedFile->ReachableFiles.begin(),
  518. includedFile->ReachableFiles.end());
  519. return ReadFileResult::READ_OK;
  520. };
  521. for (auto include : presets.Include) {
  522. if (!cmSystemTools::FileIsFullPath(include)) {
  523. auto directory = cmSystemTools::GetFilenamePath(filename);
  524. include = cmStrCat(directory, '/', include);
  525. }
  526. if ((result = includeFile(include, rootType, ReadReason::Included)) !=
  527. ReadFileResult::READ_OK) {
  528. return result;
  529. }
  530. }
  531. if (rootType == RootType::User && readReason == ReadReason::Root) {
  532. auto cmakePresetsFilename = GetFilename(this->SourceDir);
  533. if (cmSystemTools::FileExists(cmakePresetsFilename)) {
  534. if ((result = includeFile(cmakePresetsFilename, RootType::Project,
  535. ReadReason::Root)) !=
  536. ReadFileResult::READ_OK) {
  537. return result;
  538. }
  539. }
  540. }
  541. inProgressFiles.pop_back();
  542. return ReadFileResult::READ_OK;
  543. }