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/filesystem_utils.h"
12 #include "tools/gn/scheduler.h"
13 #include "tools/gn/substitution_writer.h"
17 typedef std::set
<const Config
*> ConfigSet
;
19 // Merges the dependent configs from the given target to the given config list.
20 void MergeDirectDependentConfigsFrom(const Target
* from_target
,
21 UniqueVector
<LabelConfigPair
>* dest
) {
22 const UniqueVector
<LabelConfigPair
>& direct
=
23 from_target
->direct_dependent_configs();
24 for (size_t i
= 0; i
< direct
.size(); i
++)
25 dest
->push_back(direct
[i
]);
28 // Like MergeDirectDependentConfigsFrom above except does the "all dependent"
29 // ones. This additionally adds all configs to the all_dependent_configs_ of
30 // the dest target given in *all_dest.
31 void MergeAllDependentConfigsFrom(const Target
* from_target
,
32 UniqueVector
<LabelConfigPair
>* dest
,
33 UniqueVector
<LabelConfigPair
>* all_dest
) {
34 const UniqueVector
<LabelConfigPair
>& all
=
35 from_target
->all_dependent_configs();
36 for (size_t i
= 0; i
< all
.size(); i
++) {
37 all_dest
->push_back(all
[i
]);
38 dest
->push_back(all
[i
]);
42 Err
MakeTestOnlyError(const Target
* from
, const Target
* to
) {
43 return Err(from
->defined_from(), "Test-only dependency not allowed.",
44 from
->label().GetUserVisibleName(false) + "\n"
45 "which is NOT marked testonly can't depend on\n" +
46 to
->label().GetUserVisibleName(false) + "\n"
47 "which is marked testonly. Only targets with \"testonly = true\"\n"
48 "can depend on other test-only targets.\n"
50 "Either mark it test-only or don't do this dependency.");
53 // Inserts the given groups dependencies, starting at the given index of the
54 // given vector. Returns the number of items inserted.
55 size_t InsertGroupDeps(LabelTargetVector
* vector
,
57 const Target
* group
) {
58 const LabelTargetVector
& deps
= group
->deps();
59 vector
->insert(vector
->begin() + insert_at
, deps
.begin(), deps
.end());
61 // Clear the origin of each of the insertions. This marks these dependencies
62 // as internally generated.
63 for (size_t i
= insert_at
; i
< deps
.size() + insert_at
; i
++)
64 (*vector
)[i
].origin
= NULL
;
71 Target::Target(const Settings
* settings
, const Label
& label
)
72 : Item(settings
, label
),
73 output_type_(UNKNOWN
),
74 all_headers_public_(true),
75 check_includes_(true),
76 complete_static_lib_(false),
86 const char* Target::GetStringForOutputType(OutputType type
) {
95 return "Shared library";
97 return "Static library";
105 return "ActionForEach";
111 Target
* Target::AsTarget() {
115 const Target
* Target::AsTarget() const {
119 bool Target::OnResolved(Err
* err
) {
120 DCHECK(output_type_
!= UNKNOWN
);
121 DCHECK(toolchain_
) << "Toolchain should have been set before resolving.";
125 // Copy our own dependent configs to the list of configs applying to us.
126 configs_
.Append(all_dependent_configs_
.begin(), all_dependent_configs_
.end());
127 configs_
.Append(direct_dependent_configs_
.begin(),
128 direct_dependent_configs_
.end());
130 // Copy our own libs and lib_dirs to the final set. This will be from our
131 // target and all of our configs. We do this specially since these must be
132 // inherited through the dependency tree (other flags don't work this way).
133 for (ConfigValuesIterator
iter(this); !iter
.done(); iter
.Next()) {
134 const ConfigValues
& cur
= iter
.cur();
135 all_lib_dirs_
.append(cur
.lib_dirs().begin(), cur
.lib_dirs().end());
136 all_libs_
.append(cur
.libs().begin(), cur
.libs().end());
139 if (output_type_
!= GROUP
) {
140 // Don't pull target info like libraries and configs from dependencies into
141 // a group target. When A depends on a group G, the G's dependents will
142 // be treated as direct dependencies of A, so this is unnecessary and will
143 // actually result in duplicated settings (since settings will also be
144 // pulled from G to A in case G has configs directly on it).
145 PullDependentTargetInfo();
147 PullForwardedDependentConfigs();
148 PullRecursiveHardDeps();
152 if (!CheckVisibility(err
))
154 if (!CheckTestonly(err
))
160 bool Target::IsLinkable() const {
161 return output_type_
== STATIC_LIBRARY
|| output_type_
== SHARED_LIBRARY
;
164 bool Target::IsFinal() const {
165 return output_type_
== EXECUTABLE
|| output_type_
== SHARED_LIBRARY
||
166 (output_type_
== STATIC_LIBRARY
&& complete_static_lib_
);
169 std::string
Target::GetComputedOutputName(bool include_prefix
) const {
171 << "Toolchain must be specified before getting the computed output name.";
173 const std::string
& name
= output_name_
.empty() ? label().name()
177 if (include_prefix
) {
178 const Tool
* tool
= toolchain_
->GetToolForTargetFinalOutput(this);
179 const std::string
& prefix
= tool
->output_prefix();
180 // Only add the prefix if the name doesn't already have it.
181 if (!StartsWithASCII(name
, prefix
, true))
189 bool Target::SetToolchain(const Toolchain
* toolchain
, Err
* err
) {
191 DCHECK_NE(UNKNOWN
, output_type_
);
192 toolchain_
= toolchain
;
194 const Tool
* tool
= toolchain
->GetToolForTargetFinalOutput(this);
198 // Tool not specified for this target type.
200 *err
= Err(defined_from(), "This target uses an undefined tool.",
204 "uses toolchain %s\n"
205 "which doesn't have the tool \"%s\" defined.\n\n"
206 "Alas, I can not continue.",
207 label().GetUserVisibleName(false).c_str(),
208 GetStringForOutputType(output_type_
),
209 label().GetToolchainLabel().GetUserVisibleName(false).c_str(),
210 Toolchain::ToolTypeToName(
211 toolchain
->GetToolTypeForTargetFinalOutput(this)).c_str()));
216 void Target::ExpandGroups() {
217 // Convert any groups we depend on to just direct dependencies on that
218 // group's deps. We insert the new deps immediately after the group so that
219 // the ordering is preserved. We need to keep the original group so that any
220 // flags, etc. that it specifies itself are applied to us.
221 // TODO(brettw) bug 403488 this should also handle datadeps.
222 for (size_t i
= 0; i
< deps_
.size(); i
++) {
223 const Target
* dep
= deps_
[i
].ptr
;
224 if (dep
->output_type_
== GROUP
)
225 i
+= InsertGroupDeps(&deps_
, i
+ 1, dep
);
229 void Target::PullDependentTargetInfo() {
230 // Gather info from our dependents we need.
231 for (size_t dep_i
= 0; dep_i
< deps_
.size(); dep_i
++) {
232 const Target
* dep
= deps_
[dep_i
].ptr
;
233 MergeAllDependentConfigsFrom(dep
, &configs_
, &all_dependent_configs_
);
234 MergeDirectDependentConfigsFrom(dep
, &configs_
);
236 // Direct dependent libraries.
237 if (dep
->output_type() == STATIC_LIBRARY
||
238 dep
->output_type() == SHARED_LIBRARY
||
239 dep
->output_type() == SOURCE_SET
)
240 inherited_libraries_
.push_back(dep
);
242 // Inherited libraries and flags are inherited across static library
244 if (!dep
->IsFinal()) {
245 inherited_libraries_
.Append(dep
->inherited_libraries().begin(),
246 dep
->inherited_libraries().end());
248 // Inherited library settings.
249 all_lib_dirs_
.append(dep
->all_lib_dirs());
250 all_libs_
.append(dep
->all_libs());
255 void Target::PullForwardedDependentConfigs() {
256 // Groups implicitly forward all if its dependency's configs.
257 if (output_type() == GROUP
) {
258 for (size_t i
= 0; i
< deps_
.size(); i
++)
259 forward_dependent_configs_
.push_back(deps_
[i
]);
262 // Forward direct dependent configs if requested.
263 for (size_t dep
= 0; dep
< forward_dependent_configs_
.size(); dep
++) {
264 const Target
* from_target
= forward_dependent_configs_
[dep
].ptr
;
266 // The forward_dependent_configs_ must be in the deps already, so we
267 // don't need to bother copying to our configs, only forwarding.
268 DCHECK(std::find_if(deps_
.begin(), deps_
.end(),
269 LabelPtrPtrEquals
<Target
>(from_target
)) !=
271 direct_dependent_configs_
.Append(
272 from_target
->direct_dependent_configs().begin(),
273 from_target
->direct_dependent_configs().end());
277 void Target::PullRecursiveHardDeps() {
278 for (size_t dep_i
= 0; dep_i
< deps_
.size(); dep_i
++) {
279 const Target
* dep
= deps_
[dep_i
].ptr
;
281 recursive_hard_deps_
.insert(dep
);
283 // Android STL doesn't like insert(begin, end) so do it manually.
284 // TODO(brettw) this can be changed to insert(dep->begin(), dep->end()) when
285 // Android uses a better STL.
286 for (std::set
<const Target
*>::const_iterator cur
=
287 dep
->recursive_hard_deps().begin();
288 cur
!= dep
->recursive_hard_deps().end(); ++cur
)
289 recursive_hard_deps_
.insert(*cur
);
293 void Target::FillOutputFiles() {
294 const Tool
* tool
= toolchain_
->GetToolForTargetFinalOutput(this);
295 switch (output_type_
) {
300 case ACTION_FOREACH
: {
301 // These don't get linked to and use stamps which should be the first
302 // entry in the outputs. These stamps are named
303 // "<target_out_dir>/<targetname>.stamp".
304 dependency_output_file_
= GetTargetOutputDirAsOutputFile(this);
305 dependency_output_file_
.value().append(GetComputedOutputName(true));
306 dependency_output_file_
.value().append(".stamp");
310 // Executables don't get linked to, but the first output is used for
311 // dependency management.
312 CHECK_GE(tool
->outputs().list().size(), 1u);
313 dependency_output_file_
=
314 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
315 this, tool
, tool
->outputs().list()[0]);
318 // Static libraries both have dependencies and linking going off of the
320 CHECK(tool
->outputs().list().size() >= 1);
321 link_output_file_
= dependency_output_file_
=
322 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
323 this, tool
, tool
->outputs().list()[0]);
326 CHECK(tool
->outputs().list().size() >= 1);
327 if (tool
->link_output().empty() && tool
->depend_output().empty()) {
328 // Default behavior, use the first output file for both.
329 link_output_file_
= dependency_output_file_
=
330 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
331 this, tool
, tool
->outputs().list()[0]);
333 // Use the tool-specified ones.
334 if (!tool
->link_output().empty()) {
336 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
337 this, tool
, tool
->link_output());
339 if (!tool
->depend_output().empty()) {
340 dependency_output_file_
=
341 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
342 this, tool
, tool
->link_output());
352 bool Target::CheckVisibility(Err
* err
) const {
353 // Only check visibility when the origin of the dependency is non-null. These
354 // are dependencies added by the GN files. Internally added dependencies
355 // (expanded groups) will have a null origin. We don't want to check
356 // visibility for these, since the point of a group would often be to
357 // forward visibility.
358 for (size_t i
= 0; i
< deps_
.size(); i
++) {
359 if (deps_
[i
].origin
&&
360 !Visibility::CheckItemVisibility(this, deps_
[i
].ptr
, err
))
364 for (size_t i
= 0; i
< datadeps_
.size(); i
++) {
365 if (deps_
[i
].origin
&&
366 !Visibility::CheckItemVisibility(this, datadeps_
[i
].ptr
, err
))
373 bool Target::CheckTestonly(Err
* err
) const {
374 // If there current target is marked testonly, it can include both testonly
375 // and non-testonly targets, so there's nothing to check.
379 // Verify no deps have "testonly" set.
380 for (size_t i
= 0; i
< deps_
.size(); i
++) {
381 if (deps_
[i
].ptr
->testonly()) {
382 *err
= MakeTestOnlyError(this, deps_
[i
].ptr
);
387 for (size_t i
= 0; i
< datadeps_
.size(); i
++) {
388 if (datadeps_
[i
].ptr
->testonly()) {
389 *err
= MakeTestOnlyError(this, datadeps_
[i
].ptr
);