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.
5 #include "tools/gn/builder.h"
7 #include "tools/gn/config.h"
8 #include "tools/gn/err.h"
9 #include "tools/gn/loader.h"
10 #include "tools/gn/scheduler.h"
11 #include "tools/gn/settings.h"
12 #include "tools/gn/target.h"
13 #include "tools/gn/trace.h"
17 typedef BuilderRecord::BuilderRecordSet BuilderRecordSet
;
19 // Recursively looks in the tree for a given node, returning true if it
20 // was found in the dependecy graph. This is used to see if a given node
21 // participates in a cycle.
23 // If this returns true, the cycle will be in *path. This should point to an
24 // empty vector for the first call. During computation, the path will contain
25 // the full dependency path to the current node.
27 // Return false means no cycle was found.
28 bool RecursiveFindCycle(const BuilderRecord
* search_in
,
29 std::vector
<const BuilderRecord
*>* path
) {
30 path
->push_back(search_in
);
32 const BuilderRecord::BuilderRecordSet
& unresolved
=
33 search_in
->unresolved_deps();
34 for (BuilderRecord::BuilderRecordSet::const_iterator i
= unresolved
.begin();
35 i
!= unresolved
.end(); ++i
) {
36 const BuilderRecord
* cur
= *i
;
38 std::vector
<const BuilderRecord
*>::iterator found
=
39 std::find(path
->begin(), path
->end(), cur
);
40 if (found
!= path
->end()) {
41 // This item is already in the set, we found the cycle. Everything before
42 // the first definition of cur is irrelevant to the cycle.
43 path
->erase(path
->begin(), found
);
48 if (RecursiveFindCycle(cur
, path
))
49 return true; // Found cycle.
57 Builder::Builder(Loader
* loader
) : loader_(loader
) {
63 void Builder::ItemDefined(scoped_ptr
<Item
> item
) {
64 ScopedTrace
trace(TraceItem::TRACE_DEFINE_TARGET
, item
->label());
65 trace
.SetToolchain(item
->settings()->toolchain_label());
67 BuilderRecord::ItemType type
= BuilderRecord::TypeOfItem(item
.get());
70 BuilderRecord
* record
=
71 GetOrCreateRecordOfType(item
->label(), item
->defined_from(), type
, &err
);
73 g_scheduler
->FailWithError(err
);
77 // Check that it's not been already defined.
79 err
= Err(item
->defined_from(), "Duplicate definition.",
80 "The item\n " + item
->label().GetUserVisibleName(false) +
81 "\nwas already defined.");
82 err
.AppendSubErr(Err(record
->item()->defined_from(),
83 "Previous definition:"));
84 g_scheduler
->FailWithError(err
);
88 record
->set_item(item
.Pass());
90 // Do target-specific dependency setup. This will also schedule dependency
91 // loads for targets that are required.
93 case BuilderRecord::ITEM_TARGET
:
94 if (!TargetDefined(record
, &err
)) {
95 g_scheduler
->FailWithError(err
);
99 case BuilderRecord::ITEM_TOOLCHAIN
:
100 loader_
->ToolchainLoaded(record
->item()->AsToolchain());
106 if (record
->can_resolve()) {
107 if (!ResolveItem(record
, &err
)) {
108 g_scheduler
->FailWithError(err
);
114 const Item
* Builder::GetItem(const Label
& label
) const {
115 const BuilderRecord
* record
= GetRecord(label
);
118 return record
->item();
121 const Toolchain
* Builder::GetToolchain(const Label
& label
) const {
122 const BuilderRecord
* record
= GetRecord(label
);
127 return record
->item()->AsToolchain();
130 std::vector
<const BuilderRecord
*> Builder::GetAllRecords() const {
131 std::vector
<const BuilderRecord
*> result
;
132 result
.reserve(records_
.size());
133 for (RecordMap::const_iterator i
= records_
.begin();
134 i
!= records_
.end(); ++i
)
135 result
.push_back(i
->second
);
139 std::vector
<const Target
*> Builder::GetAllResolvedTargets() const {
140 std::vector
<const Target
*> result
;
141 result
.reserve(records_
.size());
142 for (RecordMap::const_iterator i
= records_
.begin();
143 i
!= records_
.end(); ++i
) {
144 if (i
->second
->type() == BuilderRecord::ITEM_TARGET
&&
145 i
->second
->should_generate() && i
->second
->item())
146 result
.push_back(i
->second
->item()->AsTarget());
151 const BuilderRecord
* Builder::GetRecord(const Label
& label
) const {
152 // Forward to the non-const version.
153 return const_cast<Builder
*>(this)->GetRecord(label
);
156 BuilderRecord
* Builder::GetRecord(const Label
& label
) {
157 RecordMap::iterator found
= records_
.find(label
);
158 if (found
== records_
.end())
160 return found
->second
;
163 bool Builder::CheckForBadItems(Err
* err
) const {
164 // Look for errors where we find a defined node with an item that refers to
165 // an undefined one with no item. There may be other nodes in turn depending
166 // on our defined one, but listing those isn't helpful: we want to find the
169 // This finds normal "missing dependency" errors but does not find circular
170 // dependencies because in this case all items in the cycle will be GENERATED
171 // but none will be resolved. If this happens, we'll check explicitly for
173 std::vector
<const BuilderRecord
*> bad_records
;
174 std::string depstring
;
175 for (RecordMap::const_iterator i
= records_
.begin();
176 i
!= records_
.end(); ++i
) {
177 const BuilderRecord
* src
= i
->second
;
178 if (!src
->should_generate())
179 continue; // Skip ungenerated nodes.
181 if (!src
->resolved()) {
182 bad_records
.push_back(src
);
184 // Check dependencies.
185 for (BuilderRecord::BuilderRecordSet::const_iterator dest_iter
=
186 src
->unresolved_deps().begin();
187 dest_iter
!= src
->unresolved_deps().end();
189 const BuilderRecord
* dest
= *dest_iter
;
191 depstring
+= src
->label().GetUserVisibleName(true) +
192 "\n needs " + dest
->label().GetUserVisibleName(true) + "\n";
198 if (!depstring
.empty()) {
199 *err
= Err(Location(), "Unresolved dependencies.", depstring
);
203 if (!bad_records
.empty()) {
204 // Our logic above found a bad node but didn't identify the problem. This
205 // normally means a circular dependency.
206 depstring
= CheckForCircularDependencies(bad_records
);
207 if (depstring
.empty()) {
208 // Something's very wrong, just dump out the bad nodes.
209 depstring
= "I have no idea what went wrong, but these are unresolved, "
210 "possible due to an\ninternal error:";
211 for (size_t i
= 0; i
< bad_records
.size(); i
++) {
212 depstring
+= "\n\"" +
213 bad_records
[i
]->label().GetUserVisibleName(false) + "\"";
215 *err
= Err(Location(), "", depstring
);
217 *err
= Err(Location(), "Dependency cycle:", depstring
);
225 bool Builder::TargetDefined(BuilderRecord
* record
, Err
* err
) {
226 Target
* target
= record
->item()->AsTarget();
228 if (!AddDeps(record
, target
->deps(), err
) ||
229 !AddDeps(record
, target
->datadeps(), err
) ||
230 !AddDeps(record
, target
->configs(), err
) ||
231 !AddDeps(record
, target
->all_dependent_configs(), err
) ||
232 !AddDeps(record
, target
->direct_dependent_configs(), err
) ||
233 !AddToolchainDep(record
, target
, err
))
236 // All targets in the default toolchain get generated by default. We also
237 // check if this target was previously marked as "required" and force setting
238 // the bit again so the target's dependencies (which we now know) get the
239 // required bit pushed to them.
240 if (record
->should_generate() || target
->settings()->is_default())
241 RecursiveSetShouldGenerate(record
, true);
246 BuilderRecord
* Builder::GetOrCreateRecordOfType(const Label
& label
,
247 const ParseNode
* request_from
,
248 BuilderRecord::ItemType type
,
250 BuilderRecord
* record
= GetRecord(label
);
252 // Not seen this record yet, create a new one.
253 record
= new BuilderRecord(type
, label
);
254 record
->set_originally_referenced_from(request_from
);
255 records_
[label
] = record
;
260 if (record
->type() != type
) {
261 *err
= Err(request_from
, "Item type does not match.",
262 "The item \"" + label
.GetUserVisibleName(false) +
263 "\"\nwas expected to be a " +
264 BuilderRecord::GetNameForType(type
) +
265 " but was previously referenced as a " +
266 BuilderRecord::GetNameForType(record
->type()));
267 if (record
->originally_referenced_from()) {
268 err
->AppendSubErr(Err(record
->originally_referenced_from(),
269 "The previous reference was here."));
277 BuilderRecord
* Builder::GetResolvedRecordOfType(const Label
& label
,
278 const ParseNode
* origin
,
279 BuilderRecord::ItemType type
,
281 BuilderRecord
* record
= GetRecord(label
);
283 *err
= Err(origin
, "Item not found",
284 "\"" + label
.GetUserVisibleName(false) + "\" doesn't\n"
285 "refer to an existent thing.");
289 const Item
* item
= record
->item();
291 *err
= Err(origin
, "Item not resolved.",
292 "\"" + label
.GetUserVisibleName(false) + "\" hasn't been resolved.\n");
296 if (!BuilderRecord::IsItemOfType(item
, type
)) {
298 std::string("This is not a ") + BuilderRecord::GetNameForType(type
),
299 "\"" + label
.GetUserVisibleName(false) + "\" refers to a " +
300 item
->GetItemTypeName() + " instead of a " +
301 BuilderRecord::GetNameForType(type
) + ".");
307 bool Builder::AddDeps(BuilderRecord
* record
,
308 const LabelConfigVector
& configs
,
310 for (size_t i
= 0; i
< configs
.size(); i
++) {
311 BuilderRecord
* dep_record
= GetOrCreateRecordOfType(
312 configs
[i
].label
, configs
[i
].origin
, BuilderRecord::ITEM_CONFIG
, err
);
315 record
->AddDep(dep_record
);
320 bool Builder::AddDeps(BuilderRecord
* record
,
321 const LabelTargetVector
& targets
,
323 for (size_t i
= 0; i
< targets
.size(); i
++) {
324 BuilderRecord
* dep_record
= GetOrCreateRecordOfType(
325 targets
[i
].label
, targets
[i
].origin
, BuilderRecord::ITEM_TARGET
, err
);
328 record
->AddDep(dep_record
);
333 bool Builder::AddToolchainDep(BuilderRecord
* record
,
334 const Target
* target
,
336 BuilderRecord
* toolchain_record
= GetOrCreateRecordOfType(
337 target
->settings()->toolchain_label(), target
->defined_from(),
338 BuilderRecord::ITEM_TOOLCHAIN
, err
);
339 if (!toolchain_record
)
341 record
->AddDep(toolchain_record
);
346 void Builder::RecursiveSetShouldGenerate(BuilderRecord
* record
,
348 if (!force
&& record
->should_generate())
349 return; // Already set.
350 record
->set_should_generate(true);
352 const BuilderRecordSet
& deps
= record
->all_deps();
353 for (BuilderRecordSet::const_iterator i
= deps
.begin();
354 i
!= deps
.end(); i
++) {
355 BuilderRecord
* cur
= *i
;
356 if (!cur
->should_generate()) {
357 ScheduleItemLoadIfNecessary(cur
);
358 RecursiveSetShouldGenerate(cur
, false);
363 void Builder::ScheduleItemLoadIfNecessary(BuilderRecord
* record
) {
364 loader_
->Load(record
->label());
367 bool Builder::ResolveItem(BuilderRecord
* record
, Err
* err
) {
368 DCHECK(record
->can_resolve() && !record
->resolved());
370 if (record
->type() == BuilderRecord::ITEM_TARGET
) {
371 Target
* target
= record
->item()->AsTarget();
372 if (!ResolveDeps(&target
->deps(), err
) ||
373 !ResolveDeps(&target
->datadeps(), err
) ||
374 !ResolveConfigs(&target
->configs(), err
) ||
375 !ResolveConfigs(&target
->all_dependent_configs(), err
) ||
376 !ResolveConfigs(&target
->direct_dependent_configs(), err
) ||
377 !ResolveForwardDependentConfigs(target
, err
))
381 record
->set_resolved(true);
382 record
->item()->OnResolved();
383 if (!resolved_callback_
.is_null())
384 resolved_callback_
.Run(record
);
386 // Recursively update everybody waiting on this item to be resolved.
387 BuilderRecordSet
& waiting_set
= record
->waiting_on_resolution();
388 for (BuilderRecordSet::iterator i
= waiting_set
.begin();
389 i
!= waiting_set
.end(); ++i
) {
390 BuilderRecord
* waiting
= *i
;
391 DCHECK(waiting
->unresolved_deps().find(record
) !=
392 waiting
->unresolved_deps().end());
393 waiting
->unresolved_deps().erase(record
);
395 if (waiting
->can_resolve()) {
396 if (!ResolveItem(waiting
, err
))
404 bool Builder::ResolveDeps(LabelTargetVector
* deps
, Err
* err
) {
405 for (size_t i
= 0; i
< deps
->size(); i
++) {
406 LabelTargetPair
& cur
= (*deps
)[i
];
409 BuilderRecord
* record
= GetResolvedRecordOfType(
410 cur
.label
, cur
.origin
, BuilderRecord::ITEM_TARGET
, err
);
413 cur
.ptr
= record
->item()->AsTarget();
418 bool Builder::ResolveConfigs(LabelConfigVector
* configs
, Err
* err
) {
419 for (size_t i
= 0; i
< configs
->size(); i
++) {
420 LabelConfigPair
& cur
= (*configs
)[i
];
423 BuilderRecord
* record
= GetResolvedRecordOfType(
424 cur
.label
, cur
.origin
, BuilderRecord::ITEM_CONFIG
, err
);
427 cur
.ptr
= record
->item()->AsConfig();
432 // "Forward dependent configs" should refer to targets in the deps that should
433 // have their configs forwarded.
434 bool Builder::ResolveForwardDependentConfigs(Target
* target
, Err
* err
) {
435 const LabelTargetVector
& deps
= target
->deps();
436 LabelTargetVector
& configs
= target
->forward_dependent_configs();
438 // Assume that the lists are small so that brute-force n^2 is appropriate.
439 for (size_t config_i
= 0; config_i
< configs
.size(); config_i
++) {
440 for (size_t dep_i
= 0; dep_i
< deps
.size(); dep_i
++) {
441 if (configs
[config_i
].label
== deps
[dep_i
].label
) {
442 DCHECK(deps
[dep_i
].ptr
); // Should already be resolved.
443 configs
[config_i
].ptr
= deps
[dep_i
].ptr
;
447 if (!configs
[config_i
].ptr
) {
448 *err
= Err(target
->defined_from(),
449 "Target in forward_dependent_configs_from was not listed in the deps",
450 "The target \"" + configs
[config_i
].label
.GetUserVisibleName(false) +
451 "\"\n was not present in the deps. This thing is used to forward\n"
452 "configs from direct dependents.");
459 std::string
Builder::CheckForCircularDependencies(
460 const std::vector
<const BuilderRecord
*>& bad_records
) const {
461 std::vector
<const BuilderRecord
*> cycle
;
462 if (!RecursiveFindCycle(bad_records
[0], &cycle
))
463 return std::string(); // Didn't find a cycle, something else is wrong.
465 // Walk backwards since the dependency arrows point in the reverse direction.
467 for (int i
= static_cast<int>(cycle
.size()) - 1; i
>= 0; i
--) {
468 ret
+= " " + cycle
[i
]->label().GetUserVisibleName(false);