Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: tools/gn/target.cc

Issue 440333002: Support more configurability in GN toolchains (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "tools/gn/target.h" 5 #include "tools/gn/target.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/strings/string_util.h"
8 #include "tools/gn/config_values_extractors.h" 9 #include "tools/gn/config_values_extractors.h"
10 #include "tools/gn/filesystem_utils.h"
9 #include "tools/gn/scheduler.h" 11 #include "tools/gn/scheduler.h"
12 #include "tools/gn/substitution_writer.h"
10 13
11 namespace { 14 namespace {
12 15
13 typedef std::set<const Config*> ConfigSet; 16 typedef std::set<const Config*> ConfigSet;
14 17
15 // Merges the dependent configs from the given target to the given config list. 18 // Merges the dependent configs from the given target to the given config list.
16 void MergeDirectDependentConfigsFrom(const Target* from_target, 19 void MergeDirectDependentConfigsFrom(const Target* from_target,
17 UniqueVector<LabelConfigPair>* dest) { 20 UniqueVector<LabelConfigPair>* dest) {
18 const UniqueVector<LabelConfigPair>& direct = 21 const UniqueVector<LabelConfigPair>& direct =
19 from_target->direct_dependent_configs(); 22 from_target->direct_dependent_configs();
(...skipping 14 matching lines...) Expand all
34 dest->push_back(all[i]); 37 dest->push_back(all[i]);
35 } 38 }
36 } 39 }
37 40
38 } // namespace 41 } // namespace
39 42
40 Target::Target(const Settings* settings, const Label& label) 43 Target::Target(const Settings* settings, const Label& label)
41 : Item(settings, label), 44 : Item(settings, label),
42 output_type_(UNKNOWN), 45 output_type_(UNKNOWN),
43 all_headers_public_(true), 46 all_headers_public_(true),
44 hard_dep_(false) { 47 hard_dep_(false),
48 toolchain_(NULL) {
45 } 49 }
46 50
47 Target::~Target() { 51 Target::~Target() {
48 } 52 }
49 53
50 // static 54 // static
51 const char* Target::GetStringForOutputType(OutputType type) { 55 const char* Target::GetStringForOutputType(OutputType type) {
52 switch (type) { 56 switch (type) {
53 case UNKNOWN: 57 case UNKNOWN:
54 return "Unknown"; 58 return "Unknown";
(...skipping 21 matching lines...) Expand all
76 Target* Target::AsTarget() { 80 Target* Target::AsTarget() {
77 return this; 81 return this;
78 } 82 }
79 83
80 const Target* Target::AsTarget() const { 84 const Target* Target::AsTarget() const {
81 return this; 85 return this;
82 } 86 }
83 87
84 void Target::OnResolved() { 88 void Target::OnResolved() {
85 DCHECK(output_type_ != UNKNOWN); 89 DCHECK(output_type_ != UNKNOWN);
90 DCHECK(toolchain_) << "Toolchain should have been set before resolving.";
86 91
87 // Convert any groups we depend on to just direct dependencies on that 92 // Convert any groups we depend on to just direct dependencies on that
88 // group's deps. We insert the new deps immediately after the group so that 93 // group's deps. We insert the new deps immediately after the group so that
89 // the ordering is preserved. We need to keep the original group so that any 94 // the ordering is preserved. We need to keep the original group so that any
90 // flags, etc. that it specifies itself are applied to us. 95 // flags, etc. that it specifies itself are applied to us.
91 for (size_t i = 0; i < deps_.size(); i++) { 96 for (size_t i = 0; i < deps_.size(); i++) {
92 const Target* dep = deps_[i].ptr; 97 const Target* dep = deps_[i].ptr;
93 if (dep->output_type_ == GROUP) { 98 if (dep->output_type_ == GROUP) {
99 // TODO(brettw) bug 403488 this should also handle datadeps.
94 deps_.insert(deps_.begin() + i + 1, dep->deps_.begin(), dep->deps_.end()); 100 deps_.insert(deps_.begin() + i + 1, dep->deps_.begin(), dep->deps_.end());
95 i += dep->deps_.size(); 101 i += dep->deps_.size();
96 } 102 }
97 } 103 }
98 104
99 // Copy our own dependent configs to the list of configs applying to us. 105 // Copy our own dependent configs to the list of configs applying to us.
100 configs_.Append(all_dependent_configs_.begin(), all_dependent_configs_.end()); 106 configs_.Append(all_dependent_configs_.begin(), all_dependent_configs_.end());
101 configs_.Append(direct_dependent_configs_.begin(), 107 configs_.Append(direct_dependent_configs_.begin(),
102 direct_dependent_configs_.end()); 108 direct_dependent_configs_.end());
103 109
104 // Copy our own libs and lib_dirs to the final set. This will be from our 110 // Copy our own libs and lib_dirs to the final set. This will be from our
105 // target and all of our configs. We do this specially since these must be 111 // target and all of our configs. We do this specially since these must be
106 // inherited through the dependency tree (other flags don't work this way). 112 // inherited through the dependency tree (other flags don't work this way).
107 for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) { 113 for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) {
108 const ConfigValues& cur = iter.cur(); 114 const ConfigValues& cur = iter.cur();
109 all_lib_dirs_.append(cur.lib_dirs().begin(), cur.lib_dirs().end()); 115 all_lib_dirs_.append(cur.lib_dirs().begin(), cur.lib_dirs().end());
110 all_libs_.append(cur.libs().begin(), cur.libs().end()); 116 all_libs_.append(cur.libs().begin(), cur.libs().end());
111 } 117 }
112 118
113 if (output_type_ != GROUP) { 119 if (output_type_ != GROUP) {
114 // Don't pull target info like libraries and configs from dependencies into 120 // Don't pull target info like libraries and configs from dependencies into
115 // a group target. When A depends on a group G, the G's dependents will 121 // a group target. When A depends on a group G, the G's dependents will
116 // be treated as direct dependencies of A, so this is unnecessary and will 122 // be treated as direct dependencies of A, so this is unnecessary and will
117 // actually result in duplicated settings (since settings will also be 123 // actually result in duplicated settings (since settings will also be
118 // pulled from G to A in case G has configs directly on it). 124 // pulled from G to A in case G has configs directly on it).
119 PullDependentTargetInfo(); 125 PullDependentTargetInfo();
120 } 126 }
121 PullForwardedDependentConfigs(); 127 PullForwardedDependentConfigs();
122 PullRecursiveHardDeps(); 128 PullRecursiveHardDeps();
129
130 FillOutputFiles();
123 } 131 }
124 132
125 bool Target::IsLinkable() const { 133 bool Target::IsLinkable() const {
126 return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY; 134 return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY;
127 } 135 }
128 136
137 std::string Target::GetComputedOutputName(bool include_prefix) const {
138 DCHECK(toolchain_)
139 << "Toolchain must be specified before getting the computed output name.";
140
141 const std::string& name = output_name_.empty() ? label().name()
142 : output_name_;
143
144 std::string result;
145 if (include_prefix) {
146 const Tool* tool = toolchain_->GetToolForTargetFinalOutput(this);
147 const std::string& prefix = tool->output_prefix();
148 // Only add the prefix if the name doesn't already have it.
149 if (!StartsWithASCII(name, prefix, true))
150 result = prefix;
151 }
152
153 result.append(name);
154 return result;
155 }
156
157 bool Target::SetToolchain(const Toolchain* toolchain, Err* err) {
158 DCHECK(!toolchain_);
159 DCHECK(output_type_ != UNKNOWN);
jamesr 2014/08/19 19:30:42 DCHECK_NE will give better output on failure
160 toolchain_ = toolchain;
161
162 const Tool* tool = toolchain->GetToolForTargetFinalOutput(this);
163 if (tool)
164 return true;
165
166 // Tool not specified for this target type.
167 if (err) {
168 *err = Err(defined_from(), "This target uses an undefined tool.",
169 "The target " + label().GetUserVisibleName(false) +
jamesr 2014/08/19 19:30:42 this could use some stringprintf, imo. it's really
170 "\nof type \"" + GetStringForOutputType(output_type_) +
171 "\"\nuses toolchain " +
172 label().GetToolchainLabel().GetUserVisibleName(false) +
173 "\nwhich doesn't have the tool \"" +
174 Toolchain::ToolTypeToName(
175 toolchain->GetToolTypeForTargetFinalOutput(this)) +
176 "\" defined.\n\nAlas, I can not continue.");
177 }
178 return false;
179 }
180
129 void Target::PullDependentTargetInfo() { 181 void Target::PullDependentTargetInfo() {
130 // Gather info from our dependents we need. 182 // Gather info from our dependents we need.
131 for (size_t dep_i = 0; dep_i < deps_.size(); dep_i++) { 183 for (size_t dep_i = 0; dep_i < deps_.size(); dep_i++) {
132 const Target* dep = deps_[dep_i].ptr; 184 const Target* dep = deps_[dep_i].ptr;
133 MergeAllDependentConfigsFrom(dep, &configs_, &all_dependent_configs_); 185 MergeAllDependentConfigsFrom(dep, &configs_, &all_dependent_configs_);
134 MergeDirectDependentConfigsFrom(dep, &configs_); 186 MergeDirectDependentConfigsFrom(dep, &configs_);
135 187
136 // Direct dependent libraries. 188 // Direct dependent libraries.
137 if (dep->output_type() == STATIC_LIBRARY || 189 if (dep->output_type() == STATIC_LIBRARY ||
138 dep->output_type() == SHARED_LIBRARY || 190 dep->output_type() == SHARED_LIBRARY ||
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 235
184 // Android STL doesn't like insert(begin, end) so do it manually. 236 // Android STL doesn't like insert(begin, end) so do it manually.
185 // TODO(brettw) this can be changed to insert(dep->begin(), dep->end()) when 237 // TODO(brettw) this can be changed to insert(dep->begin(), dep->end()) when
186 // Android uses a better STL. 238 // Android uses a better STL.
187 for (std::set<const Target*>::const_iterator cur = 239 for (std::set<const Target*>::const_iterator cur =
188 dep->recursive_hard_deps().begin(); 240 dep->recursive_hard_deps().begin();
189 cur != dep->recursive_hard_deps().end(); ++cur) 241 cur != dep->recursive_hard_deps().end(); ++cur)
190 recursive_hard_deps_.insert(*cur); 242 recursive_hard_deps_.insert(*cur);
191 } 243 }
192 } 244 }
245
246 void Target::FillOutputFiles() {
247 const Tool* tool = toolchain_->GetToolForTargetFinalOutput(this);
248 switch (output_type_) {
249 case GROUP:
250 case SOURCE_SET:
251 case COPY_FILES:
252 case ACTION:
253 case ACTION_FOREACH: {
254 // These don't get linked to and use stamps which should be the first
255 // entry in the outputs. These stamps are named
256 // "<target_out_dir>/<targetname>.stamp".
257 dependency_output_file_ = GetTargetOutputDirAsOutputFile(this);
258 dependency_output_file_.value().append(GetComputedOutputName(true));
259 dependency_output_file_.value().append(".stamp");
260 break;
261 }
262 case EXECUTABLE:
263 // Executables don't get linked to, but the first output is used for
264 // dependency management.
265 CHECK(tool->outputs().list().size() >= 1);
jamesr 2014/08/19 19:30:42 CHECK_GE produces slightly better output on failur
266 dependency_output_file_ =
267 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
268 this, tool, tool->outputs().list()[0]);
269 break;
270 case STATIC_LIBRARY:
271 // Static libraries both have dependencies and linking going off of the
272 // first output.
273 CHECK(tool->outputs().list().size() >= 1);
274 link_output_file_ = dependency_output_file_ =
275 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
276 this, tool, tool->outputs().list()[0]);
277 break;
278 case SHARED_LIBRARY:
279 CHECK(tool->outputs().list().size() >= 1);
280 if (tool->link_output().empty() && tool->depend_output().empty()) {
281 // Default behavior, use the first output file for both.
282 link_output_file_ = dependency_output_file_ =
283 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
284 this, tool, tool->outputs().list()[0]);
285 } else {
286 // Use the tool-specified ones.
287 if (!tool->link_output().empty()) {
288 link_output_file_ =
289 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
290 this, tool, tool->link_output());
291 }
292 if (!tool->depend_output().empty()) {
293 dependency_output_file_ =
294 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
295 this, tool, tool->link_output());
296 }
297 }
298 break;
299 case UNKNOWN:
300 default:
301 NOTREACHED();
302 }
303 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698