OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |