/src/CMake/Source/cmCMakePresetsGraphReadJSON.cxx
Line | Count | Source |
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 <algorithm> |
4 | | #include <cstddef> |
5 | | #include <functional> |
6 | | #include <map> |
7 | | #include <string> |
8 | | #include <unordered_set> |
9 | | #include <utility> |
10 | | #include <vector> |
11 | | |
12 | | #include <cm/memory> |
13 | | #include <cm/optional> |
14 | | #include <cmext/string_view> |
15 | | |
16 | | #include <cm3p/json/value.h> |
17 | | #include <cm3p/json/writer.h> |
18 | | |
19 | | #include "cmCMakePresetsErrors.h" |
20 | | #include "cmCMakePresetsGraph.h" |
21 | | #include "cmCMakePresetsGraphInternal.h" |
22 | | #include "cmJSONHelpers.h" |
23 | | #include "cmJSONState.h" |
24 | | #include "cmStringAlgorithms.h" |
25 | | #include "cmSystemTools.h" |
26 | | #include "cmVersion.h" |
27 | | |
28 | | namespace { |
29 | | using CacheVariable = cmCMakePresetsGraph::CacheVariable; |
30 | | using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset; |
31 | | using BuildPreset = cmCMakePresetsGraph::BuildPreset; |
32 | | using TestPreset = cmCMakePresetsGraph::TestPreset; |
33 | | using PackagePreset = cmCMakePresetsGraph::PackagePreset; |
34 | | using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset; |
35 | | template <typename T> |
36 | | using PresetPair = cmCMakePresetsGraph::PresetPair<T>; |
37 | | using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy; |
38 | | using JSONHelperBuilder = cmJSONHelperBuilder; |
39 | | using ExpandMacroResult = cmCMakePresetsGraphInternal::ExpandMacroResult; |
40 | | using MacroExpander = cmCMakePresetsGraphInternal::MacroExpander; |
41 | | using MacroExpanderVector = cmCMakePresetsGraphInternal::MacroExpanderVector; |
42 | | using cmCMakePresetsGraphInternal::BaseMacroExpander; |
43 | | using cmCMakePresetsGraphInternal::ExpandMacros; |
44 | | using cmCMakePresetsGraphInternal::ExpandImmediateMacros; |
45 | | |
46 | | constexpr int MIN_VERSION = 1; |
47 | | constexpr int MAX_VERSION = 13; |
48 | | |
49 | | struct CMakeVersion |
50 | | { |
51 | | unsigned int Major = 0; |
52 | | unsigned int Minor = 0; |
53 | | unsigned int Patch = 0; |
54 | | }; |
55 | | |
56 | | struct RootPresets |
57 | | { |
58 | | CMakeVersion CMakeMinimumRequired; |
59 | | std::vector<ConfigurePreset> ConfigurePresets; |
60 | | std::vector<BuildPreset> BuildPresets; |
61 | | std::vector<TestPreset> TestPresets; |
62 | | std::vector<PackagePreset> PackagePresets; |
63 | | std::vector<WorkflowPreset> WorkflowPresets; |
64 | | std::vector<std::string> Include; |
65 | | }; |
66 | | |
67 | | std::unique_ptr<cmCMakePresetsGraphInternal::NotCondition> InvertCondition( |
68 | | std::unique_ptr<cmCMakePresetsGraph::Condition> condition) |
69 | 0 | { |
70 | 0 | auto retval = cm::make_unique<cmCMakePresetsGraphInternal::NotCondition>(); |
71 | 0 | retval->SubCondition = std::move(condition); |
72 | 0 | return retval; |
73 | 0 | } |
74 | | |
75 | | auto const ConditionStringHelper = JSONHelperBuilder::String(); |
76 | | |
77 | | auto const ConditionBoolHelper = JSONHelperBuilder::Bool(); |
78 | | |
79 | | auto const ConditionStringListHelper = JSONHelperBuilder::Vector<std::string>( |
80 | | cmCMakePresetsErrors::INVALID_CONDITION, ConditionStringHelper); |
81 | | |
82 | | auto const ConstConditionHelper = |
83 | | JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::ConstCondition>( |
84 | | cmCMakePresetsErrors::INVALID_CONDITION_OBJECT, false) |
85 | | .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) |
86 | | .Bind("value"_s, &cmCMakePresetsGraphInternal::ConstCondition::Value, |
87 | | ConditionBoolHelper, true); |
88 | | |
89 | | auto const EqualsConditionHelper = |
90 | | JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::EqualsCondition>( |
91 | | cmCMakePresetsErrors::INVALID_CONDITION_OBJECT, false) |
92 | | .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) |
93 | | .Bind("lhs"_s, &cmCMakePresetsGraphInternal::EqualsCondition::Lhs, |
94 | | ConditionStringHelper, true) |
95 | | .Bind("rhs"_s, &cmCMakePresetsGraphInternal::EqualsCondition::Rhs, |
96 | | ConditionStringHelper, true); |
97 | | |
98 | | auto const InListConditionHelper = |
99 | | JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::InListCondition>( |
100 | | cmCMakePresetsErrors::INVALID_CONDITION_OBJECT, false) |
101 | | .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) |
102 | | .Bind("string"_s, &cmCMakePresetsGraphInternal::InListCondition::String, |
103 | | ConditionStringHelper, true) |
104 | | .Bind("list"_s, &cmCMakePresetsGraphInternal::InListCondition::List, |
105 | | ConditionStringListHelper, true); |
106 | | |
107 | | auto const MatchesConditionHelper = |
108 | | JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::MatchesCondition>( |
109 | | cmCMakePresetsErrors::INVALID_CONDITION_OBJECT, false) |
110 | | .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) |
111 | | .Bind("string"_s, &cmCMakePresetsGraphInternal::MatchesCondition::String, |
112 | | ConditionStringHelper, true) |
113 | | .Bind("regex"_s, &cmCMakePresetsGraphInternal::MatchesCondition::Regex, |
114 | | ConditionStringHelper, true); |
115 | | |
116 | | bool SubConditionHelper(std::unique_ptr<cmCMakePresetsGraph::Condition>& out, |
117 | | Json::Value const* value, cmJSONState* state); |
118 | | |
119 | | auto const ListConditionVectorHelper = |
120 | | JSONHelperBuilder::Vector<std::unique_ptr<cmCMakePresetsGraph::Condition>>( |
121 | | cmCMakePresetsErrors::INVALID_CONDITION, SubConditionHelper); |
122 | | auto const AnyAllOfConditionHelper = |
123 | | JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::AnyAllOfCondition>( |
124 | | cmCMakePresetsErrors::INVALID_CONDITION_OBJECT, false) |
125 | | .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) |
126 | | .Bind("conditions"_s, |
127 | | &cmCMakePresetsGraphInternal::AnyAllOfCondition::Conditions, |
128 | | ListConditionVectorHelper); |
129 | | |
130 | | auto const NotConditionHelper = |
131 | | JSONHelperBuilder::Object<cmCMakePresetsGraphInternal::NotCondition>( |
132 | | cmCMakePresetsErrors::INVALID_CONDITION_OBJECT, false) |
133 | | .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true) |
134 | | .Bind("condition"_s, |
135 | | &cmCMakePresetsGraphInternal::NotCondition::SubCondition, |
136 | | SubConditionHelper); |
137 | | |
138 | | bool ConditionHelper(std::unique_ptr<cmCMakePresetsGraph::Condition>& out, |
139 | | Json::Value const* value, cmJSONState* state) |
140 | 346k | { |
141 | 346k | if (!value) { |
142 | 227k | out.reset(); |
143 | 227k | return true; |
144 | 227k | } |
145 | | |
146 | 118k | if (value->isBool()) { |
147 | 2.37k | auto c = cm::make_unique<cmCMakePresetsGraphInternal::ConstCondition>(); |
148 | 2.37k | c->Value = value->asBool(); |
149 | 2.37k | out = std::move(c); |
150 | 2.37k | return true; |
151 | 2.37k | } |
152 | | |
153 | 116k | if (value->isNull()) { |
154 | 0 | out = cm::make_unique<cmCMakePresetsGraphInternal::NullCondition>(); |
155 | 0 | return true; |
156 | 0 | } |
157 | | |
158 | 116k | if (value->isObject()) { |
159 | 116k | if (!value->isMember("type")) { |
160 | 16.7k | cmCMakePresetsErrors::INVALID_CONDITION(value, state); |
161 | 16.7k | return false; |
162 | 16.7k | } |
163 | | |
164 | 99.6k | if (!(*value)["type"].isString()) { |
165 | 9 | cmCMakePresetsErrors::INVALID_CONDITION(value, state); |
166 | 9 | return false; |
167 | 9 | } |
168 | 99.6k | auto type = (*value)["type"].asString(); |
169 | | |
170 | 99.6k | if (type == "const") { |
171 | 11.0k | auto c = cm::make_unique<cmCMakePresetsGraphInternal::ConstCondition>(); |
172 | 11.0k | CHECK_OK(ConstConditionHelper(*c, value, state)); |
173 | 10.7k | out = std::move(c); |
174 | 10.7k | return true; |
175 | 11.0k | } |
176 | | |
177 | 88.5k | if (type == "equals" || type == "notEquals") { |
178 | 10.2k | auto c = cm::make_unique<cmCMakePresetsGraphInternal::EqualsCondition>(); |
179 | 10.2k | CHECK_OK(EqualsConditionHelper(*c, value, state)); |
180 | 6.78k | out = std::move(c); |
181 | 6.78k | if (type == "notEquals") { |
182 | 0 | out = InvertCondition(std::move(out)); |
183 | 0 | } |
184 | 6.78k | return true; |
185 | 10.2k | } |
186 | | |
187 | 78.3k | if (type == "inList" || type == "notInList") { |
188 | 21.1k | auto c = cm::make_unique<cmCMakePresetsGraphInternal::InListCondition>(); |
189 | 21.1k | CHECK_OK(InListConditionHelper(*c, value, state)); |
190 | 10.7k | out = std::move(c); |
191 | 10.7k | if (type == "notInList") { |
192 | 0 | out = InvertCondition(std::move(out)); |
193 | 0 | } |
194 | 10.7k | return true; |
195 | 21.1k | } |
196 | | |
197 | 57.1k | if (type == "matches" || type == "notMatches") { |
198 | 29.3k | auto c = |
199 | 29.3k | cm::make_unique<cmCMakePresetsGraphInternal::MatchesCondition>(); |
200 | 29.3k | CHECK_OK(MatchesConditionHelper(*c, value, state)); |
201 | 18.3k | out = std::move(c); |
202 | 18.3k | if (type == "notMatches") { |
203 | 0 | out = InvertCondition(std::move(out)); |
204 | 0 | } |
205 | 18.3k | return true; |
206 | 29.3k | } |
207 | | |
208 | 27.8k | if (type == "anyOf" || type == "allOf") { |
209 | 6.07k | auto c = |
210 | 6.07k | cm::make_unique<cmCMakePresetsGraphInternal::AnyAllOfCondition>(); |
211 | 6.07k | c->StopValue = (type == "anyOf"); |
212 | 6.07k | CHECK_OK(AnyAllOfConditionHelper(*c, value, state)); |
213 | 4.38k | out = std::move(c); |
214 | 4.38k | return true; |
215 | 6.07k | } |
216 | | |
217 | 21.7k | if (type == "not") { |
218 | 11.4k | auto c = cm::make_unique<cmCMakePresetsGraphInternal::NotCondition>(); |
219 | 11.4k | CHECK_OK(NotConditionHelper(*c, value, state)); |
220 | 8.36k | out = std::move(c); |
221 | 8.36k | return true; |
222 | 11.4k | } |
223 | 21.7k | } |
224 | | |
225 | 10.4k | cmCMakePresetsErrors::INVALID_CONDITION(value, state); |
226 | 10.4k | return false; |
227 | 116k | } |
228 | | |
229 | | bool SubConditionHelper(std::unique_ptr<cmCMakePresetsGraph::Condition>& out, |
230 | | Json::Value const* value, cmJSONState* state) |
231 | 107k | { |
232 | 107k | std::unique_ptr<cmCMakePresetsGraph::Condition> ptr; |
233 | 107k | auto result = ConditionHelper(ptr, value, state); |
234 | 107k | if (ptr && ptr->IsNull()) { |
235 | 0 | cmCMakePresetsErrors::INVALID_CONDITION(value, state); |
236 | 0 | return false; |
237 | 0 | } |
238 | 107k | out = std::move(ptr); |
239 | 107k | return result; |
240 | 107k | } |
241 | | |
242 | | bool EnvironmentHelper(cm::optional<std::string>& out, |
243 | | Json::Value const* value, cmJSONState* state) |
244 | 15.3k | { |
245 | 15.3k | if (!value || value->isNull()) { |
246 | 60 | out = cm::nullopt; |
247 | 60 | return true; |
248 | 60 | } |
249 | 15.2k | if (value->isString()) { |
250 | 15.1k | out = value->asString(); |
251 | 15.1k | return true; |
252 | 15.1k | } |
253 | 159 | cmCMakePresetsErrors::INVALID_PRESET(value, state); |
254 | 159 | return false; |
255 | 15.2k | } |
256 | | |
257 | | auto const VersionIntHelper = |
258 | | JSONHelperBuilder::Int(cmCMakePresetsErrors::INVALID_VERSION); |
259 | | |
260 | | auto const VersionHelper = JSONHelperBuilder::Required<int>( |
261 | | cmCMakePresetsErrors::NO_VERSION, VersionIntHelper); |
262 | | |
263 | | auto const VersionRangeHelper = JSONHelperBuilder::Checked<int>( |
264 | | cmCMakePresetsErrors::UNRECOGNIZED_VERSION_RANGE(MIN_VERSION, MAX_VERSION), |
265 | | VersionHelper, |
266 | 27.0k | [](int const v) -> bool { return v >= MIN_VERSION && v <= MAX_VERSION; }); |
267 | | |
268 | | auto const RootVersionHelper = |
269 | | JSONHelperBuilder::Object<int>(cmCMakePresetsErrors::INVALID_ROOT_OBJECT) |
270 | | .Bind("version"_s, VersionRangeHelper, false); |
271 | | |
272 | | auto const CMakeVersionUIntHelper = |
273 | | JSONHelperBuilder::UInt(cmCMakePresetsErrors::INVALID_VERSION); |
274 | | |
275 | | auto const CMakeVersionHelper = |
276 | | JSONHelperBuilder::Object<CMakeVersion>(JsonErrors::INVALID_NAMED_OBJECT_KEY, |
277 | | false) |
278 | | .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false) |
279 | | .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false) |
280 | | .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false); |
281 | | |
282 | | auto const IncludeHelper = |
283 | | JSONHelperBuilder::String(cmCMakePresetsErrors::INVALID_INCLUDE); |
284 | | |
285 | | auto const IncludeVectorHelper = JSONHelperBuilder::Vector<std::string>( |
286 | | cmCMakePresetsErrors::INVALID_INCLUDE, IncludeHelper); |
287 | | |
288 | | auto const RootPresetsHelper = |
289 | | JSONHelperBuilder::Object<RootPresets>( |
290 | | cmCMakePresetsErrors::INVALID_ROOT_OBJECT, false) |
291 | | .Bind<int>("version"_s, nullptr, VersionHelper) |
292 | | .Bind("configurePresets"_s, &RootPresets::ConfigurePresets, |
293 | | cmCMakePresetsGraphInternal::ConfigurePresetsHelper, false) |
294 | | .Bind("buildPresets"_s, &RootPresets::BuildPresets, |
295 | | cmCMakePresetsGraphInternal::BuildPresetsHelper, false) |
296 | | .Bind("testPresets"_s, &RootPresets::TestPresets, |
297 | | cmCMakePresetsGraphInternal::TestPresetsHelper, false) |
298 | | .Bind("packagePresets"_s, &RootPresets::PackagePresets, |
299 | | cmCMakePresetsGraphInternal::PackagePresetsHelper, false) |
300 | | .Bind("workflowPresets"_s, &RootPresets::WorkflowPresets, |
301 | | cmCMakePresetsGraphInternal::WorkflowPresetsHelper, false) |
302 | | .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired, |
303 | | CMakeVersionHelper, false) |
304 | | .Bind("include"_s, &RootPresets::Include, IncludeVectorHelper, false) |
305 | | .Bind<std::nullptr_t>("vendor"_s, nullptr, |
306 | | cmCMakePresetsGraphInternal::VendorHelper( |
307 | | cmCMakePresetsErrors::INVALID_ROOT), |
308 | | false) |
309 | | .Bind<std::nullptr_t>("$schema"_s, nullptr, |
310 | | cmCMakePresetsGraphInternal::SchemaHelper(), false); |
311 | | |
312 | | class EnvironmentMacroExpander : public MacroExpander |
313 | | { |
314 | | public: |
315 | | ExpandMacroResult operator()(std::string const& macroNamespace, |
316 | | std::string const& macroName, |
317 | | std::string& macroOut, |
318 | | int /*version*/) const override |
319 | 2.53k | { |
320 | 2.53k | if (macroNamespace == "penv") { |
321 | 2.37k | if (macroName.empty()) { |
322 | 3 | return ExpandMacroResult::Error; |
323 | 3 | } |
324 | 2.37k | if (cm::optional<std::string> value = |
325 | 2.37k | cmSystemTools::GetEnvVar(macroName)) { |
326 | 132 | macroOut += *value; |
327 | 132 | } |
328 | 2.37k | return ExpandMacroResult::Ok; |
329 | 2.37k | } |
330 | | |
331 | 156 | return ExpandMacroResult::Ignore; |
332 | 2.53k | } |
333 | | }; |
334 | | |
335 | | template <typename T> |
336 | | bool RegisterPresets(std::vector<T>& presets, cmCMakePresetsGraph::File* file, |
337 | | std::map<std::string, PresetPair<T>>& out, |
338 | | std::vector<std::string>& order, cmJSONState* state, |
339 | | std::function<bool(T&)> const& checkVersionSupport = {}) |
340 | 92.4k | { |
341 | 92.4k | for (auto& preset : presets) { |
342 | 84.8k | preset.OriginFile = file; |
343 | 84.8k | if (preset.Name.empty()) { |
344 | | // No error, already handled by PresetNameHelper |
345 | 0 | return false; |
346 | 0 | } |
347 | | |
348 | 84.8k | if (!ExpandImmediateMacros<T>(preset)) { |
349 | 117 | cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name, state); |
350 | 117 | return false; |
351 | 117 | } |
352 | | |
353 | 84.7k | if (checkVersionSupport && !checkVersionSupport(preset)) { |
354 | 183 | return false; |
355 | 183 | } |
356 | | |
357 | 84.5k | PresetPair<T> presetPair; |
358 | 84.5k | presetPair.Unexpanded = preset; |
359 | 84.5k | presetPair.Expanded = cm::nullopt; |
360 | 84.5k | if (!out.emplace(preset.Name, presetPair).second) { |
361 | 465 | cmCMakePresetsErrors::DUPLICATE_PRESETS(preset.Name, state); |
362 | 465 | return false; |
363 | 465 | } |
364 | | |
365 | 84.1k | order.push_back(preset.Name); |
366 | 84.1k | } |
367 | 91.6k | return true; |
368 | 92.4k | } cmCMakePresetsGraphReadJSON.cxx:bool (anonymous namespace)::RegisterPresets<cmCMakePresetsGraph::ConfigurePreset>(std::__1::vector<cmCMakePresetsGraph::ConfigurePreset, std::__1::allocator<cmCMakePresetsGraph::ConfigurePreset> >&, cmCMakePresetsGraph::File*, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, cmCMakePresetsGraph::PresetPair<cmCMakePresetsGraph::ConfigurePreset>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, cmCMakePresetsGraph::PresetPair<cmCMakePresetsGraph::ConfigurePreset> > > >&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, cmJSONState*, std::__1::function<bool (cmCMakePresetsGraph::ConfigurePreset&)> const&) Line | Count | Source | 340 | 18.9k | { | 341 | 47.7k | for (auto& preset : presets) { | 342 | 47.7k | preset.OriginFile = file; | 343 | 47.7k | if (preset.Name.empty()) { | 344 | | // No error, already handled by PresetNameHelper | 345 | 0 | return false; | 346 | 0 | } | 347 | | | 348 | 47.7k | if (!ExpandImmediateMacros<T>(preset)) { | 349 | 102 | cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name, state); | 350 | 102 | return false; | 351 | 102 | } | 352 | | | 353 | 47.6k | if (checkVersionSupport && !checkVersionSupport(preset)) { | 354 | 174 | return false; | 355 | 174 | } | 356 | | | 357 | 47.4k | PresetPair<T> presetPair; | 358 | 47.4k | presetPair.Unexpanded = preset; | 359 | 47.4k | presetPair.Expanded = cm::nullopt; | 360 | 47.4k | if (!out.emplace(preset.Name, presetPair).second) { | 361 | 204 | cmCMakePresetsErrors::DUPLICATE_PRESETS(preset.Name, state); | 362 | 204 | return false; | 363 | 204 | } | 364 | | | 365 | 47.2k | order.push_back(preset.Name); | 366 | 47.2k | } | 367 | 18.5k | return true; | 368 | 18.9k | } |
cmCMakePresetsGraphReadJSON.cxx:bool (anonymous namespace)::RegisterPresets<cmCMakePresetsGraph::BuildPreset>(std::__1::vector<cmCMakePresetsGraph::BuildPreset, std::__1::allocator<cmCMakePresetsGraph::BuildPreset> >&, cmCMakePresetsGraph::File*, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, cmCMakePresetsGraph::PresetPair<cmCMakePresetsGraph::BuildPreset>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, cmCMakePresetsGraph::PresetPair<cmCMakePresetsGraph::BuildPreset> > > >&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, cmJSONState*, std::__1::function<bool (cmCMakePresetsGraph::BuildPreset&)> const&) Line | Count | Source | 340 | 18.5k | { | 341 | 18.5k | for (auto& preset : presets) { | 342 | 11.7k | preset.OriginFile = file; | 343 | 11.7k | if (preset.Name.empty()) { | 344 | | // No error, already handled by PresetNameHelper | 345 | 0 | return false; | 346 | 0 | } | 347 | | | 348 | 11.7k | if (!ExpandImmediateMacros<T>(preset)) { | 349 | 15 | cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name, state); | 350 | 15 | return false; | 351 | 15 | } | 352 | | | 353 | 11.7k | if (checkVersionSupport && !checkVersionSupport(preset)) { | 354 | 3 | return false; | 355 | 3 | } | 356 | | | 357 | 11.7k | PresetPair<T> presetPair; | 358 | 11.7k | presetPair.Unexpanded = preset; | 359 | 11.7k | presetPair.Expanded = cm::nullopt; | 360 | 11.7k | if (!out.emplace(preset.Name, presetPair).second) { | 361 | 90 | cmCMakePresetsErrors::DUPLICATE_PRESETS(preset.Name, state); | 362 | 90 | return false; | 363 | 90 | } | 364 | | | 365 | 11.6k | order.push_back(preset.Name); | 366 | 11.6k | } | 367 | 18.4k | return true; | 368 | 18.5k | } |
cmCMakePresetsGraphReadJSON.cxx:bool (anonymous namespace)::RegisterPresets<cmCMakePresetsGraph::TestPreset>(std::__1::vector<cmCMakePresetsGraph::TestPreset, std::__1::allocator<cmCMakePresetsGraph::TestPreset> >&, cmCMakePresetsGraph::File*, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, cmCMakePresetsGraph::PresetPair<cmCMakePresetsGraph::TestPreset>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, cmCMakePresetsGraph::PresetPair<cmCMakePresetsGraph::TestPreset> > > >&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, cmJSONState*, std::__1::function<bool (cmCMakePresetsGraph::TestPreset&)> const&) Line | Count | Source | 340 | 18.4k | { | 341 | 18.4k | for (auto& preset : presets) { | 342 | 12.9k | preset.OriginFile = file; | 343 | 12.9k | if (preset.Name.empty()) { | 344 | | // No error, already handled by PresetNameHelper | 345 | 0 | return false; | 346 | 0 | } | 347 | | | 348 | 12.9k | if (!ExpandImmediateMacros<T>(preset)) { | 349 | 0 | cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name, state); | 350 | 0 | return false; | 351 | 0 | } | 352 | | | 353 | 12.9k | if (checkVersionSupport && !checkVersionSupport(preset)) { | 354 | 6 | return false; | 355 | 6 | } | 356 | | | 357 | 12.9k | PresetPair<T> presetPair; | 358 | 12.9k | presetPair.Unexpanded = preset; | 359 | 12.9k | presetPair.Expanded = cm::nullopt; | 360 | 12.9k | if (!out.emplace(preset.Name, presetPair).second) { | 361 | 87 | cmCMakePresetsErrors::DUPLICATE_PRESETS(preset.Name, state); | 362 | 87 | return false; | 363 | 87 | } | 364 | | | 365 | 12.8k | order.push_back(preset.Name); | 366 | 12.8k | } | 367 | 18.3k | return true; | 368 | 18.4k | } |
cmCMakePresetsGraphReadJSON.cxx:bool (anonymous namespace)::RegisterPresets<cmCMakePresetsGraph::PackagePreset>(std::__1::vector<cmCMakePresetsGraph::PackagePreset, std::__1::allocator<cmCMakePresetsGraph::PackagePreset> >&, cmCMakePresetsGraph::File*, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, cmCMakePresetsGraph::PresetPair<cmCMakePresetsGraph::PackagePreset>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, cmCMakePresetsGraph::PresetPair<cmCMakePresetsGraph::PackagePreset> > > >&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, cmJSONState*, std::__1::function<bool (cmCMakePresetsGraph::PackagePreset&)> const&) Line | Count | Source | 340 | 18.3k | { | 341 | 18.3k | for (auto& preset : presets) { | 342 | 10.6k | preset.OriginFile = file; | 343 | 10.6k | if (preset.Name.empty()) { | 344 | | // No error, already handled by PresetNameHelper | 345 | 0 | return false; | 346 | 0 | } | 347 | | | 348 | 10.6k | if (!ExpandImmediateMacros<T>(preset)) { | 349 | 0 | cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name, state); | 350 | 0 | return false; | 351 | 0 | } | 352 | | | 353 | 10.6k | if (checkVersionSupport && !checkVersionSupport(preset)) { | 354 | 0 | return false; | 355 | 0 | } | 356 | | | 357 | 10.6k | PresetPair<T> presetPair; | 358 | 10.6k | presetPair.Unexpanded = preset; | 359 | 10.6k | presetPair.Expanded = cm::nullopt; | 360 | 10.6k | if (!out.emplace(preset.Name, presetPair).second) { | 361 | 84 | cmCMakePresetsErrors::DUPLICATE_PRESETS(preset.Name, state); | 362 | 84 | return false; | 363 | 84 | } | 364 | | | 365 | 10.5k | order.push_back(preset.Name); | 366 | 10.5k | } | 367 | 18.2k | return true; | 368 | 18.3k | } |
cmCMakePresetsGraphReadJSON.cxx:bool (anonymous namespace)::RegisterPresets<cmCMakePresetsGraph::WorkflowPreset>(std::__1::vector<cmCMakePresetsGraph::WorkflowPreset, std::__1::allocator<cmCMakePresetsGraph::WorkflowPreset> >&, cmCMakePresetsGraph::File*, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, cmCMakePresetsGraph::PresetPair<cmCMakePresetsGraph::WorkflowPreset>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, cmCMakePresetsGraph::PresetPair<cmCMakePresetsGraph::WorkflowPreset> > > >&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, cmJSONState*, std::__1::function<bool (cmCMakePresetsGraph::WorkflowPreset&)> const&) Line | Count | Source | 340 | 18.2k | { | 341 | 18.2k | for (auto& preset : presets) { | 342 | 1.91k | preset.OriginFile = file; | 343 | 1.91k | if (preset.Name.empty()) { | 344 | | // No error, already handled by PresetNameHelper | 345 | 0 | return false; | 346 | 0 | } | 347 | | | 348 | 1.91k | if (!ExpandImmediateMacros<T>(preset)) { | 349 | 0 | cmCMakePresetsErrors::INVALID_MACRO_EXPANSION(preset.Name, state); | 350 | 0 | return false; | 351 | 0 | } | 352 | | | 353 | 1.91k | if (checkVersionSupport && !checkVersionSupport(preset)) { | 354 | 0 | return false; | 355 | 0 | } | 356 | | | 357 | 1.91k | PresetPair<T> presetPair; | 358 | 1.91k | presetPair.Unexpanded = preset; | 359 | 1.91k | presetPair.Expanded = cm::nullopt; | 360 | 1.91k | if (!out.emplace(preset.Name, presetPair).second) { | 361 | 0 | cmCMakePresetsErrors::DUPLICATE_PRESETS(preset.Name, state); | 362 | 0 | return false; | 363 | 0 | } | 364 | | | 365 | 1.91k | order.push_back(preset.Name); | 366 | 1.91k | } | 367 | 18.2k | return true; | 368 | 18.2k | } |
|
369 | | } |
370 | | |
371 | | namespace cmCMakePresetsGraphInternal { |
372 | | bool PresetStringHelper(std::string& out, Json::Value const* value, |
373 | | cmJSONState* state) |
374 | 1.77M | { |
375 | 1.77M | static auto const helper = JSONHelperBuilder::String(); |
376 | 1.77M | return helper(out, value, state); |
377 | 1.77M | } |
378 | | |
379 | | bool PresetNameHelper(std::string& out, Json::Value const* value, |
380 | | cmJSONState* state) |
381 | 222k | { |
382 | 222k | if (!value || !value->isString() || value->asString().empty()) { |
383 | 561 | cmCMakePresetsErrors::INVALID_PRESET_NAME(value, state); |
384 | 561 | return false; |
385 | 561 | } |
386 | 222k | out = value->asString(); |
387 | 222k | return true; |
388 | 222k | } |
389 | | |
390 | | bool PresetVectorStringHelper(std::vector<std::string>& out, |
391 | | Json::Value const* value, cmJSONState* state) |
392 | 186k | { |
393 | 186k | static auto const helper = JSONHelperBuilder::Vector<std::string>( |
394 | 186k | cmCMakePresetsErrors::INVALID_PRESET, |
395 | 186k | cmCMakePresetsGraphInternal::PresetStringHelper); |
396 | 186k | return helper(out, value, state); |
397 | 186k | } |
398 | | |
399 | | bool PresetBoolHelper(bool& out, Json::Value const* value, cmJSONState* state) |
400 | 238k | { |
401 | 238k | static auto const helper = JSONHelperBuilder::Bool(); |
402 | 238k | return helper(out, value, state); |
403 | 238k | } |
404 | | |
405 | | bool PresetOptionalBoolHelper(cm::optional<bool>& out, |
406 | | Json::Value const* value, cmJSONState* state) |
407 | 2.79M | { |
408 | 2.79M | static auto const helper = |
409 | 2.79M | JSONHelperBuilder::Optional<bool>(PresetBoolHelper); |
410 | 2.79M | return helper(out, value, state); |
411 | 2.79M | } |
412 | | |
413 | | bool PresetIntHelper(int& out, Json::Value const* value, cmJSONState* state) |
414 | 0 | { |
415 | 0 | static auto const helper = JSONHelperBuilder::Int(); |
416 | 0 | return helper(out, value, state); |
417 | 0 | } |
418 | | |
419 | | bool PresetOptionalIntHelper(cm::optional<int>& out, Json::Value const* value, |
420 | | cmJSONState* state) |
421 | 96 | { |
422 | 96 | static auto const helper = JSONHelperBuilder::Optional<int>(PresetIntHelper); |
423 | 96 | return helper(out, value, state); |
424 | 96 | } |
425 | | |
426 | | bool PresetUIntHelper(unsigned int& out, Json::Value const* value, |
427 | | cmJSONState* state) |
428 | 4.94k | { |
429 | 4.94k | static auto const helper = JSONHelperBuilder::UInt(); |
430 | 4.94k | return helper(out, value, state); |
431 | 4.94k | } |
432 | | |
433 | | bool PresetOptionalUIntHelper(cm::optional<unsigned int>& out, |
434 | | Json::Value const* value, cmJSONState* state) |
435 | 51.5k | { |
436 | 51.5k | static auto const helper = |
437 | 51.5k | JSONHelperBuilder::Optional<unsigned int>(PresetUIntHelper); |
438 | 51.5k | return helper(out, value, state); |
439 | 51.5k | } |
440 | | |
441 | | bool PresetVectorIntHelper(std::vector<int>& out, Json::Value const* value, |
442 | | cmJSONState* state) |
443 | 0 | { |
444 | 0 | static auto const helper = JSONHelperBuilder::Vector<int>( |
445 | 0 | cmCMakePresetsErrors::INVALID_PRESET, PresetIntHelper); |
446 | 0 | return helper(out, value, state); |
447 | 0 | } |
448 | | |
449 | | cmJSONHelper<std::nullptr_t> VendorHelper(ErrorGenerator const& error) |
450 | 36 | { |
451 | 36 | return [error](std::nullptr_t& /*out*/, Json::Value const* value, |
452 | 290k | cmJSONState* state) -> bool { |
453 | 290k | if (!value) { |
454 | 290k | return true; |
455 | 290k | } |
456 | | |
457 | 102 | if (!value->isObject()) { |
458 | 96 | error(value, state); |
459 | 96 | return false; |
460 | 96 | } |
461 | | |
462 | 6 | return true; |
463 | 102 | }; |
464 | 36 | } |
465 | | |
466 | | bool PresetConditionHelper( |
467 | | std::shared_ptr<cmCMakePresetsGraph::Condition>& out, |
468 | | Json::Value const* value, cmJSONState* state) |
469 | 238k | { |
470 | 238k | std::unique_ptr<cmCMakePresetsGraph::Condition> ptr; |
471 | 238k | auto result = ConditionHelper(ptr, value, state); |
472 | 238k | if (result && ptr) { |
473 | 9.10k | Json::StreamWriterBuilder writer; |
474 | 9.10k | writer["indentation"] = ""; |
475 | 9.10k | ptr->ConditionJson = Json::writeString(writer, *value); |
476 | 9.10k | } |
477 | 238k | out = std::move(ptr); |
478 | 238k | return result; |
479 | 238k | } |
480 | | |
481 | | bool PresetVectorOneOrMoreStringHelper(std::vector<std::string>& out, |
482 | | Json::Value const* value, |
483 | | cmJSONState* state) |
484 | 394k | { |
485 | 394k | out.clear(); |
486 | 394k | if (!value) { |
487 | 355k | return true; |
488 | 355k | } |
489 | | |
490 | 38.8k | if (value->isString()) { |
491 | 22.4k | out.push_back(value->asString()); |
492 | 22.4k | return true; |
493 | 22.4k | } |
494 | | |
495 | 16.4k | return PresetVectorStringHelper(out, value, state); |
496 | 38.8k | } |
497 | | |
498 | | bool EnvironmentMapHelper( |
499 | | std::map<std::string, cm::optional<std::string>>& out, |
500 | | Json::Value const* value, cmJSONState* state) |
501 | 238k | { |
502 | 238k | static auto const helper = JSONHelperBuilder::Map<cm::optional<std::string>>( |
503 | 238k | cmCMakePresetsErrors::INVALID_PRESET, EnvironmentHelper); |
504 | | |
505 | 238k | return helper(out, value, state); |
506 | 238k | } |
507 | | |
508 | | cmJSONHelper<std::nullptr_t> SchemaHelper() |
509 | 6 | { |
510 | 26.6k | return [](std::nullptr_t&, Json::Value const*, cmJSONState*) -> bool { |
511 | 26.6k | return true; |
512 | 26.6k | }; |
513 | 6 | } |
514 | | } |
515 | | |
516 | | bool cmCMakePresetsGraph::ReadJSONFile(std::string const& filename, |
517 | | RootType rootType, |
518 | | ReadReason readReason, |
519 | | std::vector<File*>& inProgressFiles, |
520 | | File*& file, std::string& errMsg) |
521 | 36.2k | { |
522 | 36.2k | bool result; |
523 | | |
524 | 36.2k | for (auto const& f : this->Files) { |
525 | 3.56k | if (cmSystemTools::SameFile(filename, f->Filename)) { |
526 | 1.10k | file = f.get(); |
527 | 1.10k | auto fileIt = |
528 | 1.10k | std::find(inProgressFiles.begin(), inProgressFiles.end(), file); |
529 | 1.10k | if (fileIt != inProgressFiles.end()) { |
530 | 1.10k | cmCMakePresetsErrors::CYCLIC_INCLUDE(filename, &this->parseState); |
531 | 1.10k | return false; |
532 | 1.10k | } |
533 | | |
534 | 0 | return true; |
535 | 1.10k | } |
536 | 3.56k | } |
537 | | |
538 | 35.1k | Json::Value root; |
539 | 35.1k | this->parseState = cmJSONState(filename, &root); |
540 | 35.1k | if (!this->parseState.errors.empty()) { |
541 | 7.53k | return false; |
542 | 7.53k | } |
543 | | |
544 | 27.5k | int v = 0; |
545 | 27.5k | if ((result = RootVersionHelper(v, &root, &parseState)) != true) { |
546 | 924 | return result; |
547 | 924 | } |
548 | | |
549 | | // Support for build and test presets added in version 2. |
550 | 26.6k | if (v < 2) { |
551 | 564 | if (root.isMember("buildPresets")) { |
552 | 3 | cmCMakePresetsErrors::BUILD_TEST_PRESETS_UNSUPPORTED( |
553 | 3 | &root["buildPresets"], &this->parseState); |
554 | 3 | return false; |
555 | 3 | } |
556 | 561 | if (root.isMember("testPresets")) { |
557 | 3 | cmCMakePresetsErrors::BUILD_TEST_PRESETS_UNSUPPORTED( |
558 | 3 | &root["testPresets"], &this->parseState); |
559 | 3 | return false; |
560 | 3 | } |
561 | 561 | } |
562 | | |
563 | | // Support for package presets added in version 6. |
564 | 26.6k | if (v < 6 && root.isMember("packagePresets")) { |
565 | 3 | cmCMakePresetsErrors::PACKAGE_PRESETS_UNSUPPORTED(&root["packagePresets"], |
566 | 3 | &this->parseState); |
567 | 3 | return false; |
568 | 3 | } |
569 | | |
570 | | // Support for workflow presets added in version 6. |
571 | 26.6k | if (v < 6 && root.isMember("workflowPresets")) { |
572 | 3 | cmCMakePresetsErrors::WORKFLOW_PRESETS_UNSUPPORTED( |
573 | 3 | &root["workflowPresets"], &this->parseState); |
574 | 3 | return false; |
575 | 3 | } |
576 | | |
577 | | // Support for include added in version 4. |
578 | 26.6k | if (v < 4 && root.isMember("include")) { |
579 | 9 | cmCMakePresetsErrors::INCLUDE_UNSUPPORTED(&root["include"], |
580 | 9 | &this->parseState); |
581 | 9 | return false; |
582 | 9 | } |
583 | | |
584 | | // Support for $schema added in version 8. |
585 | 26.6k | if (v < 8 && root.isMember("$schema")) { |
586 | 3 | cmCMakePresetsErrors::SCHEMA_UNSUPPORTED(&this->parseState); |
587 | 3 | return false; |
588 | 3 | } |
589 | | |
590 | | // Support for $comment added in version 10. |
591 | 26.6k | this->parseState.allowComments = (v >= 10); |
592 | | |
593 | 26.6k | RootPresets presets; |
594 | 26.6k | if ((result = RootPresetsHelper(presets, &root, &parseState)) != true) { |
595 | 7.61k | return result; |
596 | 7.61k | } |
597 | | |
598 | 19.0k | unsigned int currentMajor = cmVersion::GetMajorVersion(); |
599 | 19.0k | unsigned int currentMinor = cmVersion::GetMinorVersion(); |
600 | 19.0k | unsigned int currentPatch = cmVersion::GetPatchVersion(); |
601 | 19.0k | auto const& required = presets.CMakeMinimumRequired; |
602 | 19.0k | if (required.Major > currentMajor) { |
603 | 30 | ErrorGenerator error = cmCMakePresetsErrors::UNRECOGNIZED_CMAKE_VERSION( |
604 | 30 | "major", currentMajor, required.Major); |
605 | 30 | error(&root["cmakeMinimumRequired"]["major"], &this->parseState); |
606 | 30 | return false; |
607 | 30 | } |
608 | 19.0k | if (required.Major == currentMajor) { |
609 | 21 | if (required.Minor > currentMinor) { |
610 | 12 | ErrorGenerator error = cmCMakePresetsErrors::UNRECOGNIZED_CMAKE_VERSION( |
611 | 12 | "minor", currentMinor, required.Minor); |
612 | 12 | error(&root["cmakeMinimumRequired"]["minor"], &this->parseState); |
613 | 12 | return false; |
614 | 12 | } |
615 | 9 | if (required.Minor == currentMinor && required.Patch > currentPatch) { |
616 | 0 | ErrorGenerator error = cmCMakePresetsErrors::UNRECOGNIZED_CMAKE_VERSION( |
617 | 0 | "patch", currentPatch, required.Patch); |
618 | 0 | error(&root["cmakeMinimumRequired"]["patch"], &this->parseState); |
619 | 0 | return false; |
620 | 0 | } |
621 | 9 | } |
622 | | |
623 | 18.9k | auto filePtr = cm::make_unique<File>(); |
624 | 18.9k | file = filePtr.get(); |
625 | 18.9k | this->Files.emplace_back(std::move(filePtr)); |
626 | 18.9k | inProgressFiles.emplace_back(file); |
627 | 18.9k | file->Filename = filename; |
628 | 18.9k | file->Version = v; |
629 | 18.9k | file->ReachableFiles.insert(file); |
630 | | |
631 | 47.6k | auto const configureVersionCheck = [&](ConfigurePreset& preset) -> bool { |
632 | | // Support for installDir presets added in version 3. |
633 | 47.6k | if (v < 3 && !preset.InstallDir.empty()) { |
634 | 60 | cmCMakePresetsErrors::INSTALL_PREFIX_UNSUPPORTED(&root["installDir"], |
635 | 60 | &this->parseState); |
636 | 60 | return false; |
637 | 60 | } |
638 | | |
639 | | // Support for conditions added in version 3. |
640 | 47.5k | if (v < 3 && preset.ConditionEvaluator) { |
641 | 27 | cmCMakePresetsErrors::CONDITION_UNSUPPORTED(&this->parseState); |
642 | 27 | return false; |
643 | 27 | } |
644 | | |
645 | | // Support for toolchainFile presets added in version 3. |
646 | 47.5k | if (v < 3 && !preset.ToolchainFile.empty()) { |
647 | 45 | cmCMakePresetsErrors::TOOLCHAIN_FILE_UNSUPPORTED(&this->parseState); |
648 | 45 | return false; |
649 | 45 | } |
650 | | |
651 | | // Support for trace presets added in version 7. |
652 | 47.4k | if (v < 7 && |
653 | 32.6k | (preset.TraceMode.has_value() || preset.TraceFormat.has_value() || |
654 | 32.6k | !preset.TraceRedirect.empty() || !preset.TraceSource.empty())) { |
655 | 0 | cmCMakePresetsErrors::TRACE_UNSUPPORTED(&this->parseState); |
656 | 0 | return false; |
657 | 0 | } |
658 | | |
659 | | // Support for graphviz argument added in version 10. |
660 | 47.4k | if (v < 10 && !preset.GraphVizFile.empty()) { |
661 | 42 | cmCMakePresetsErrors::GRAPHVIZ_FILE_UNSUPPORTED(&this->parseState); |
662 | 42 | return false; |
663 | 42 | } |
664 | | |
665 | | // Support for diagnostics. |
666 | 47.4k | return cmCMakePresetsGraphInternal::CheckDiagnostics(&this->parseState, v, |
667 | 47.4k | preset); |
668 | 47.4k | }; |
669 | | |
670 | 18.9k | if (!RegisterPresets<ConfigurePreset>( |
671 | 18.9k | presets.ConfigurePresets, file, this->ConfigurePresets, |
672 | 18.9k | this->ConfigurePresetOrder, &this->parseState, |
673 | 18.9k | configureVersionCheck)) { |
674 | 480 | return false; |
675 | 480 | } |
676 | | |
677 | 18.5k | auto const buildVersionCheck = [&](BuildPreset& preset) -> bool { |
678 | | // Support for conditions added in version 3. |
679 | 11.7k | if (v < 3 && preset.ConditionEvaluator) { |
680 | 3 | cmCMakePresetsErrors::CONDITION_UNSUPPORTED(&this->parseState); |
681 | 3 | return false; |
682 | 3 | } |
683 | 11.7k | return true; |
684 | 11.7k | }; |
685 | | |
686 | 18.5k | if (!RegisterPresets<BuildPreset>(presets.BuildPresets, file, |
687 | 18.5k | this->BuildPresets, this->BuildPresetOrder, |
688 | 18.5k | &this->parseState, buildVersionCheck)) { |
689 | 108 | return false; |
690 | 108 | } |
691 | | |
692 | 18.4k | auto const testVersionCheck = [&](TestPreset& preset) -> bool { |
693 | | // Support for conditions added in version 3. |
694 | 12.9k | if (v < 3 && preset.ConditionEvaluator) { |
695 | 6 | cmCMakePresetsErrors::CONDITION_UNSUPPORTED(&this->parseState); |
696 | 6 | return false; |
697 | 6 | } |
698 | | |
699 | | // Support for TestOutputTruncation added in version 5. |
700 | 12.9k | if (v < 5 && preset.Output && preset.Output->TestOutputTruncation) { |
701 | 0 | cmCMakePresetsErrors::TEST_OUTPUT_TRUNCATION_UNSUPPORTED( |
702 | 0 | &this->parseState); |
703 | 0 | return false; |
704 | 0 | } |
705 | | |
706 | | // Support for outputJUnitFile added in version 6. |
707 | 12.9k | if (v < 6 && preset.Output && !preset.Output->OutputJUnitFile.empty()) { |
708 | 0 | cmCMakePresetsErrors::CTEST_JUNIT_UNSUPPORTED(&this->parseState); |
709 | 0 | return false; |
710 | 0 | } |
711 | | |
712 | | // Support for processor-count-based jobs added in version 11. |
713 | 12.9k | if (v < 11 && preset.Execution && preset.Execution->Jobs.has_value() && |
714 | 0 | !preset.Execution->Jobs->has_value()) { |
715 | 0 | cmCMakePresetsErrors::JOBS_PROC_UNSUPPORTED(&this->parseState); |
716 | 0 | return false; |
717 | 0 | } |
718 | | |
719 | | // Support for testPassthroughArguments added in version 12. |
720 | 12.9k | if (v < 12 && preset.Execution && |
721 | 6 | !preset.Execution->TestPassthroughArguments.empty()) { |
722 | 0 | cmCMakePresetsErrors::PASSTHROUGH_ARGS_UNSUPPORTED(&this->parseState); |
723 | 0 | return false; |
724 | 0 | } |
725 | | |
726 | 12.9k | return true; |
727 | 12.9k | }; |
728 | | |
729 | 18.4k | if (!RegisterPresets<TestPreset>(presets.TestPresets, file, |
730 | 18.4k | this->TestPresets, this->TestPresetOrder, |
731 | 18.4k | &this->parseState, testVersionCheck)) { |
732 | 93 | return false; |
733 | 93 | } |
734 | | |
735 | | // Support for conditions added in version 3, but this requires version 5 |
736 | | // already, so no action needed. |
737 | 18.3k | if (!RegisterPresets<PackagePreset>( |
738 | 18.3k | presets.PackagePresets, file, this->PackagePresets, |
739 | 18.3k | this->PackagePresetOrder, &this->parseState)) { |
740 | 84 | return false; |
741 | 84 | } |
742 | | |
743 | | // Support for conditions added in version 3, but this requires version 6 |
744 | | // already, so no action needed. |
745 | 18.2k | if (!RegisterPresets<WorkflowPreset>( |
746 | 18.2k | presets.WorkflowPresets, file, this->WorkflowPresets, |
747 | 18.2k | this->WorkflowPresetOrder, &this->parseState)) { |
748 | 0 | return false; |
749 | 0 | } |
750 | | |
751 | 18.2k | auto const includeFile = [this, &inProgressFiles, |
752 | 18.2k | file](std::string const& include, |
753 | 18.2k | RootType rootType2, ReadReason readReason2, |
754 | 18.2k | std::string& FailureMessage) -> bool { |
755 | 2.46k | bool r; |
756 | 2.46k | File* includedFile; |
757 | 2.46k | if ((r = |
758 | 2.46k | this->ReadJSONFile(include, rootType2, readReason2, inProgressFiles, |
759 | 2.46k | includedFile, FailureMessage)) != true) { |
760 | 2.46k | return r; |
761 | 2.46k | } |
762 | | |
763 | 0 | file->ReachableFiles.insert(includedFile->ReachableFiles.begin(), |
764 | 0 | includedFile->ReachableFiles.end()); |
765 | 0 | return true; |
766 | 2.46k | }; |
767 | | |
768 | 18.2k | MacroExpanderVector macroExpanders{}; |
769 | | |
770 | 18.2k | if (v >= 9) { |
771 | 2.89k | macroExpanders.push_back( |
772 | 2.89k | cm::make_unique<BaseMacroExpander>(*this, filename)); |
773 | 2.89k | } |
774 | 18.2k | macroExpanders.push_back(cm::make_unique<EnvironmentMacroExpander>()); |
775 | | |
776 | 18.2k | for (Json::ArrayIndex i = 0; i < presets.Include.size(); ++i) { |
777 | 2.66k | auto include = presets.Include[i]; |
778 | | |
779 | | // Support for macro expansion in includes added in version 7 |
780 | 2.66k | if (v >= 7) { |
781 | 2.14k | if (ExpandMacros(include, macroExpanders, v) != ExpandMacroResult::Ok) { |
782 | 204 | cmCMakePresetsErrors::INVALID_INCLUDE(&root["include"][i], |
783 | 204 | &this->parseState); |
784 | 204 | return false; |
785 | 204 | } |
786 | 2.14k | } |
787 | | |
788 | 2.46k | if (!cmSystemTools::FileIsFullPath(include)) { |
789 | 2.44k | auto directory = cmSystemTools::GetFilenamePath(filename); |
790 | 2.44k | include = cmStrCat(directory, '/', include); |
791 | 2.44k | } |
792 | | |
793 | 2.46k | if ((result = includeFile(include, rootType, ReadReason::Included, |
794 | 2.46k | errMsg)) != true) { |
795 | 2.46k | return result; |
796 | 2.46k | } |
797 | 2.46k | } |
798 | | |
799 | 15.5k | if (rootType == RootType::User && readReason == ReadReason::Root) { |
800 | 5.18k | auto cmakePresetsFilename = GetFilename(this->SourceDir); |
801 | 5.18k | if (cmSystemTools::FileExists(cmakePresetsFilename)) { |
802 | 0 | if ((result = includeFile(cmakePresetsFilename, RootType::Project, |
803 | 0 | ReadReason::Root, errMsg)) != true) { |
804 | 0 | return result; |
805 | 0 | } |
806 | 0 | } |
807 | 5.18k | } |
808 | | |
809 | 15.5k | inProgressFiles.pop_back(); |
810 | 15.5k | return true; |
811 | 15.5k | } |