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/target.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/stringprintf.h"
10 #include "tools/gn/config_values_extractors.h"
11 #include "tools/gn/deps_iterator.h"
12 #include "tools/gn/filesystem_utils.h"
13 #include "tools/gn/scheduler.h"
14 #include "tools/gn/substitution_writer.h"
18 typedef std::set
<const Config
*> ConfigSet
;
20 // Merges the public configs from the given target to the given config list.
21 void MergePublicConfigsFrom(const Target
* from_target
,
22 UniqueVector
<LabelConfigPair
>* dest
) {
23 const UniqueVector
<LabelConfigPair
>& pub
= from_target
->public_configs();
24 dest
->Append(pub
.begin(), pub
.end());
27 // Like MergePublicConfigsFrom above except does the "all dependent" ones. This
28 // additionally adds all configs to the all_dependent_configs_ of the dest
29 // target given in *all_dest.
30 void MergeAllDependentConfigsFrom(const Target
* from_target
,
31 UniqueVector
<LabelConfigPair
>* dest
,
32 UniqueVector
<LabelConfigPair
>* all_dest
) {
33 const UniqueVector
<LabelConfigPair
>& all
=
34 from_target
->all_dependent_configs();
35 for (size_t i
= 0; i
< all
.size(); i
++) {
36 all_dest
->push_back(all
[i
]);
37 dest
->push_back(all
[i
]);
41 Err
MakeTestOnlyError(const Target
* from
, const Target
* to
) {
42 return Err(from
->defined_from(), "Test-only dependency not allowed.",
43 from
->label().GetUserVisibleName(false) + "\n"
44 "which is NOT marked testonly can't depend on\n" +
45 to
->label().GetUserVisibleName(false) + "\n"
46 "which is marked testonly. Only targets with \"testonly = true\"\n"
47 "can depend on other test-only targets.\n"
49 "Either mark it test-only or don't do this dependency.");
52 Err
MakeStaticLibDepsError(const Target
* from
, const Target
* to
) {
53 return Err(from
->defined_from(),
54 "Complete static libraries can't depend on static libraries.",
55 from
->label().GetUserVisibleName(false) +
57 "which is a complete static library can't depend on\n" +
58 to
->label().GetUserVisibleName(false) +
60 "which is a static library.\n"
62 "Use source sets for intermediate targets instead.");
67 Target::Target(const Settings
* settings
, const Label
& label
)
68 : Item(settings
, label
),
69 output_type_(UNKNOWN
),
70 all_headers_public_(true),
71 check_includes_(true),
72 complete_static_lib_(false),
82 const char* Target::GetStringForOutputType(OutputType type
) {
91 return "Shared library";
93 return "Static library";
101 return "ActionForEach";
107 Target
* Target::AsTarget() {
111 const Target
* Target::AsTarget() const {
115 bool Target::OnResolved(Err
* err
) {
116 DCHECK(output_type_
!= UNKNOWN
);
117 DCHECK(toolchain_
) << "Toolchain should have been set before resolving.";
119 // Copy our own dependent configs to the list of configs applying to us.
120 configs_
.Append(all_dependent_configs_
.begin(), all_dependent_configs_
.end());
121 MergePublicConfigsFrom(this, &configs_
);
123 // Copy our own libs and lib_dirs to the final set. This will be from our
124 // target and all of our configs. We do this specially since these must be
125 // inherited through the dependency tree (other flags don't work this way).
126 for (ConfigValuesIterator
iter(this); !iter
.done(); iter
.Next()) {
127 const ConfigValues
& cur
= iter
.cur();
128 all_lib_dirs_
.append(cur
.lib_dirs().begin(), cur
.lib_dirs().end());
129 all_libs_
.append(cur
.libs().begin(), cur
.libs().end());
132 PullDependentTargetInfo();
133 PullForwardedDependentConfigs();
134 PullRecursiveHardDeps();
138 if (!CheckVisibility(err
))
140 if (!CheckTestonly(err
))
142 if (!CheckNoNestedStaticLibs(err
))
148 bool Target::IsLinkable() const {
149 return output_type_
== STATIC_LIBRARY
|| output_type_
== SHARED_LIBRARY
;
152 bool Target::IsFinal() const {
153 return output_type_
== EXECUTABLE
|| output_type_
== SHARED_LIBRARY
||
154 (output_type_
== STATIC_LIBRARY
&& complete_static_lib_
);
157 std::string
Target::GetComputedOutputName(bool include_prefix
) const {
159 << "Toolchain must be specified before getting the computed output name.";
161 const std::string
& name
= output_name_
.empty() ? label().name()
165 if (include_prefix
) {
166 const Tool
* tool
= toolchain_
->GetToolForTargetFinalOutput(this);
167 const std::string
& prefix
= tool
->output_prefix();
168 // Only add the prefix if the name doesn't already have it.
169 if (!StartsWithASCII(name
, prefix
, true))
177 bool Target::SetToolchain(const Toolchain
* toolchain
, Err
* err
) {
179 DCHECK_NE(UNKNOWN
, output_type_
);
180 toolchain_
= toolchain
;
182 const Tool
* tool
= toolchain
->GetToolForTargetFinalOutput(this);
186 // Tool not specified for this target type.
188 *err
= Err(defined_from(), "This target uses an undefined tool.",
192 "uses toolchain %s\n"
193 "which doesn't have the tool \"%s\" defined.\n\n"
194 "Alas, I can not continue.",
195 label().GetUserVisibleName(false).c_str(),
196 GetStringForOutputType(output_type_
),
197 label().GetToolchainLabel().GetUserVisibleName(false).c_str(),
198 Toolchain::ToolTypeToName(
199 toolchain
->GetToolTypeForTargetFinalOutput(this)).c_str()));
204 void Target::PullDependentTargetInfo() {
205 // Gather info from our dependents we need.
206 for (DepsIterator
iter(this, DepsIterator::LINKED_ONLY
); !iter
.done();
208 const Target
* dep
= iter
.target();
209 MergeAllDependentConfigsFrom(dep
, &configs_
, &all_dependent_configs_
);
210 MergePublicConfigsFrom(dep
, &configs_
);
212 // Direct dependent libraries.
213 if (dep
->output_type() == STATIC_LIBRARY
||
214 dep
->output_type() == SHARED_LIBRARY
||
215 dep
->output_type() == SOURCE_SET
)
216 inherited_libraries_
.push_back(dep
);
218 // Inherited libraries and flags are inherited across static library
220 if (!dep
->IsFinal()) {
221 inherited_libraries_
.Append(dep
->inherited_libraries().begin(),
222 dep
->inherited_libraries().end());
224 // Inherited library settings.
225 all_lib_dirs_
.append(dep
->all_lib_dirs());
226 all_libs_
.append(dep
->all_libs());
231 void Target::PullForwardedDependentConfigs() {
232 // Pull public configs from each of our dependency's public deps.
233 for (size_t dep
= 0; dep
< public_deps_
.size(); dep
++)
234 PullForwardedDependentConfigsFrom(public_deps_
[dep
].ptr
);
236 // Forward public configs if explicitly requested.
237 for (size_t dep
= 0; dep
< forward_dependent_configs_
.size(); dep
++) {
238 const Target
* from_target
= forward_dependent_configs_
[dep
].ptr
;
240 // The forward_dependent_configs_ must be in the deps (public or private)
241 // already, so we don't need to bother copying to our configs, only
243 DCHECK(std::find_if(private_deps_
.begin(), private_deps_
.end(),
244 LabelPtrPtrEquals
<Target
>(from_target
)) !=
245 private_deps_
.end() ||
246 std::find_if(public_deps_
.begin(), public_deps_
.end(),
247 LabelPtrPtrEquals
<Target
>(from_target
)) !=
250 PullForwardedDependentConfigsFrom(from_target
);
254 void Target::PullForwardedDependentConfigsFrom(const Target
* from
) {
255 public_configs_
.Append(from
->public_configs().begin(),
256 from
->public_configs().end());
259 void Target::PullRecursiveHardDeps() {
260 for (DepsIterator
iter(this, DepsIterator::LINKED_ONLY
); !iter
.done();
262 if (iter
.target()->hard_dep())
263 recursive_hard_deps_
.insert(iter
.target());
265 // Android STL doesn't like insert(begin, end) so do it manually.
266 // TODO(brettw) this can be changed to
267 // insert(iter.target()->begin(), iter.target()->end())
268 // when Android uses a better STL.
269 for (std::set
<const Target
*>::const_iterator cur
=
270 iter
.target()->recursive_hard_deps().begin();
271 cur
!= iter
.target()->recursive_hard_deps().end(); ++cur
)
272 recursive_hard_deps_
.insert(*cur
);
276 void Target::FillOutputFiles() {
277 const Tool
* tool
= toolchain_
->GetToolForTargetFinalOutput(this);
278 switch (output_type_
) {
283 case ACTION_FOREACH
: {
284 // These don't get linked to and use stamps which should be the first
285 // entry in the outputs. These stamps are named
286 // "<target_out_dir>/<targetname>.stamp".
287 dependency_output_file_
= GetTargetOutputDirAsOutputFile(this);
288 dependency_output_file_
.value().append(GetComputedOutputName(true));
289 dependency_output_file_
.value().append(".stamp");
293 // Executables don't get linked to, but the first output is used for
294 // dependency management.
295 CHECK_GE(tool
->outputs().list().size(), 1u);
296 dependency_output_file_
=
297 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
298 this, tool
, tool
->outputs().list()[0]);
301 // Static libraries both have dependencies and linking going off of the
303 CHECK(tool
->outputs().list().size() >= 1);
304 link_output_file_
= dependency_output_file_
=
305 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
306 this, tool
, tool
->outputs().list()[0]);
309 CHECK(tool
->outputs().list().size() >= 1);
310 if (tool
->link_output().empty() && tool
->depend_output().empty()) {
311 // Default behavior, use the first output file for both.
312 link_output_file_
= dependency_output_file_
=
313 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
314 this, tool
, tool
->outputs().list()[0]);
316 // Use the tool-specified ones.
317 if (!tool
->link_output().empty()) {
319 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
320 this, tool
, tool
->link_output());
322 if (!tool
->depend_output().empty()) {
323 dependency_output_file_
=
324 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
325 this, tool
, tool
->depend_output());
335 bool Target::CheckVisibility(Err
* err
) const {
336 for (DepsIterator
iter(this); !iter
.done(); iter
.Advance()) {
337 if (!Visibility::CheckItemVisibility(this, iter
.target(), err
))
343 bool Target::CheckTestonly(Err
* err
) const {
344 // If the current target is marked testonly, it can include both testonly
345 // and non-testonly targets, so there's nothing to check.
349 // Verify no deps have "testonly" set.
350 for (DepsIterator
iter(this); !iter
.done(); iter
.Advance()) {
351 if (iter
.target()->testonly()) {
352 *err
= MakeTestOnlyError(this, iter
.target());
360 bool Target::CheckNoNestedStaticLibs(Err
* err
) const {
361 // If the current target is not a complete static library, it can depend on
362 // static library targets with no problem.
363 if (!(output_type() == Target::STATIC_LIBRARY
&& complete_static_lib()))
366 // Verify no deps are static libraries.
367 for (DepsIterator
iter(this); !iter
.done(); iter
.Advance()) {
368 if (iter
.target()->output_type() == Target::STATIC_LIBRARY
) {
369 *err
= MakeStaticLibDepsError(this, iter
.target());
374 // Verify no inherited libraries are static libraries.
375 for (size_t i
= 0; i
< inherited_libraries().size(); ++i
) {
376 if (inherited_libraries()[i
]->output_type() == Target::STATIC_LIBRARY
) {
377 *err
= MakeStaticLibDepsError(this, inherited_libraries()[i
]);