1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gn/value_extractors.h"
6
7 #include <stddef.h>
8
9 #include "gn/build_settings.h"
10 #include "gn/err.h"
11 #include "gn/frameworks_utils.h"
12 #include "gn/label.h"
13 #include "gn/ohos_components_mapping.h"
14 #include "gn/source_dir.h"
15 #include "gn/source_file.h"
16 #include "gn/target.h"
17 #include "gn/value.h"
18
19 namespace {
20
21 // Sets the error and returns false on failure.
22 template <typename T, class Converter>
ListValueExtractor(const Value & value,std::vector<T> * dest,Err * err,const Converter & converter)23 bool ListValueExtractor(const Value& value,
24 std::vector<T>* dest,
25 Err* err,
26 const Converter& converter) {
27 if (!value.VerifyTypeIs(Value::LIST, err))
28 return false;
29 const std::vector<Value>& input_list = value.list_value();
30 dest->resize(input_list.size());
31 for (size_t i = 0; i < input_list.size(); i++) {
32 if (!converter(input_list[i], &(*dest)[i], err))
33 return false;
34 }
35 return true;
36 }
37
38 // Sets the error and returns false on failure.
39 template <typename T, class Converter>
ListValueExtractorExt(const Value & value,std::vector<T> * dest,std::vector<T> * whole_dest,std::vector<T> * no_whole_dest,Err * err,const Converter & converter)40 bool ListValueExtractorExt(const Value& value,
41 std::vector<T>* dest,
42 std::vector<T>* whole_dest,
43 std::vector<T>* no_whole_dest,
44 Err* err,
45 const Converter& converter) {
46 if (!value.VerifyTypeIs(Value::LIST, err))
47 return false;
48 const std::vector<Value>& input_list = value.list_value();
49 dest->resize(input_list.size());
50 for (size_t i = 0; i < input_list.size(); i++) {
51 int whole_status = -1;
52 if (!converter(input_list[i], &(*dest)[i], whole_status, err))
53 return false;
54
55 if (whole_status == 1) {
56 whole_dest->push_back((*dest)[i]);
57 } else if (whole_status == 0) {
58 no_whole_dest->push_back((*dest)[i]);
59 }
60 }
61 return true;
62 }
63
64 // Sets the error and returns false on failure.
65 template <typename T, class Converter>
ListValueAppender(const Value & value,std::vector<T> * dest,std::vector<T> * whole_dest,std::vector<T> * no_whole_dest,Err * err,const Converter & converter)66 bool ListValueAppender(const Value& value,
67 std::vector<T>* dest,
68 std::vector<T>* whole_dest,
69 std::vector<T>* no_whole_dest,
70 Err* err,
71 const Converter& converter)
72 {
73 if (!value.VerifyTypeIs(Value::LIST, err))
74 return false;
75 const std::vector<Value>& input_list = value.list_value();
76 for (const auto& item : input_list) {
77 T new_one;
78 int whole_status = -1;
79 if (!converter(item, &new_one, whole_status, err))
80 return false;
81 dest->push_back(new_one);
82 if (whole_status == 1) {
83 whole_dest->push_back(new_one);
84 } else if (whole_status == 0) {
85 no_whole_dest->push_back(new_one);
86 }
87 }
88 return true;
89 }
90
91 // Like the above version but extracts to a UniqueVector and sets the error if
92 // there are duplicates.
93 template <typename T, class Converter>
ListValueUniqueExtractor(const Value & value,UniqueVector<T> * dest,Err * err,const Converter & converter)94 bool ListValueUniqueExtractor(const Value& value,
95 UniqueVector<T>* dest,
96 Err* err,
97 const Converter& converter) {
98 if (!value.VerifyTypeIs(Value::LIST, err))
99 return false;
100 const std::vector<Value>& input_list = value.list_value();
101
102 for (const auto& item : input_list) {
103 T new_one;
104 if (!converter(item, &new_one, err))
105 return false;
106 if (!dest->push_back(new_one)) {
107 // Already in the list, throw error.
108 *err = Err(item, "Duplicate item in list");
109 size_t previous_index = dest->IndexOf(new_one);
110 err->AppendSubErr(
111 Err(input_list[previous_index], "This was the previous definition."));
112 return false;
113 }
114 }
115 return true;
116 }
117
118 struct RelativeFileConverter {
RelativeFileConverter__anonf177f6c20111::RelativeFileConverter119 RelativeFileConverter(const BuildSettings* build_settings_in,
120 const SourceDir& current_dir_in)
121 : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anonf177f6c20111::RelativeFileConverter122 bool operator()(const Value& v, SourceFile* out, Err* err) const {
123 *out = current_dir.ResolveRelativeFile(v, err,
124 build_settings->root_path_utf8());
125 return !err->has_error();
126 }
127 const BuildSettings* build_settings;
128 const SourceDir& current_dir;
129 };
130
131 struct LibFileConverter {
LibFileConverter__anonf177f6c20111::LibFileConverter132 LibFileConverter(const BuildSettings* build_settings_in,
133 const SourceDir& current_dir_in)
134 : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anonf177f6c20111::LibFileConverter135 bool operator()(const Value& v, LibFile* out, Err* err) const {
136 if (!v.VerifyTypeIs(Value::STRING, err))
137 return false;
138 if (!GetFrameworkName(v.string_value()).empty()) {
139 *err = Err(v, "Unsupported value in libs.",
140 "Use frameworks to list framework dependencies.");
141 return false;
142 }
143 if (v.string_value().find('/') == std::string::npos) {
144 *out = LibFile(v.string_value());
145 } else {
146 *out = LibFile(current_dir.ResolveRelativeFile(
147 v, err, build_settings->root_path_utf8()));
148 }
149 return !err->has_error();
150 }
151 const BuildSettings* build_settings;
152 const SourceDir& current_dir;
153 };
154
155 struct RelativeDirConverter {
RelativeDirConverter__anonf177f6c20111::RelativeDirConverter156 RelativeDirConverter(const BuildSettings* build_settings_in,
157 const SourceDir& current_dir_in)
158 : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anonf177f6c20111::RelativeDirConverter159 bool operator()(const Value& v, SourceDir* out, Err* err) const {
160 *out = current_dir.ResolveRelativeDir(v, err,
161 build_settings->root_path_utf8());
162 return true;
163 }
164 const BuildSettings* build_settings;
165 const SourceDir& current_dir;
166 };
167
168 struct ExternConverter {
ExternConverter__anonf177f6c20111::ExternConverter169 ExternConverter(const BuildSettings* build_settings_in,
170 const SourceDir& current_dir_in)
171 : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anonf177f6c20111::ExternConverter172 bool operator()(const Value& v,
173 std::pair<std::string, LibFile>* out,
174 Err* err) const {
175 if (!v.VerifyTypeIs(Value::SCOPE, err))
176 return false;
177 Scope::KeyValueMap scope;
178 v.scope_value()->GetCurrentScopeValues(&scope);
179 std::string cratename;
180 if (auto it = scope.find("crate_name"); it != scope.end()) {
181 if (!it->second.VerifyTypeIs(Value::STRING, err))
182 return false;
183 cratename = it->second.string_value();
184 } else {
185 return false;
186 }
187 LibFile path;
188 if (auto it = scope.find("path"); it != scope.end()) {
189 if (!it->second.VerifyTypeIs(Value::STRING, err))
190 return false;
191 if (it->second.string_value().find('/') == std::string::npos) {
192 path = LibFile(it->second.string_value());
193 } else {
194 path = LibFile(current_dir.ResolveRelativeFile(
195 it->second, err, build_settings->root_path_utf8()));
196 }
197 } else {
198 return false;
199 }
200 *out = std::pair(cratename, path);
201 return !err->has_error();
202 }
203 const BuildSettings* build_settings;
204 const SourceDir& current_dir;
205 };
206
207 // Fills in a label.
208 template <typename T>
209 struct LabelResolver {
LabelResolver__anonf177f6c20111::LabelResolver210 LabelResolver(const BuildSettings* build_settings_in,
211 const SourceDir& current_dir_in,
212 const Label& current_toolchain_in)
213 : build_settings(build_settings_in),
214 current_dir(current_dir_in),
215 current_toolchain(current_toolchain_in) {}
operator ()__anonf177f6c20111::LabelResolver216 bool operator()(const Value& v, Label* out, Err* err) const {
217 if (!v.VerifyTypeIs(Value::STRING, err))
218 return false;
219 *out = Label::Resolve(current_dir, build_settings->root_path_utf8(),
220 current_toolchain, v, err);
221 return !err->has_error();
222 }
223 const BuildSettings* build_settings;
224 const SourceDir& current_dir;
225 const Label& current_toolchain;
226 };
227
228 // Fills the label part of a LabelPtrPair, if it is a cross-component dependency, mapping is required.
229 template <typename T>
230 struct LabelPtrResolverMapping {
LabelPtrResolverMapping__anonf177f6c20111::LabelPtrResolverMapping231 LabelPtrResolverMapping(const std::string &label_in,
232 const BuildSettings* build_settings_in,
233 const SourceDir& current_dir_in,
234 const Label& current_toolchain_in)
235 : label(label_in),
236 build_settings(build_settings_in),
237 current_dir(current_dir_in),
238 current_toolchain(current_toolchain_in) {}
operator ()__anonf177f6c20111::LabelPtrResolverMapping239 bool operator()(const Value& v, LabelPtrPair<T>* out, int &whole_status, Err* err) const {
240 if (!v.VerifyTypeIs(Value::STRING, err)) {
241 return false;
242 }
243
244 std::string dep_label;
245 if (!build_settings->GetPrivateDepsLabel(v, dep_label, current_toolchain, whole_status, err)) {
246 return false;
247 }
248
249 std::string map_label = "";
250 OhosComponentMapping *mapping = OhosComponentMapping::getInstance();
251 if (mapping != nullptr) {
252 map_label = mapping->MappingTargetAbsoluteDpes(build_settings, label, dep_label);
253 }
254 if (map_label != "") {
255 Value map_dep(v.origin(), map_label);
256 out->label = Label::Resolve(current_dir, build_settings->root_path_utf8(),
257 current_toolchain, map_dep, err);
258 out->origin = map_dep.origin();
259 } else {
260 Value dep_value(v.origin(), dep_label);
261 out->label = Label::Resolve(current_dir, build_settings->root_path_utf8(),
262 current_toolchain, dep_value, err);
263 out->origin = v.origin();
264 }
265 return !err->has_error();
266 }
267 const std::string &label;
268 const BuildSettings* build_settings;
269 const SourceDir& current_dir;
270 const Label& current_toolchain;
271 };
272
273 // Fills the label part of a LabelPtrPair, leaving the pointer null.
274 template <typename T>
275 struct LabelPtrResolver {
LabelPtrResolver__anonf177f6c20111::LabelPtrResolver276 LabelPtrResolver(const BuildSettings* build_settings_in,
277 const SourceDir& current_dir_in,
278 const Label& current_toolchain_in)
279 : build_settings(build_settings_in),
280 current_dir(current_dir_in),
281 current_toolchain(current_toolchain_in) {}
operator ()__anonf177f6c20111::LabelPtrResolver282 bool operator()(const Value& v, LabelPtrPair<T>* out, Err* err) const {
283 if (!v.VerifyTypeIs(Value::STRING, err))
284 return false;
285 out->label = Label::Resolve(current_dir, build_settings->root_path_utf8(),
286 current_toolchain, v, err);
287 out->origin = v.origin();
288 return !err->has_error();
289 }
290 const BuildSettings* build_settings;
291 const SourceDir& current_dir;
292 const Label& current_toolchain;
293 };
294
295 // Fills the label part of a LabelPtrPair, leaving the pointer null.
296 template <typename T>
297 struct ExternalDepPtrResolver {
ExternalDepPtrResolver__anonf177f6c20111::ExternalDepPtrResolver298 ExternalDepPtrResolver(const BuildSettings* build_settings_in,
299 const SourceDir& current_dir_in,
300 const Label& current_toolchain_in)
301 : build_settings(build_settings_in),
302 current_dir(current_dir_in),
303 current_toolchain(current_toolchain_in) {}
operator ()__anonf177f6c20111::ExternalDepPtrResolver304 bool operator()(const Value& v, LabelPtrPair<T>* out, int &whole_status, Err* err) const
305 {
306 if (!v.VerifyTypeIs(Value::STRING, err)) {
307 return false;
308 }
309 std::string label;
310 if (!build_settings->GetExternalDepsLabel(v, label, current_toolchain, whole_status, err)) {
311 return false;
312 }
313 Value external_dep(v.origin(), label);
314 out->label = Label::Resolve(current_dir, build_settings->root_path_utf8(),
315 current_toolchain, external_dep, err);
316 out->origin = v.origin();
317 out->is_external_deps = true;
318 return !err->has_error();
319 }
320 const BuildSettings* build_settings;
321 const SourceDir& current_dir;
322 const Label& current_toolchain;
323 };
324
325 struct LabelPatternResolver {
LabelPatternResolver__anonf177f6c20111::LabelPatternResolver326 LabelPatternResolver(const BuildSettings* build_settings_in,
327 const SourceDir& current_dir_in)
328 : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anonf177f6c20111::LabelPatternResolver329 bool operator()(const Value& v, LabelPattern* out, Err* err) const {
330 *out = LabelPattern::GetPattern(current_dir,
331 build_settings->root_path_utf8(), v, err);
332 return !err->has_error();
333 }
334
335 const BuildSettings* build_settings;
336 const SourceDir& current_dir;
337 };
338
339 } // namespace
340
ExtractListOfStringValues(const Value & value,std::vector<std::string> * dest,Err * err)341 bool ExtractListOfStringValues(const Value& value,
342 std::vector<std::string>* dest,
343 Err* err) {
344 if (!value.VerifyTypeIs(Value::LIST, err))
345 return false;
346 const std::vector<Value>& input_list = value.list_value();
347 dest->reserve(input_list.size());
348 for (const auto& item : input_list) {
349 if (!item.VerifyTypeIs(Value::STRING, err))
350 return false;
351 dest->push_back(item.string_value());
352 }
353 return true;
354 }
355
ExtractListOfRelativeFiles(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<SourceFile> * files,Err * err)356 bool ExtractListOfRelativeFiles(const BuildSettings* build_settings,
357 const Value& value,
358 const SourceDir& current_dir,
359 std::vector<SourceFile>* files,
360 Err* err) {
361 return ListValueExtractor(value, files, err,
362 RelativeFileConverter(build_settings, current_dir));
363 }
364
ExtractListOfLibs(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<LibFile> * libs,Err * err)365 bool ExtractListOfLibs(const BuildSettings* build_settings,
366 const Value& value,
367 const SourceDir& current_dir,
368 std::vector<LibFile>* libs,
369 Err* err) {
370 return ListValueExtractor(value, libs, err,
371 LibFileConverter(build_settings, current_dir));
372 }
373
ExtractListOfRelativeDirs(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<SourceDir> * dest,Err * err)374 bool ExtractListOfRelativeDirs(const BuildSettings* build_settings,
375 const Value& value,
376 const SourceDir& current_dir,
377 std::vector<SourceDir>* dest,
378 Err* err) {
379 return ListValueExtractor(value, dest, err,
380 RelativeDirConverter(build_settings, current_dir));
381 }
382
ExtractListOfLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,LabelTargetVector * dest,Err * err)383 bool ExtractListOfLabels(const BuildSettings* build_settings,
384 const Value& value,
385 const SourceDir& current_dir,
386 const Label& current_toolchain,
387 LabelTargetVector* dest,
388 Err* err) {
389 return ListValueExtractor(
390 value, dest, err,
391 LabelPtrResolver<Target>(build_settings, current_dir, current_toolchain));
392 }
393
ExtractListOfLabelsMapping(const std::string & label,const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,LabelTargetVector * dest,LabelTargetVector * whole_dest,LabelTargetVector * no_whole_dest,Err * err)394 bool ExtractListOfLabelsMapping(const std::string& label,
395 const BuildSettings* build_settings,
396 const Value& value,
397 const SourceDir& current_dir,
398 const Label& current_toolchain,
399 LabelTargetVector* dest,
400 LabelTargetVector* whole_dest,
401 LabelTargetVector* no_whole_dest,
402 Err* err) {
403 return ListValueExtractorExt(
404 value, dest, whole_dest, no_whole_dest, err,
405 LabelPtrResolverMapping<Target>(label, build_settings, current_dir, current_toolchain));
406 }
407
ExtractListOfExternalDeps(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,LabelTargetVector * dest,LabelTargetVector * whole_dest,LabelTargetVector * no_whole_dest,Err * err)408 bool ExtractListOfExternalDeps(const BuildSettings* build_settings,
409 const Value& value,
410 const SourceDir& current_dir,
411 const Label& current_toolchain,
412 LabelTargetVector* dest,
413 LabelTargetVector* whole_dest,
414 LabelTargetVector* no_whole_dest,
415 Err* err) {
416 return ListValueAppender(
417 value, dest, whole_dest, no_whole_dest, err,
418 ExternalDepPtrResolver<Target>(build_settings, current_dir, current_toolchain));
419 }
420
ExtractListOfUniqueLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,UniqueVector<Label> * dest,Err * err)421 bool ExtractListOfUniqueLabels(const BuildSettings* build_settings,
422 const Value& value,
423 const SourceDir& current_dir,
424 const Label& current_toolchain,
425 UniqueVector<Label>* dest,
426 Err* err) {
427 return ListValueUniqueExtractor(
428 value, dest, err,
429 LabelResolver<Config>(build_settings, current_dir, current_toolchain));
430 }
431
ExtractListOfUniqueLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,UniqueVector<LabelConfigPair> * dest,Err * err)432 bool ExtractListOfUniqueLabels(const BuildSettings* build_settings,
433 const Value& value,
434 const SourceDir& current_dir,
435 const Label& current_toolchain,
436 UniqueVector<LabelConfigPair>* dest,
437 Err* err) {
438 return ListValueUniqueExtractor(
439 value, dest, err,
440 LabelPtrResolver<Config>(build_settings, current_dir, current_toolchain));
441 }
442
ExtractListOfUniqueLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,UniqueVector<LabelTargetPair> * dest,Err * err)443 bool ExtractListOfUniqueLabels(const BuildSettings* build_settings,
444 const Value& value,
445 const SourceDir& current_dir,
446 const Label& current_toolchain,
447 UniqueVector<LabelTargetPair>* dest,
448 Err* err) {
449 return ListValueUniqueExtractor(
450 value, dest, err,
451 LabelPtrResolver<Target>(build_settings, current_dir, current_toolchain));
452 }
453
ExtractRelativeFile(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,SourceFile * file,Err * err)454 bool ExtractRelativeFile(const BuildSettings* build_settings,
455 const Value& value,
456 const SourceDir& current_dir,
457 SourceFile* file,
458 Err* err) {
459 RelativeFileConverter converter(build_settings, current_dir);
460 return converter(value, file, err);
461 }
462
ExtractListOfLabelPatterns(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<LabelPattern> * patterns,Err * err)463 bool ExtractListOfLabelPatterns(const BuildSettings* build_settings,
464 const Value& value,
465 const SourceDir& current_dir,
466 std::vector<LabelPattern>* patterns,
467 Err* err) {
468 return ListValueExtractor(value, patterns, err,
469 LabelPatternResolver(build_settings, current_dir));
470 }
471
ExtractListOfExterns(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<std::pair<std::string,LibFile>> * externs,Err * err)472 bool ExtractListOfExterns(const BuildSettings* build_settings,
473 const Value& value,
474 const SourceDir& current_dir,
475 std::vector<std::pair<std::string, LibFile>>* externs,
476 Err* err) {
477 return ListValueExtractor(value, externs, err,
478 ExternConverter(build_settings, current_dir));
479 }
480