1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "tools/gn/target_manager.h"
#include <deque>
#include "base/bind.h"
#include "base/strings/string_piece.h"
#include "tools/gn/build_settings.h"
#include "tools/gn/err.h"
#include "tools/gn/filesystem_utils.h"
#include "tools/gn/item_node.h"
#include "tools/gn/scheduler.h"
#include "tools/gn/toolchain_manager.h"
#include "tools/gn/value.h"
TargetManager::TargetManager(const BuildSettings* build_settings)
: build_settings_(build_settings) {
}
TargetManager::~TargetManager() {
}
Target* TargetManager::GetTarget(const Label& label,
const LocationRange& specified_from_here,
Target* dep_from,
Err* err) {
DCHECK(!label.is_null());
DCHECK(!label.toolchain_dir().value().empty());
DCHECK(!label.toolchain_name().empty());
base::AutoLock lock(build_settings_->item_tree().lock());
ItemNode* target_node =
build_settings_->item_tree().GetExistingNodeLocked(label);
Target* target = NULL;
if (!target_node) {
// First time we've seen this, may need to load the file.
// Compute the settings. The common case is that we have a dep_from and
// the toolchains match, so we can use the settings from there rather than
// querying the toolchain manager (which requires locking, etc.).
const Settings* settings;
if (dep_from && dep_from->label().ToolchainsEqual(label)) {
settings = dep_from->settings();
} else {
settings =
build_settings_->toolchain_manager().GetSettingsForToolchainLocked(
specified_from_here, label.GetToolchainLabel(), err);
if (!settings)
return NULL;
}
target = new Target(settings, label);
target_node = new ItemNode(target);
target_node->set_originally_referenced_from_here(specified_from_here);
build_settings_->item_tree().AddNodeLocked(target_node);
// We're generating a node when there is no referencing one.
if (!dep_from)
target_node->set_generated_from_here(specified_from_here);
// Only schedule loading the given target if somebody is depending on it
// (and we optimize by not re-asking it to run the current file).
// Otherwise, we're probably generating it right now.
if (dep_from && dep_from->label().dir() != label.dir()) {
if (!ScheduleInvocationLocked(specified_from_here, label, err))
return NULL;
}
} else if ((target = target_node->item()->AsTarget())) {
// Previously saw this item as a target.
// If we have no dep_from, we're generating it.
if (!dep_from) {
// In this case, it had better not already be generated.
if (target_node->state() != ItemNode::REFERENCED) {
*err = Err(specified_from_here,
"Duplicate target.",
"\"" + label.GetUserVisibleName(true) +
"\" being defined here.");
err->AppendSubErr(Err(target_node->generated_from_here(),
"Originally defined here."));
return NULL;
} else {
target_node->set_generated_from_here(specified_from_here);
}
}
} else {
// Error, we previously saw this thing as a non-target.
*err = Err(specified_from_here, "Not previously a target.",
"The target being declared here was previously seen referenced as a\n"
"non-target (like a config)");
err->AppendSubErr(Err(target_node->originally_referenced_from_here(),
"Originally referenced from here."));
return NULL;
}
// Keep a record of the guy asking us for this dependency. We know if
// somebody is adding a dependency, that guy it himself not resolved.
if (dep_from && target_node->state() != ItemNode::RESOLVED) {
build_settings_->item_tree().GetExistingNodeLocked(
dep_from->label())->AddDependency(target_node);
}
return target;
}
void TargetManager::TargetGenerationComplete(const Label& label) {
base::AutoLock lock(build_settings_->item_tree().lock());
build_settings_->item_tree().MarkItemGeneratedLocked(label);
}
void TargetManager::GetAllTargets(
std::vector<const Target*>* all_targets) const {
base::AutoLock lock(build_settings_->item_tree().lock());
std::vector<const Item*> all_items;
build_settings_->item_tree().GetAllItemsLocked(&all_items);
for (size_t i = 0; i < all_items.size(); i++) {
const Target* t = all_items[i]->AsTarget();
if (t)
all_targets->push_back(t);
}
}
bool TargetManager::ScheduleInvocationLocked(
const LocationRange& specified_from_here,
const Label& label,
Err* err) {
return build_settings_->toolchain_manager().ScheduleInvocationLocked(
specified_from_here, label.GetToolchainLabel(), label.dir(), err);
}
|