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/target.h"
6
7 #include <stddef.h>
8
9 #include "base/stl_util.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "gn/c_tool.h"
13 #include "gn/config_values_extractors.h"
14 #include "gn/deps_iterator.h"
15 #include "gn/filesystem_utils.h"
16 #include "gn/functions.h"
17 #include "gn/scheduler.h"
18 #include "gn/substitution_writer.h"
19 #include "gn/tool.h"
20 #include "gn/toolchain.h"
21 #include "gn/trace.h"
22
23 namespace {
24
25 using ConfigSet = std::set<const Config*>;
26
27 // Merges the public configs from the given target to the given config list.
MergePublicConfigsFrom(const Target * from_target,UniqueVector<LabelConfigPair> * dest)28 void MergePublicConfigsFrom(const Target* from_target,
29 UniqueVector<LabelConfigPair>* dest) {
30 const UniqueVector<LabelConfigPair>& pub = from_target->public_configs();
31 dest->Append(pub.begin(), pub.end());
32 }
33
34 // Like MergePublicConfigsFrom above except does the "all dependent" ones. This
35 // additionally adds all configs to the all_dependent_configs_ of the dest
36 // target given in *all_dest.
MergeAllDependentConfigsFrom(const Target * from_target,UniqueVector<LabelConfigPair> * dest,UniqueVector<LabelConfigPair> * all_dest)37 void MergeAllDependentConfigsFrom(const Target* from_target,
38 UniqueVector<LabelConfigPair>* dest,
39 UniqueVector<LabelConfigPair>* all_dest) {
40 for (const auto& pair : from_target->all_dependent_configs()) {
41 all_dest->push_back(pair);
42 dest->push_back(pair);
43 }
44 }
45
MakeTestOnlyError(const Item * from,const Item * to)46 Err MakeTestOnlyError(const Item* from, const Item* to) {
47 return Err(
48 from->defined_from(), "Test-only dependency not allowed.",
49 from->label().GetUserVisibleName(false) +
50 "\n"
51 "which is NOT marked testonly can't depend on\n" +
52 to->label().GetUserVisibleName(false) +
53 "\n"
54 "which is marked testonly. Only targets with \"testonly = true\"\n"
55 "can depend on other test-only targets.\n"
56 "\n"
57 "Either mark it test-only or don't do this dependency.");
58 }
59
60 // Set check_private_deps to true for the first invocation since a target
61 // can see all of its dependencies. For recursive invocations this will be set
62 // to false to follow only public dependency paths.
63 //
64 // Pass a pointer to an empty set for the first invocation. This will be used
65 // to avoid duplicate checking.
66 //
67 // Checking of object files is optional because it is much slower. This allows
68 // us to check targets for normal outputs, and then as a second pass check
69 // object files (since we know it will be an error otherwise). This allows
70 // us to avoid computing all object file names in the common case.
EnsureFileIsGeneratedByDependency(const Target * target,const OutputFile & file,bool check_private_deps,bool consider_object_files,bool check_data_deps,TargetSet * seen_targets)71 bool EnsureFileIsGeneratedByDependency(const Target* target,
72 const OutputFile& file,
73 bool check_private_deps,
74 bool consider_object_files,
75 bool check_data_deps,
76 TargetSet* seen_targets) {
77 if (!seen_targets->add(target))
78 return false; // Already checked this one and it's not found.
79
80 // Assume that we have relatively few generated inputs so brute-force
81 // searching here is OK. If this becomes a bottleneck, consider storing
82 // computed_outputs as a hash set.
83 for (const OutputFile& cur : target->computed_outputs()) {
84 if (file == cur)
85 return true;
86 }
87
88 if (file == target->write_runtime_deps_output())
89 return true;
90
91 // Check binary target intermediate files if requested.
92 if (consider_object_files && target->IsBinary()) {
93 std::vector<OutputFile> source_outputs;
94 for (const SourceFile& source : target->sources()) {
95 const char* tool_name;
96 if (!target->GetOutputFilesForSource(source, &tool_name, &source_outputs))
97 continue;
98 if (base::ContainsValue(source_outputs, file))
99 return true;
100 }
101 }
102
103 if (check_data_deps) {
104 check_data_deps = false; // Consider only direct data_deps.
105 for (const auto& pair : target->data_deps()) {
106 if (EnsureFileIsGeneratedByDependency(pair.ptr, file, false,
107 consider_object_files,
108 check_data_deps, seen_targets))
109 return true; // Found a path.
110 }
111 }
112
113 // Check all public dependencies (don't do data ones since those are
114 // runtime-only).
115 for (const auto& pair : target->public_deps()) {
116 if (EnsureFileIsGeneratedByDependency(pair.ptr, file, false,
117 consider_object_files,
118 check_data_deps, seen_targets))
119 return true; // Found a path.
120 }
121
122 // Only check private deps if requested.
123 if (check_private_deps) {
124 for (const auto& pair : target->private_deps()) {
125 if (EnsureFileIsGeneratedByDependency(pair.ptr, file, false,
126 consider_object_files,
127 check_data_deps, seen_targets))
128 return true; // Found a path.
129 }
130 if (target->output_type() == Target::CREATE_BUNDLE) {
131 for (auto* dep : target->bundle_data().bundle_deps()) {
132 if (EnsureFileIsGeneratedByDependency(dep, file, false,
133 consider_object_files,
134 check_data_deps, seen_targets))
135 return true; // Found a path.
136 }
137 }
138 }
139 return false;
140 }
141
142 // check_this indicates if the given target should be matched against the
143 // patterns. It should be set to false for the first call since assert_no_deps
144 // shouldn't match the target itself.
145 //
146 // visited should point to an empty set, this will be used to prevent
147 // multiple visits.
148 //
149 // *failure_path_str will be filled with a string describing the path of the
150 // dependency failure, and failure_pattern will indicate the pattern in
151 // assert_no that matched the target.
152 //
153 // Returns true if everything is OK. failure_path_str and failure_pattern_index
154 // will be unchanged in this case.
RecursiveCheckAssertNoDeps(const Target * target,bool check_this,const std::vector<LabelPattern> & assert_no,TargetSet * visited,std::string * failure_path_str,const LabelPattern ** failure_pattern)155 bool RecursiveCheckAssertNoDeps(const Target* target,
156 bool check_this,
157 const std::vector<LabelPattern>& assert_no,
158 TargetSet* visited,
159 std::string* failure_path_str,
160 const LabelPattern** failure_pattern) {
161 static const char kIndentPath[] = " ";
162
163 if (!visited->add(target))
164 return true; // Already checked this target.
165
166 if (check_this) {
167 // Check this target against the given list of patterns.
168 for (const LabelPattern& pattern : assert_no) {
169 if (pattern.Matches(target->label())) {
170 // Found a match.
171 *failure_pattern = &pattern;
172 *failure_path_str =
173 kIndentPath + target->label().GetUserVisibleName(false);
174 return false;
175 }
176 }
177 }
178
179 // Recursively check dependencies.
180 for (const auto& pair : target->GetDeps(Target::DEPS_ALL)) {
181 if (pair.ptr->output_type() == Target::EXECUTABLE)
182 continue;
183 if (!RecursiveCheckAssertNoDeps(pair.ptr, true, assert_no, visited,
184 failure_path_str, failure_pattern)) {
185 // To reconstruct the path, prepend the current target to the error.
186 std::string prepend_path =
187 kIndentPath + target->label().GetUserVisibleName(false) + " ->\n";
188 failure_path_str->insert(0, prepend_path);
189 return false;
190 }
191 }
192
193 return true;
194 }
195
196 } // namespace
197
198 const char kExecution_Help[] =
199 R"(Build graph and execution overview
200
201 Overall build flow
202
203 1. Look for ".gn" file (see "gn help dotfile") in the current directory and
204 walk up the directory tree until one is found. Set this directory to be
205 the "source root" and interpret this file to find the name of the build
206 config file.
207
208 2. Execute the build config file identified by .gn to set up the global
209 variables and default toolchain name. Any arguments, variables, defaults,
210 etc. set up in this file will be visible to all files in the build.
211
212 3. Load the //BUILD.gn (in the source root directory).
213
214 4. Recursively evaluate rules and load BUILD.gn in other directories as
215 necessary to resolve dependencies. If a BUILD file isn't found in the
216 specified location, GN will look in the corresponding location inside
217 the secondary_source defined in the dotfile (see "gn help dotfile").
218
219 5. When a target's dependencies are resolved, write out the `.ninja`
220 file to disk.
221
222 6. When all targets are resolved, write out the root build.ninja file.
223
224 Note that the BUILD.gn file name may be modulated by .gn arguments such as
225 build_file_extension.
226
227 Executing target definitions and templates
228
229 Build files are loaded in parallel. This means it is impossible to
230 interrogate a target from GN code for any information not derivable from its
231 label (see "gn help label"). The exception is the get_target_outputs()
232 function which requires the target being interrogated to have been defined
233 previously in the same file.
234
235 Targets are declared by their type and given a name:
236
237 static_library("my_static_library") {
238 ... target parameter definitions ...
239 }
240
241 There is also a generic "target" function for programmatically defined types
242 (see "gn help target"). You can define new types using templates (see "gn
243 help template"). A template defines some custom code that expands to one or
244 more other targets.
245
246 Before executing the code inside the target's { }, the target defaults are
247 applied (see "gn help set_defaults"). It will inject implicit variable
248 definitions that can be overridden by the target code as necessary. Typically
249 this mechanism is used to inject a default set of configs that define the
250 global compiler and linker flags.
251
252 Which targets are built
253
254 All targets encountered in the default toolchain (see "gn help toolchain")
255 will have build rules generated for them, even if no other targets reference
256 them. Their dependencies must resolve and they will be added to the implicit
257 "all" rule (see "gn help ninja_rules").
258
259 Targets in non-default toolchains will only be generated when they are
260 required (directly or transitively) to build a target in the default
261 toolchain.
262
263 Some targets might be associated but without a formal build dependency (for
264 example, related tools or optional variants). A target that is marked as
265 "generated" can propagate its generated state to an associated target using
266 "gen_deps". This will make the referenced dependency have Ninja rules
267 generated in the same cases the source target has but without a build-time
268 dependency and even in non-default toolchains.
269
270 See also "gn help ninja_rules".
271
272 Dependencies
273
274 The only difference between "public_deps" and "deps" except for pushing
275 configs around the build tree and allowing includes for the purposes of "gn
276 check".
277
278 A target's "data_deps" are guaranteed to be built whenever the target is
279 built, but the ordering is not defined. The meaning of this is dependencies
280 required at runtime. Currently data deps will be complete before the target
281 is linked, but this is not semantically guaranteed and this is undesirable
282 from a build performance perspective. Since we hope to change this in the
283 future, do not rely on this behavior.
284 )";
285
Target(const Settings * settings,const Label & label,const SourceFileSet & build_dependency_files)286 Target::Target(const Settings* settings,
287 const Label& label,
288 const SourceFileSet& build_dependency_files)
289 : Item(settings, label, build_dependency_files) {}
290
291 Target::~Target() = default;
292
293 // A technical note on accessors defined below: Using a static global
294 // constant is much faster at runtime than using a static local one.
295 //
296 // In other words:
297 //
298 // static const Foo kEmptyFoo;
299 //
300 // const Foo& Target::foo() const {
301 // return foo_ ? *foo_ : kEmptyFoo;
302 // }
303 //
304 // Is considerably faster than:
305 //
306 // const Foo& Target::foo() const {
307 // if (foo_) {
308 // return *foo_;
309 // } else {
310 // static const Foo kEmptyFoo;
311 // return kEmptyFoo;
312 // }
313 // }
314 //
315 // Because the latter requires relatively expensive atomic operations
316 // in the second branch.
317 //
318
319 static const BundleData kEmptyBundleData;
320
bundle_data() const321 const BundleData& Target::bundle_data() const {
322 return bundle_data_ ? *bundle_data_ : kEmptyBundleData;
323 }
324
bundle_data()325 BundleData& Target::bundle_data() {
326 if (!bundle_data_)
327 bundle_data_ = std::make_unique<BundleData>();
328 return *bundle_data_;
329 }
330
331 static ConfigValues kEmptyConfigValues;
332
config_values() const333 const ConfigValues& Target::config_values() const {
334 return config_values_ ? *config_values_ : kEmptyConfigValues;
335 }
336
config_values()337 ConfigValues& Target::config_values() {
338 if (!config_values_)
339 config_values_ = std::make_unique<ConfigValues>();
340 return *config_values_;
341 }
342
343 static const ActionValues kEmptyActionValues;
344
action_values() const345 const ActionValues& Target::action_values() const {
346 return action_values_ ? *action_values_ : kEmptyActionValues;
347 }
348
action_values()349 ActionValues& Target::action_values() {
350 if (!action_values_)
351 action_values_ = std::make_unique<ActionValues>();
352 return *action_values_;
353 }
354
355 static const RustValues kEmptyRustValues;
356
rust_values() const357 const RustValues& Target::rust_values() const {
358 return rust_values_ ? *rust_values_ : kEmptyRustValues;
359 }
360
rust_values()361 RustValues& Target::rust_values() {
362 if (!rust_values_)
363 rust_values_ = std::make_unique<RustValues>();
364 return *rust_values_;
365 }
366
367 static const SwiftValues kEmptySwiftValues;
368
swift_values() const369 const SwiftValues& Target::swift_values() const {
370 return swift_values_ ? *swift_values_ : kEmptySwiftValues;
371 }
372
swift_values()373 SwiftValues& Target::swift_values() {
374 if (!swift_values_)
375 swift_values_ = std::make_unique<SwiftValues>();
376 return *swift_values_;
377 }
378
379 static const Metadata kEmptyMetadata;
380
metadata() const381 const Metadata& Target::metadata() const {
382 return metadata_ ? *metadata_ : kEmptyMetadata;
383 }
384
metadata()385 Metadata& Target::metadata() {
386 if (!metadata_)
387 metadata_ = std::make_unique<Metadata>();
388 return *metadata_;
389 }
390
391 static const Target::GeneratedFile kEmptyGeneratedFile;
392
generated_file() const393 const Target::GeneratedFile& Target::generated_file() const {
394 return generated_file_ ? *generated_file_ : kEmptyGeneratedFile;
395 }
396
generated_file()397 Target::GeneratedFile& Target::generated_file() {
398 if (!generated_file_)
399 generated_file_ = std::make_unique<Target::GeneratedFile>();
400 return *generated_file_;
401 }
402
403 // static
GetStringForOutputType(OutputType type)404 const char* Target::GetStringForOutputType(OutputType type) {
405 switch (type) {
406 case UNKNOWN:
407 return "unknown";
408 case GROUP:
409 return functions::kGroup;
410 case EXECUTABLE:
411 return functions::kExecutable;
412 case LOADABLE_MODULE:
413 return functions::kLoadableModule;
414 case SHARED_LIBRARY:
415 return functions::kSharedLibrary;
416 case STATIC_LIBRARY:
417 return functions::kStaticLibrary;
418 case SOURCE_SET:
419 return functions::kSourceSet;
420 case COPY_FILES:
421 return functions::kCopy;
422 case ACTION:
423 return functions::kAction;
424 case ACTION_FOREACH:
425 return functions::kActionForEach;
426 case BUNDLE_DATA:
427 return functions::kBundleData;
428 case CREATE_BUNDLE:
429 return functions::kCreateBundle;
430 case GENERATED_FILE:
431 return functions::kGeneratedFile;
432 case RUST_LIBRARY:
433 return functions::kRustLibrary;
434 case RUST_PROC_MACRO:
435 return functions::kRustProcMacro;
436 default:
437 return "";
438 }
439 }
440
AsTarget()441 Target* Target::AsTarget() {
442 return this;
443 }
444
AsTarget() const445 const Target* Target::AsTarget() const {
446 return this;
447 }
448
OnResolved(Err * err)449 bool Target::OnResolved(Err* err) {
450 DCHECK(output_type_ != UNKNOWN);
451 DCHECK(toolchain_) << "Toolchain should have been set before resolving.";
452
453 ScopedTrace trace(TraceItem::TRACE_ON_RESOLVED, label());
454 trace.SetToolchain(settings()->toolchain_label());
455
456 // Copy this target's own dependent and public configs to the list of configs
457 // applying to it.
458 configs_.Append(all_dependent_configs_.begin(), all_dependent_configs_.end());
459 MergePublicConfigsFrom(this, &configs_);
460
461 // Check visibility for just this target's own configs, before dependents are
462 // added, but after public_configs and all_dependent_configs are merged.
463 if (!CheckConfigVisibility(err))
464 return false;
465
466 // Copy public configs from all dependencies into the list of configs
467 // applying to this target (configs_).
468 PullDependentTargetConfigs();
469
470 // Copies public dependencies' public configs to this target's public
471 // configs. These configs have already been applied to this target by
472 // PullDependentTargetConfigs above, along with the public configs from
473 // private deps. This step re-exports them as public configs for targets that
474 // depend on this one.
475 for (const auto& dep : public_deps_) {
476 if (dep.ptr->toolchain() == toolchain() ||
477 dep.ptr->toolchain()->propagates_configs())
478 public_configs_.Append(dep.ptr->public_configs().begin(),
479 dep.ptr->public_configs().end());
480 }
481
482 // Copy our own libs and lib_dirs to the final set. This will be from our
483 // target and all of our configs. We do this specially since these must be
484 // inherited through the dependency tree (other flags don't work this way).
485 //
486 // This needs to happen after we pull dependent target configs for the
487 // public config's libs to be included here. And it needs to happen
488 // before pulling the dependent target libs so the libs are in the correct
489 // order (local ones first, then the dependency's).
490 for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) {
491 const ConfigValues& cur = iter.cur();
492 all_lib_dirs_.Append(cur.lib_dirs().begin(), cur.lib_dirs().end());
493 all_libs_.Append(cur.libs().begin(), cur.libs().end());
494
495 all_framework_dirs_.Append(cur.framework_dirs().begin(),
496 cur.framework_dirs().end());
497 all_frameworks_.Append(cur.frameworks().begin(), cur.frameworks().end());
498 all_weak_frameworks_.Append(cur.weak_frameworks().begin(),
499 cur.weak_frameworks().end());
500 }
501
502 PullRecursiveBundleData();
503 PullDependentTargetLibs();
504 PullRecursiveHardDeps();
505 if (!ResolvePrecompiledHeaders(err))
506 return false;
507
508 if (!FillOutputFiles(err))
509 return false;
510
511 if (!SwiftValues::OnTargetResolved(this, err))
512 return false;
513
514 if (!CheckSourceSetLanguages(err))
515 return false;
516 if (!CheckVisibility(err))
517 return false;
518 if (!CheckTestonly(err))
519 return false;
520 if (!CheckAssertNoDeps(err))
521 return false;
522 CheckSourcesGenerated();
523
524 if (!write_runtime_deps_output_.value().empty())
525 g_scheduler->AddWriteRuntimeDepsTarget(this);
526
527 if (output_type_ == GENERATED_FILE) {
528 DCHECK(!computed_outputs_.empty());
529 g_scheduler->AddGeneratedFile(
530 computed_outputs_[0].AsSourceFile(settings()->build_settings()));
531 }
532
533 return true;
534 }
535
IsBinary() const536 bool Target::IsBinary() const {
537 return output_type_ == EXECUTABLE || output_type_ == SHARED_LIBRARY ||
538 output_type_ == LOADABLE_MODULE || output_type_ == STATIC_LIBRARY ||
539 output_type_ == SOURCE_SET || output_type_ == RUST_LIBRARY ||
540 output_type_ == RUST_PROC_MACRO;
541 }
542
IsLinkable() const543 bool Target::IsLinkable() const {
544 return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY ||
545 output_type_ == RUST_LIBRARY || output_type_ == RUST_PROC_MACRO;
546 }
547
IsFinal() const548 bool Target::IsFinal() const {
549 return output_type_ == EXECUTABLE || output_type_ == SHARED_LIBRARY ||
550 output_type_ == LOADABLE_MODULE || output_type_ == ACTION ||
551 output_type_ == ACTION_FOREACH || output_type_ == COPY_FILES ||
552 output_type_ == CREATE_BUNDLE || output_type_ == RUST_PROC_MACRO ||
553 (output_type_ == STATIC_LIBRARY && complete_static_lib_);
554 }
555
IsDataOnly() const556 bool Target::IsDataOnly() const {
557 // BUNDLE_DATA exists only to declare inputs to subsequent CREATE_BUNDLE
558 // targets. Changing only contents of the bundle data target should not cause
559 // a binary to be re-linked. It should affect only the CREATE_BUNDLE steps
560 // instead. As a result, normal targets should treat this as a data
561 // dependency.
562 return output_type_ == BUNDLE_DATA;
563 }
564
GetDeps(DepsIterationType type) const565 DepsIteratorRange Target::GetDeps(DepsIterationType type) const {
566 if (type == DEPS_LINKED) {
567 return DepsIteratorRange(
568 DepsIterator(&public_deps_, &private_deps_, nullptr));
569 }
570 // All deps.
571 return DepsIteratorRange(
572 DepsIterator(&public_deps_, &private_deps_, &data_deps_));
573 }
574
GetComputedOutputName() const575 std::string Target::GetComputedOutputName() const {
576 DCHECK(toolchain_)
577 << "Toolchain must be specified before getting the computed output name.";
578
579 const std::string& name =
580 output_name_.empty() ? label().name() : output_name_;
581
582 std::string result;
583 const Tool* tool = toolchain_->GetToolForTargetFinalOutput(this);
584 if (tool) {
585 // Only add the prefix if the name doesn't already have it and it's not
586 // being overridden.
587 if (!output_prefix_override_ &&
588 !base::StartsWith(name, tool->output_prefix(),
589 base::CompareCase::SENSITIVE))
590 result = tool->output_prefix();
591 }
592 result.append(name);
593 return result;
594 }
595
SetToolchain(const Toolchain * toolchain,Err * err)596 bool Target::SetToolchain(const Toolchain* toolchain, Err* err) {
597 DCHECK(!toolchain_);
598 DCHECK_NE(UNKNOWN, output_type_);
599 toolchain_ = toolchain;
600
601 const Tool* tool = toolchain->GetToolForTargetFinalOutput(this);
602 if (tool)
603 return true;
604
605 // Tool not specified for this target type.
606 if (err) {
607 *err =
608 Err(defined_from(), "This target uses an undefined tool.",
609 base::StringPrintf(
610 "The target %s\n"
611 "of type \"%s\"\n"
612 "uses toolchain %s\n"
613 "which doesn't have the tool \"%s\" defined.\n\n"
614 "Alas, I can not continue.",
615 label().GetUserVisibleName(false).c_str(),
616 GetStringForOutputType(output_type_),
617 label().GetToolchainLabel().GetUserVisibleName(false).c_str(),
618 Tool::GetToolTypeForTargetFinalOutput(this)));
619 }
620 return false;
621 }
622
GetOutputsAsSourceFiles(const LocationRange & loc_for_error,bool build_complete,std::vector<SourceFile> * outputs,Err * err) const623 bool Target::GetOutputsAsSourceFiles(const LocationRange& loc_for_error,
624 bool build_complete,
625 std::vector<SourceFile>* outputs,
626 Err* err) const {
627 const static char kBuildIncompleteMsg[] =
628 "This target is a binary target which can't be queried for its "
629 "outputs\nduring the build. It will work for action, action_foreach, "
630 "generated_file,\nand copy targets.";
631
632 outputs->clear();
633
634 std::vector<SourceFile> files;
635 if (output_type() == Target::ACTION || output_type() == Target::COPY_FILES ||
636 output_type() == Target::ACTION_FOREACH ||
637 output_type() == Target::GENERATED_FILE) {
638 action_values().GetOutputsAsSourceFiles(this, outputs);
639 } else if (output_type() == Target::CREATE_BUNDLE) {
640 if (!bundle_data().GetOutputsAsSourceFiles(settings(), this, outputs, err))
641 return false;
642 } else if (IsBinary() && output_type() != Target::SOURCE_SET) {
643 // Binary target with normal outputs (source sets have stamp outputs like
644 // groups).
645 DCHECK(IsBinary()) << static_cast<int>(output_type());
646 if (!build_complete) {
647 // Can't access the toolchain for a target before the build is complete.
648 // Otherwise it will race with loading and setting the toolchain
649 // definition.
650 *err = Err(loc_for_error, kBuildIncompleteMsg);
651 return false;
652 }
653
654 const Tool* tool = toolchain()->GetToolForTargetFinalOutput(this);
655
656 std::vector<OutputFile> output_files;
657 SubstitutionWriter::ApplyListToLinkerAsOutputFile(
658 this, tool, tool->outputs(), &output_files);
659 for (const OutputFile& output_file : output_files) {
660 outputs->push_back(
661 output_file.AsSourceFile(settings()->build_settings()));
662 }
663 } else {
664 // Everything else (like a group or bundle_data) has a stamp output. The
665 // dependency output file should have computed what this is. This won't be
666 // valid unless the build is complete.
667 if (!build_complete) {
668 *err = Err(loc_for_error, kBuildIncompleteMsg);
669 return false;
670 }
671 outputs->push_back(
672 dependency_output_file().AsSourceFile(settings()->build_settings()));
673 }
674 return true;
675 }
676
GetOutputFilesForSource(const SourceFile & source,const char ** computed_tool_type,std::vector<OutputFile> * outputs) const677 bool Target::GetOutputFilesForSource(const SourceFile& source,
678 const char** computed_tool_type,
679 std::vector<OutputFile>* outputs) const {
680 DCHECK(toolchain()); // Should be resolved before calling.
681
682 outputs->clear();
683 *computed_tool_type = Tool::kToolNone;
684
685 if (output_type() == Target::COPY_FILES ||
686 output_type() == Target::ACTION_FOREACH) {
687 // These target types apply the output pattern to the input.
688 std::vector<SourceFile> output_files;
689 SubstitutionWriter::ApplyListToSourceAsOutputFile(
690 this, settings(), action_values().outputs(), source, outputs);
691 } else if (!IsBinary()) {
692 // All other non-binary target types just return the target outputs. We
693 // don't know if the build is complete and it doesn't matter for non-binary
694 // targets, so just assume it's not and pass "false".
695 std::vector<SourceFile> outputs_as_source_files;
696 Err err; // We can ignore the error and return empty for failure.
697 GetOutputsAsSourceFiles(LocationRange(), false, &outputs_as_source_files,
698 &err);
699
700 // Convert to output files.
701 for (const auto& cur : outputs_as_source_files)
702 outputs->emplace_back(OutputFile(settings()->build_settings(), cur));
703 } else {
704 // All binary targets do a tool lookup.
705 DCHECK(IsBinary());
706
707 const SourceFile::Type file_type = source.GetType();
708 if (file_type == SourceFile::SOURCE_UNKNOWN)
709 return false;
710 if (file_type == SourceFile::SOURCE_O) {
711 // Object files just get passed to the output and not compiled.
712 outputs->emplace_back(OutputFile(settings()->build_settings(), source));
713 return true;
714 }
715
716 // Rust generates on a module level, not source.
717 if (file_type == SourceFile::SOURCE_RS)
718 return false;
719
720 *computed_tool_type = Tool::GetToolTypeForSourceType(file_type);
721 if (*computed_tool_type == Tool::kToolNone)
722 return false; // No tool for this file (it's a header file or something).
723 const Tool* tool = toolchain_->GetTool(*computed_tool_type);
724 if (!tool)
725 return false; // Tool does not apply for this toolchain.file.
726
727 // Swift may generate on a module or source level.
728 if (file_type == SourceFile::SOURCE_SWIFT) {
729 if (tool->partial_outputs().list().empty())
730 return false;
731 }
732
733 const SubstitutionList& substitution_list =
734 file_type == SourceFile::SOURCE_SWIFT ? tool->partial_outputs()
735 : tool->outputs();
736
737 // Figure out what output(s) this compiler produces.
738 SubstitutionWriter::ApplyListToCompilerAsOutputFile(
739 this, source, substitution_list, outputs);
740 }
741 return !outputs->empty();
742 }
743
PullDependentTargetConfigs()744 void Target::PullDependentTargetConfigs() {
745 for (const auto& pair : GetDeps(DEPS_LINKED)) {
746 if (pair.ptr->toolchain() == toolchain() ||
747 pair.ptr->toolchain()->propagates_configs())
748 MergeAllDependentConfigsFrom(pair.ptr, &configs_,
749 &all_dependent_configs_);
750 }
751 for (const auto& pair : GetDeps(DEPS_LINKED)) {
752 if (pair.ptr->toolchain() == toolchain() ||
753 pair.ptr->toolchain()->propagates_configs())
754 MergePublicConfigsFrom(pair.ptr, &configs_);
755 }
756 }
757
PullDependentTargetLibsFrom(const Target * dep,bool is_public)758 void Target::PullDependentTargetLibsFrom(const Target* dep, bool is_public) {
759 // Direct dependent libraries.
760 if (dep->output_type() == STATIC_LIBRARY ||
761 dep->output_type() == SHARED_LIBRARY ||
762 dep->output_type() == RUST_LIBRARY ||
763 dep->output_type() == SOURCE_SET ||
764 (dep->output_type() == CREATE_BUNDLE &&
765 dep->bundle_data().is_framework())) {
766 inherited_libraries_.Append(dep, is_public);
767 }
768
769 // Collect Rust libraries that are accessible from the current target, or
770 // transitively part of the current target.
771 if (dep->output_type() == STATIC_LIBRARY ||
772 dep->output_type() == SHARED_LIBRARY ||
773 dep->output_type() == SOURCE_SET || dep->output_type() == RUST_LIBRARY ||
774 dep->output_type() == GROUP) {
775 // Here we have: `this` --[depends-on]--> `dep`
776 //
777 // The `this` target has direct access to `dep` since its a direct
778 // dependency, regardless of the edge being a public_dep or not, so we pass
779 // true for public-ness. Whereas, anything depending on `this` can only gain
780 // direct access to `dep` if the edge between `this` and `dep` is public, so
781 // we pass `is_public`.
782 //
783 // TODO(danakj): We should only need to track Rust rlibs or dylibs here, as
784 // it's used for passing to rustc with --extern. We currently track
785 // everything then drop non-Rust libs in ninja_rust_binary_target_writer.cc.
786 rust_transitive_inherited_libs_.Append(dep, true);
787 rust_transitive_inheritable_libs_.Append(dep, is_public);
788
789 rust_transitive_inherited_libs_.AppendInherited(
790 dep->rust_transitive_inheritable_libs(), true);
791 rust_transitive_inheritable_libs_.AppendInherited(
792 dep->rust_transitive_inheritable_libs(), is_public);
793 } else if (dep->output_type() == RUST_PROC_MACRO) {
794 // Proc-macros are inherited as a transitive dependency, but the things they
795 // depend on can't be used elsewhere, as the proc macro is not linked into
796 // the target (as it's only used during compilation).
797 rust_transitive_inherited_libs_.Append(dep, true);
798 rust_transitive_inheritable_libs_.Append(dep, is_public);
799 }
800
801 if (dep->output_type() == SHARED_LIBRARY) {
802 // Shared library dependendencies are inherited across public shared
803 // library boundaries.
804 //
805 // In this case:
806 // EXE -> INTERMEDIATE_SHLIB --[public]--> FINAL_SHLIB
807 // The EXE will also link to to FINAL_SHLIB. The public dependency means
808 // that the EXE can use the headers in FINAL_SHLIB so the FINAL_SHLIB
809 // will need to appear on EXE's link line.
810 //
811 // However, if the dependency is private:
812 // EXE -> INTERMEDIATE_SHLIB --[private]--> FINAL_SHLIB
813 // the dependency will not be propagated because INTERMEDIATE_SHLIB is
814 // not granting permission to call functions from FINAL_SHLIB. If EXE
815 // wants to use functions (and link to) FINAL_SHLIB, it will need to do
816 // so explicitly.
817 //
818 // Static libraries and source sets aren't inherited across shared
819 // library boundaries because they will be linked into the shared
820 // library. Rust dylib deps are handled above and transitive deps are
821 // resolved by the compiler.
822 inherited_libraries_.AppendPublicSharedLibraries(dep->inherited_libraries(),
823 is_public);
824 } else {
825 InheritedLibraries transitive;
826
827 if (!dep->IsFinal()) {
828 // The current target isn't linked, so propagate linked deps and
829 // libraries up the dependency tree.
830 for (const auto& [inherited, inherited_is_public] :
831 dep->inherited_libraries().GetOrderedAndPublicFlag()) {
832 transitive.Append(inherited, is_public && inherited_is_public);
833 }
834 } else if (dep->complete_static_lib()) {
835 // Inherit only final targets through _complete_ static libraries.
836 //
837 // Inherited final libraries aren't linked into complete static libraries.
838 // They are forwarded here so that targets that depend on complete
839 // static libraries can link them in. Conversely, since complete static
840 // libraries link in non-final targets they shouldn't be inherited.
841 for (const auto& [inherited, inherited_is_public] :
842 dep->inherited_libraries().GetOrderedAndPublicFlag()) {
843 if (inherited->IsFinal()) {
844 transitive.Append(inherited, is_public && inherited_is_public);
845 }
846 }
847 }
848
849 for (const auto& [target, pub] : transitive.GetOrderedAndPublicFlag()) {
850 // Proc macros are not linked into targets that depend on them, so do not
851 // get inherited; they are consumed by the Rust compiler and only need to
852 // be specified in --extern.
853 if (target->output_type() != RUST_PROC_MACRO) {
854 inherited_libraries_.Append(target, pub);
855 }
856 }
857 }
858
859 // Library settings are always inherited across static library boundaries.
860 if (!dep->IsFinal() || dep->output_type() == STATIC_LIBRARY) {
861 all_lib_dirs_.Append(dep->all_lib_dirs());
862 all_libs_.Append(dep->all_libs());
863
864 all_framework_dirs_.Append(dep->all_framework_dirs());
865 all_frameworks_.Append(dep->all_frameworks());
866 all_weak_frameworks_.Append(dep->all_weak_frameworks());
867 }
868 }
869
PullDependentTargetLibs()870 void Target::PullDependentTargetLibs() {
871 for (const auto& dep : public_deps_)
872 PullDependentTargetLibsFrom(dep.ptr, true);
873 for (const auto& dep : private_deps_)
874 PullDependentTargetLibsFrom(dep.ptr, false);
875 }
876
PullRecursiveHardDeps()877 void Target::PullRecursiveHardDeps() {
878 for (const auto& pair : GetDeps(DEPS_LINKED)) {
879 // Direct hard dependencies.
880 if (hard_dep() || pair.ptr->hard_dep()) {
881 recursive_hard_deps_.insert(pair.ptr);
882 continue;
883 }
884
885 // If |pair.ptr| is binary target and |pair.ptr| has no public header,
886 // |this| target does not need to have |pair.ptr|'s hard_deps as its
887 // hard_deps to start compiles earlier. Unless the target compiles a
888 // Swift module (since they also generate a header that can be used
889 // by the current target).
890 if (pair.ptr->IsBinary() && !pair.ptr->all_headers_public() &&
891 pair.ptr->public_headers().empty() &&
892 !pair.ptr->builds_swift_module()) {
893 continue;
894 }
895
896 // Recursive hard dependencies of all dependencies.
897 recursive_hard_deps_.insert(pair.ptr->recursive_hard_deps().begin(),
898 pair.ptr->recursive_hard_deps().end());
899 }
900 }
901
PullRecursiveBundleData()902 void Target::PullRecursiveBundleData() {
903 for (const auto& pair : GetDeps(DEPS_LINKED)) {
904 // Don't propagate bundle_data once they are added to a bundle.
905 if (pair.ptr->output_type() == CREATE_BUNDLE)
906 continue;
907
908 // Don't propagate across toolchain.
909 if (pair.ptr->toolchain() != toolchain())
910 continue;
911
912 // Direct dependency on a bundle_data target.
913 if (pair.ptr->output_type() == BUNDLE_DATA) {
914 bundle_data().AddBundleData(pair.ptr);
915 }
916
917 // Recursive bundle_data informations from all dependencies.
918 if (pair.ptr->has_bundle_data()) {
919 for (auto* target : pair.ptr->bundle_data().bundle_deps())
920 bundle_data().AddBundleData(target);
921 }
922 }
923
924 if (has_bundle_data())
925 bundle_data().OnTargetResolved(this);
926 }
927
FillOutputFiles(Err * err)928 bool Target::FillOutputFiles(Err* err) {
929 const Tool* tool = toolchain_->GetToolForTargetFinalOutput(this);
930 bool check_tool_outputs = false;
931 switch (output_type_) {
932 case GROUP:
933 case BUNDLE_DATA:
934 case CREATE_BUNDLE:
935 case SOURCE_SET:
936 case COPY_FILES:
937 case ACTION:
938 case ACTION_FOREACH:
939 case GENERATED_FILE: {
940 // These don't get linked to and use stamps which should be the first
941 // entry in the outputs. These stamps are named
942 // "<target_out_dir>/<targetname>.stamp". Setting "output_name" does not
943 // affect the stamp file name: it is always based on the original target
944 // name.
945 dependency_output_file_ =
946 GetBuildDirForTargetAsOutputFile(this, BuildDirType::OBJ);
947 dependency_output_file_.value().append(label().name());
948 dependency_output_file_.value().append(".stamp");
949 break;
950 }
951 case EXECUTABLE:
952 case LOADABLE_MODULE:
953 // Executables and loadable modules don't get linked to, but the first
954 // output is used for dependency management.
955 CHECK_GE(tool->outputs().list().size(), 1u);
956 check_tool_outputs = true;
957 dependency_output_file_ =
958 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
959 this, tool, tool->outputs().list()[0]);
960
961 if (tool->runtime_outputs().list().empty()) {
962 // Default to the first output for the runtime output.
963 runtime_outputs_.push_back(dependency_output_file_);
964 } else {
965 SubstitutionWriter::ApplyListToLinkerAsOutputFile(
966 this, tool, tool->runtime_outputs(), &runtime_outputs_);
967 }
968 break;
969 case RUST_LIBRARY:
970 case STATIC_LIBRARY:
971 // Static libraries both have dependencies and linking going off of the
972 // first output.
973 CHECK(tool->outputs().list().size() >= 1);
974 check_tool_outputs = true;
975 link_output_file_ = dependency_output_file_ =
976 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
977 this, tool, tool->outputs().list()[0]);
978 break;
979 case RUST_PROC_MACRO:
980 case SHARED_LIBRARY:
981 CHECK(tool->outputs().list().size() >= 1);
982 check_tool_outputs = true;
983 if (const CTool* ctool = tool->AsC()) {
984 if (ctool->link_output().empty() && ctool->depend_output().empty()) {
985 // Default behavior, use the first output file for both.
986 link_output_file_ = dependency_output_file_ =
987 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
988 this, tool, tool->outputs().list()[0]);
989 } else {
990 // Use the tool-specified ones.
991 if (!ctool->link_output().empty()) {
992 link_output_file_ =
993 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
994 this, tool, ctool->link_output());
995 }
996 if (!ctool->depend_output().empty()) {
997 dependency_output_file_ =
998 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
999 this, tool, ctool->depend_output());
1000 }
1001 }
1002 if (tool->runtime_outputs().list().empty()) {
1003 // Default to the link output for the runtime output.
1004 runtime_outputs_.push_back(link_output_file_);
1005 } else {
1006 SubstitutionWriter::ApplyListToLinkerAsOutputFile(
1007 this, tool, tool->runtime_outputs(), &runtime_outputs_);
1008 }
1009 } else if (tool->AsRust()) {
1010 // Default behavior, use the first output file for both.
1011 link_output_file_ = dependency_output_file_ =
1012 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
1013 this, tool, tool->outputs().list()[0]);
1014 }
1015 break;
1016 case UNKNOWN:
1017 default:
1018 NOTREACHED();
1019 }
1020
1021 // Count anything generated from bundle_data dependencies.
1022 if (output_type_ == CREATE_BUNDLE) {
1023 if (!bundle_data().GetOutputFiles(settings(), this, &computed_outputs_,
1024 err))
1025 return false;
1026 }
1027
1028 // Count all outputs from this tool as something generated by this target.
1029 if (check_tool_outputs) {
1030 SubstitutionWriter::ApplyListToLinkerAsOutputFile(
1031 this, tool, tool->outputs(), &computed_outputs_);
1032
1033 // Output names aren't canonicalized in the same way that source files
1034 // are. For example, the tool outputs often use
1035 // {{some_var}}/{{output_name}} which expands to "./foo", but this won't
1036 // match "foo" which is what we'll compute when converting a SourceFile to
1037 // an OutputFile.
1038 for (auto& out : computed_outputs_)
1039 NormalizePath(&out.value());
1040 }
1041
1042 // Also count anything the target has declared to be an output.
1043 if (action_values_.get()) {
1044 std::vector<SourceFile> outputs_as_sources;
1045 action_values_->GetOutputsAsSourceFiles(this, &outputs_as_sources);
1046 for (const SourceFile& out : outputs_as_sources)
1047 computed_outputs_.push_back(
1048 OutputFile(settings()->build_settings(), out));
1049 }
1050
1051 return true;
1052 }
1053
ResolvePrecompiledHeaders(Err * err)1054 bool Target::ResolvePrecompiledHeaders(Err* err) {
1055 // Precompiled headers are stored on a ConfigValues struct. This way, the
1056 // build can set all the precompiled header settings in a config and apply
1057 // it to many targets. Likewise, the precompiled header values may be
1058 // specified directly on a target.
1059 //
1060 // Unlike other values on configs which are lists that just get concatenated,
1061 // the precompiled header settings are unique values. We allow them to be
1062 // specified anywhere, but if they are specified in more than one place all
1063 // places must match.
1064
1065 // Track where the current settings came from for issuing errors.
1066 bool has_precompiled_headers =
1067 config_values_.get() && config_values_->has_precompiled_headers();
1068 const Label* pch_header_settings_from = NULL;
1069 if (has_precompiled_headers)
1070 pch_header_settings_from = &label();
1071
1072 for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) {
1073 if (!iter.GetCurrentConfig())
1074 continue; // Skip the one on the target itself.
1075
1076 const Config* config = iter.GetCurrentConfig();
1077 const ConfigValues& cur = config->resolved_values();
1078 if (!cur.has_precompiled_headers())
1079 continue; // This one has no precompiled header info, skip.
1080
1081 if (has_precompiled_headers) {
1082 // Already have a precompiled header values, the settings must match.
1083 if (config_values_->precompiled_header() != cur.precompiled_header() ||
1084 config_values_->precompiled_source() != cur.precompiled_source()) {
1085 *err = Err(
1086 defined_from(), "Precompiled header setting conflict.",
1087 "The target " + label().GetUserVisibleName(false) +
1088 "\n"
1089 "has conflicting precompiled header settings.\n"
1090 "\n"
1091 "From " +
1092 pch_header_settings_from->GetUserVisibleName(false) +
1093 "\n header: " + config_values_->precompiled_header() +
1094 "\n source: " + config_values_->precompiled_source().value() +
1095 "\n\n"
1096 "From " +
1097 config->label().GetUserVisibleName(false) +
1098 "\n header: " + cur.precompiled_header() +
1099 "\n source: " + cur.precompiled_source().value());
1100 return false;
1101 }
1102 } else {
1103 // Have settings from a config, apply them to ourselves.
1104 pch_header_settings_from = &config->label();
1105 config_values().set_precompiled_header(cur.precompiled_header());
1106 config_values().set_precompiled_source(cur.precompiled_source());
1107 }
1108 }
1109
1110 return true;
1111 }
1112
CheckVisibility(Err * err) const1113 bool Target::CheckVisibility(Err* err) const {
1114 for (const auto& pair : GetDeps(DEPS_ALL)) {
1115 if (!Visibility::CheckItemVisibility(this, pair.ptr, err))
1116 return false;
1117 }
1118 return true;
1119 }
1120
CheckConfigVisibility(Err * err) const1121 bool Target::CheckConfigVisibility(Err* err) const {
1122 for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) {
1123 if (const Config* config = iter.GetCurrentConfig())
1124 if (!Visibility::CheckItemVisibility(this, config, err))
1125 return false;
1126 }
1127 return true;
1128 }
1129
CheckSourceSetLanguages(Err * err) const1130 bool Target::CheckSourceSetLanguages(Err* err) const {
1131 if (output_type() == Target::SOURCE_SET &&
1132 source_types_used().RustSourceUsed()) {
1133 *err = Err(defined_from(), "source_set contained Rust code.",
1134 label().GetUserVisibleName(false) +
1135 " has Rust code. Only C/C++ source_sets are supported.");
1136 return false;
1137 }
1138 return true;
1139 }
1140
CheckTestonly(Err * err) const1141 bool Target::CheckTestonly(Err* err) const {
1142 // If the current target is marked testonly, it can include both testonly
1143 // and non-testonly targets, so there's nothing to check.
1144 if (testonly())
1145 return true;
1146
1147 // Verify no deps have "testonly" set.
1148 for (const auto& pair : GetDeps(DEPS_ALL)) {
1149 if (pair.ptr->testonly()) {
1150 *err = MakeTestOnlyError(this, pair.ptr);
1151 return false;
1152 }
1153 }
1154
1155 // Verify no configs have "testonly" set.
1156 for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) {
1157 if (const Config* config = iter.GetCurrentConfig()) {
1158 if (config->testonly()) {
1159 *err = MakeTestOnlyError(this, config);
1160 return false;
1161 }
1162 }
1163 }
1164
1165 return true;
1166 }
1167
CheckAssertNoDeps(Err * err) const1168 bool Target::CheckAssertNoDeps(Err* err) const {
1169 if (assert_no_deps_.empty())
1170 return true;
1171
1172 TargetSet visited;
1173 std::string failure_path_str;
1174 const LabelPattern* failure_pattern = nullptr;
1175
1176 if (!RecursiveCheckAssertNoDeps(this, false, assert_no_deps_, &visited,
1177 &failure_path_str, &failure_pattern)) {
1178 *err = Err(
1179 defined_from(), "assert_no_deps failed.",
1180 label().GetUserVisibleName(false) +
1181 " has an assert_no_deps entry:\n " + failure_pattern->Describe() +
1182 "\nwhich fails for the dependency path:\n" + failure_path_str);
1183 return false;
1184 }
1185 return true;
1186 }
1187
CheckSourcesGenerated() const1188 void Target::CheckSourcesGenerated() const {
1189 // Checks that any inputs or sources to this target that are in the build
1190 // directory are generated by a target that this one transitively depends on
1191 // in some way. We already guarantee that all generated files are written
1192 // to the build dir.
1193 //
1194 // See Scheduler::AddUnknownGeneratedInput's declaration for more.
1195 for (const SourceFile& file : sources_)
1196 CheckSourceGenerated(file);
1197 for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) {
1198 for (const SourceFile& file : iter.cur().inputs())
1199 CheckSourceGenerated(file);
1200 }
1201 // TODO(agrieve): Check all_libs_ here as well (those that are source files).
1202 // http://crbug.com/571731
1203 }
1204
CheckSourceGenerated(const SourceFile & source) const1205 void Target::CheckSourceGenerated(const SourceFile& source) const {
1206 if (!IsStringInOutputDir(settings()->build_settings()->build_dir(),
1207 source.value()))
1208 return; // Not in output dir, this is OK.
1209
1210 // Tell the scheduler about unknown files. This will be noted for later so
1211 // the list of files written by the GN build itself (often response files)
1212 // can be filtered out of this list.
1213 OutputFile out_file(settings()->build_settings(), source);
1214 TargetSet seen_targets;
1215 bool check_data_deps = false;
1216 bool consider_object_files = false;
1217 if (!EnsureFileIsGeneratedByDependency(this, out_file, true,
1218 consider_object_files, check_data_deps,
1219 &seen_targets)) {
1220 seen_targets.clear();
1221 // Allow dependency to be through data_deps for files generated by gn.
1222 check_data_deps =
1223 g_scheduler->IsFileGeneratedByWriteRuntimeDeps(out_file) ||
1224 g_scheduler->IsFileGeneratedByTarget(source);
1225 // Check object files (much slower and very rare) only if the "normal"
1226 // output check failed.
1227 consider_object_files = !check_data_deps;
1228 if (!EnsureFileIsGeneratedByDependency(this, out_file, true,
1229 consider_object_files,
1230 check_data_deps, &seen_targets))
1231 g_scheduler->AddUnknownGeneratedInput(this, source);
1232 }
1233 }
1234
GetMetadata(const std::vector<std::string> & keys_to_extract,const std::vector<std::string> & keys_to_walk,const SourceDir & rebase_dir,bool deps_only,std::vector<Value> * result,TargetSet * targets_walked,Err * err) const1235 bool Target::GetMetadata(const std::vector<std::string>& keys_to_extract,
1236 const std::vector<std::string>& keys_to_walk,
1237 const SourceDir& rebase_dir,
1238 bool deps_only,
1239 std::vector<Value>* result,
1240 TargetSet* targets_walked,
1241 Err* err) const {
1242 std::vector<Value> next_walk_keys;
1243 std::vector<Value> current_result;
1244 // If deps_only, this is the top-level target and thus we don't want to
1245 // collect its metadata, only that of its deps and data_deps.
1246 if (deps_only) {
1247 // Empty string will be converted below to mean all deps and data_deps.
1248 // Origin is null because this isn't declared anywhere, and should never
1249 // trigger any errors.
1250 next_walk_keys.push_back(Value(nullptr, ""));
1251 } else {
1252 // Otherwise, we walk this target and collect the appropriate data.
1253 // NOTE: Always call WalkStep() even when have_metadata() is false,
1254 // because WalkStep() will append to 'next_walk_keys' in this case.
1255 // See https://crbug.com/1273069.
1256 if (!metadata().WalkStep(settings()->build_settings(), keys_to_extract,
1257 keys_to_walk, rebase_dir, &next_walk_keys,
1258 ¤t_result, err))
1259 return false;
1260 }
1261
1262 // Gather walk keys and find the appropriate target. Targets identified in
1263 // the walk key set must be deps or data_deps of the declaring target.
1264 const DepsIteratorRange& all_deps = GetDeps(Target::DEPS_ALL);
1265 const SourceDir& current_dir = label().dir();
1266 for (const auto& next : next_walk_keys) {
1267 DCHECK(next.type() == Value::STRING);
1268
1269 // If we hit an empty string in this list, add all deps and data_deps. The
1270 // ordering in the resulting list of values as a result will be the data
1271 // from each explicitly listed dep prior to this, followed by all data in
1272 // walk order of the remaining deps.
1273 if (next.string_value().empty()) {
1274 for (const auto& dep : all_deps) {
1275 // If we haven't walked this dep yet, go down into it.
1276 if (targets_walked->add(dep.ptr)) {
1277 if (!dep.ptr->GetMetadata(keys_to_extract, keys_to_walk, rebase_dir,
1278 false, result, targets_walked, err))
1279 return false;
1280 }
1281 }
1282
1283 // Any other walk keys are superfluous, as they can only be a subset of
1284 // all deps.
1285 break;
1286 }
1287
1288 // Otherwise, look through the target's deps for the specified one.
1289 // Canonicalize the label if possible.
1290 Label next_label = Label::Resolve(
1291 current_dir, settings()->build_settings()->root_path_utf8(),
1292 settings()->toolchain_label(), next, err);
1293 if (next_label.is_null()) {
1294 *err = Err(next.origin(), std::string("Failed to canonicalize ") +
1295 next.string_value() + std::string("."));
1296 }
1297 std::string canonicalize_next_label = next_label.GetUserVisibleName(true);
1298
1299 bool found_next = false;
1300 for (const auto& dep : all_deps) {
1301 // Match against the label with the toolchain.
1302 if (dep.label.GetUserVisibleName(true) == canonicalize_next_label) {
1303 // If we haven't walked this dep yet, go down into it.
1304 if (targets_walked->add(dep.ptr)) {
1305 if (!dep.ptr->GetMetadata(keys_to_extract, keys_to_walk, rebase_dir,
1306 false, result, targets_walked, err))
1307 return false;
1308 }
1309 // We found it, so we can exit this search now.
1310 found_next = true;
1311 break;
1312 }
1313 }
1314 // If we didn't find the specified dep in the target, that's an error.
1315 // Propagate it back to the user.
1316 if (!found_next) {
1317 *err = Err(next.origin(),
1318 std::string("I was expecting ") + canonicalize_next_label +
1319 std::string(" to be a dependency of ") +
1320 label().GetUserVisibleName(true) +
1321 ". Make sure it's included in the deps or data_deps, and "
1322 "that you've specified the appropriate toolchain.");
1323 return false;
1324 }
1325 }
1326 result->insert(result->end(), std::make_move_iterator(current_result.begin()),
1327 std::make_move_iterator(current_result.end()));
1328 return true;
1329 }
1330