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

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

Powered by Google App Engine
This is Rietveld 408576698