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 "tools/gn/config_values_extractors.h"
9 #include "tools/gn/scheduler.h"
13 typedef std::set
<const Config
*> ConfigSet
;
15 // Merges the dependent configs from the given target to the given config list.
16 // The unique_configs list is used for de-duping so values already added will
17 // not be added again.
18 void MergeDirectDependentConfigsFrom(const Target
* from_target
,
19 ConfigSet
* unique_configs
,
20 LabelConfigVector
* dest
) {
21 const LabelConfigVector
& direct
= from_target
->direct_dependent_configs();
22 for (size_t i
= 0; i
< direct
.size(); i
++) {
23 if (unique_configs
->find(direct
[i
].ptr
) == unique_configs
->end()) {
24 unique_configs
->insert(direct
[i
].ptr
);
25 dest
->push_back(direct
[i
]);
30 // Like MergeDirectDependentConfigsFrom above except does the "all dependent"
31 // ones. This additionally adds all configs to the all_dependent_configs_ of
32 // the dest target given in *all_dest.
33 void MergeAllDependentConfigsFrom(const Target
* from_target
,
34 ConfigSet
* unique_configs
,
35 LabelConfigVector
* dest
,
36 LabelConfigVector
* all_dest
) {
37 const LabelConfigVector
& all
= from_target
->all_dependent_configs();
38 for (size_t i
= 0; i
< all
.size(); i
++) {
39 // Always add it to all_dependent_configs_ since it might not be in that
40 // list even if we've seen it applied to this target before. This may
41 // introduce some duplicates in all_dependent_configs_, but those will
42 // we removed when they're actually applied to a target.
43 all_dest
->push_back(all
[i
]);
44 if (unique_configs
->find(all
[i
].ptr
) == unique_configs
->end()) {
45 // One we haven't seen yet, also apply it to ourselves.
46 dest
->push_back(all
[i
]);
47 unique_configs
->insert(all
[i
].ptr
);
54 Target::Target(const Settings
* settings
, const Label
& label
)
55 : Item(settings
, label
),
56 output_type_(UNKNOWN
),
57 all_headers_public_(true),
65 const char* Target::GetStringForOutputType(OutputType type
) {
74 return "Shared library";
76 return "Static library";
82 return "ActionForEach";
88 Target
* Target::AsTarget() {
92 const Target
* Target::AsTarget() const {
96 void Target::OnResolved() {
97 DCHECK(output_type_
!= UNKNOWN
);
99 // Convert any groups we depend on to just direct dependencies on that
100 // group's deps. We insert the new deps immediately after the group so that
101 // the ordering is preserved. We need to keep the original group so that any
102 // flags, etc. that it specifies itself are applied to us.
103 size_t original_deps_size
= deps_
.size();
104 for (size_t i
= 0; i
< original_deps_size
; i
++) {
105 const Target
* dep
= deps_
[i
].ptr
;
106 if (dep
->output_type_
== GROUP
) {
107 deps_
.insert(deps_
.begin() + i
+ 1, dep
->deps_
.begin(), dep
->deps_
.end());
108 i
+= dep
->deps_
.size();
112 // Only add each config once. First remember the target's configs.
113 ConfigSet unique_configs
;
114 for (size_t i
= 0; i
< configs_
.size(); i
++)
115 unique_configs
.insert(configs_
[i
].ptr
);
117 // Copy our own dependent configs to the list of configs applying to us.
118 for (size_t i
= 0; i
< all_dependent_configs_
.size(); i
++) {
119 if (unique_configs
.find(all_dependent_configs_
[i
].ptr
) ==
120 unique_configs
.end()) {
121 unique_configs
.insert(all_dependent_configs_
[i
].ptr
);
122 configs_
.push_back(all_dependent_configs_
[i
]);
125 for (size_t i
= 0; i
< direct_dependent_configs_
.size(); i
++) {
126 if (unique_configs
.find(direct_dependent_configs_
[i
].ptr
) ==
127 unique_configs
.end()) {
128 unique_configs
.insert(direct_dependent_configs_
[i
].ptr
);
129 configs_
.push_back(direct_dependent_configs_
[i
]);
133 // Copy our own libs and lib_dirs to the final set. This will be from our
134 // target and all of our configs. We do this specially since these must be
135 // inherited through the dependency tree (other flags don't work this way).
136 for (ConfigValuesIterator
iter(this); !iter
.done(); iter
.Next()) {
137 const ConfigValues
& cur
= iter
.cur();
138 all_lib_dirs_
.append(cur
.lib_dirs().begin(), cur
.lib_dirs().end());
139 all_libs_
.append(cur
.libs().begin(), cur
.libs().end());
142 if (output_type_
!= GROUP
) {
143 // Don't pull target info like libraries and configs from dependencies into
144 // a group target. When A depends on a group G, the G's dependents will
145 // be treated as direct dependencies of A, so this is unnecessary and will
146 // actually result in duplicated settings (since settings will also be
147 // pulled from G to A in case G has configs directly on it).
148 PullDependentTargetInfo(&unique_configs
);
152 bool Target::IsLinkable() const {
153 return output_type_
== STATIC_LIBRARY
|| output_type_
== SHARED_LIBRARY
;
156 void Target::PullDependentTargetInfo(std::set
<const Config
*>* unique_configs
) {
157 // Gather info from our dependents we need.
158 for (size_t dep_i
= 0; dep_i
< deps_
.size(); dep_i
++) {
159 const Target
* dep
= deps_
[dep_i
].ptr
;
160 MergeAllDependentConfigsFrom(dep
, unique_configs
, &configs_
,
161 &all_dependent_configs_
);
162 MergeDirectDependentConfigsFrom(dep
, unique_configs
, &configs_
);
164 // Direct dependent libraries.
165 if (dep
->output_type() == STATIC_LIBRARY
||
166 dep
->output_type() == SHARED_LIBRARY
||
167 dep
->output_type() == SOURCE_SET
)
168 inherited_libraries_
.insert(dep
);
170 // Inherited libraries and flags are inherited across static library
172 if (dep
->output_type() != SHARED_LIBRARY
&&
173 dep
->output_type() != EXECUTABLE
) {
174 const std::set
<const Target
*> inherited
= dep
->inherited_libraries();
175 for (std::set
<const Target
*>::const_iterator i
= inherited
.begin();
176 i
!= inherited
.end(); ++i
)
177 inherited_libraries_
.insert(*i
);
179 // Inherited library settings.
180 all_lib_dirs_
.append(dep
->all_lib_dirs());
181 all_libs_
.append(dep
->all_libs());
185 // Forward direct dependent configs if requested.
186 for (size_t dep
= 0; dep
< forward_dependent_configs_
.size(); dep
++) {
187 const Target
* from_target
= forward_dependent_configs_
[dep
].ptr
;
189 // The forward_dependent_configs_ must be in the deps already, so we
190 // don't need to bother copying to our configs, only forwarding.
191 DCHECK(std::find_if(deps_
.begin(), deps_
.end(),
192 LabelPtrPtrEquals
<Target
>(from_target
)) !=
194 direct_dependent_configs_
.insert(
195 direct_dependent_configs_
.end(),
196 from_target
->direct_dependent_configs().begin(),
197 from_target
->direct_dependent_configs().end());