Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / tools / gn / target.cc
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.
4
5 #include "tools/gn/target.h"
6
7 #include "base/bind.h"
8 #include "tools/gn/config_values_extractors.h"
9 #include "tools/gn/scheduler.h"
10
11 namespace {
12
13 typedef std::set<const Config*> ConfigSet;
14
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]);
26     }
27   }
28 }
29
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);
48     }
49   }
50 }
51
52 }  // namespace
53
54 Target::Target(const Settings* settings, const Label& label)
55     : Item(settings, label),
56       output_type_(UNKNOWN),
57       hard_dep_(false) {
58 }
59
60 Target::~Target() {
61 }
62
63 // static
64 const char* Target::GetStringForOutputType(OutputType type) {
65   switch (type) {
66     case UNKNOWN:
67       return "Unknown";
68     case GROUP:
69       return "Group";
70     case EXECUTABLE:
71       return "Executable";
72     case SHARED_LIBRARY:
73       return "Shared library";
74     case STATIC_LIBRARY:
75       return "Static library";
76     case COPY_FILES:
77       return "Copy";
78     case ACTION:
79       return "Action";
80     case ACTION_FOREACH:
81       return "ActionForEach";
82     default:
83       return "";
84   }
85 }
86
87 Target* Target::AsTarget() {
88   return this;
89 }
90
91 const Target* Target::AsTarget() const {
92   return this;
93 }
94
95 void Target::OnResolved() {
96   DCHECK(output_type_ != UNKNOWN);
97
98   // Convert any groups we depend on to just direct dependencies on that
99   // group's deps. We insert the new deps immediately after the group so that
100   // the ordering is preserved. We need to keep the original group so that any
101   // flags, etc. that it specifies itself are applied to us.
102   size_t original_deps_size = deps_.size();
103   for (size_t i = 0; i < original_deps_size; i++) {
104     const Target* dep = deps_[i].ptr;
105     if (dep->output_type_ == GROUP) {
106       deps_.insert(deps_.begin() + i + 1, dep->deps_.begin(), dep->deps_.end());
107       i += dep->deps_.size();
108     }
109   }
110
111   // Only add each config once. First remember the target's configs.
112   ConfigSet unique_configs;
113   for (size_t i = 0; i < configs_.size(); i++)
114     unique_configs.insert(configs_[i].ptr);
115
116   // Copy our own dependent configs to the list of configs applying to us.
117   for (size_t i = 0; i < all_dependent_configs_.size(); i++) {
118     if (unique_configs.find(all_dependent_configs_[i].ptr) ==
119         unique_configs.end()) {
120       unique_configs.insert(all_dependent_configs_[i].ptr);
121       configs_.push_back(all_dependent_configs_[i]);
122     }
123   }
124   for (size_t i = 0; i < direct_dependent_configs_.size(); i++) {
125     if (unique_configs.find(direct_dependent_configs_[i].ptr) ==
126         unique_configs.end()) {
127       unique_configs.insert(direct_dependent_configs_[i].ptr);
128       configs_.push_back(direct_dependent_configs_[i]);
129     }
130   }
131
132   // Copy our own libs and lib_dirs to the final set. This will be from our
133   // target and all of our configs. We do this specially since these must be
134   // inherited through the dependency tree (other flags don't work this way).
135   for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) {
136     const ConfigValues& cur = iter.cur();
137     all_lib_dirs_.append(cur.lib_dirs().begin(), cur.lib_dirs().end());
138     all_libs_.append(cur.libs().begin(), cur.libs().end());
139   }
140
141   if (output_type_ != GROUP) {
142     // Don't pull target info like libraries and configs from dependencies into
143     // a group target. When A depends on a group G, the G's dependents will
144     // be treated as direct dependencies of A, so this is unnecessary and will
145     // actually result in duplicated settings (since settings will also be
146     // pulled from G to A in case G has configs directly on it).
147     PullDependentTargetInfo(&unique_configs);
148   }
149 }
150
151 bool Target::IsLinkable() const {
152   return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY;
153 }
154
155 void Target::PullDependentTargetInfo(std::set<const Config*>* unique_configs) {
156   // Gather info from our dependents we need.
157   for (size_t dep_i = 0; dep_i < deps_.size(); dep_i++) {
158     const Target* dep = deps_[dep_i].ptr;
159     MergeAllDependentConfigsFrom(dep, unique_configs, &configs_,
160                                  &all_dependent_configs_);
161     MergeDirectDependentConfigsFrom(dep, unique_configs, &configs_);
162
163     // Direct dependent libraries.
164     if (dep->output_type() == STATIC_LIBRARY ||
165         dep->output_type() == SHARED_LIBRARY ||
166         dep->output_type() == SOURCE_SET)
167       inherited_libraries_.insert(dep);
168
169     // Inherited libraries and flags are inherited across static library
170     // boundaries.
171     if (dep->output_type() != SHARED_LIBRARY &&
172         dep->output_type() != EXECUTABLE) {
173       const std::set<const Target*> inherited = dep->inherited_libraries();
174       for (std::set<const Target*>::const_iterator i = inherited.begin();
175            i != inherited.end(); ++i)
176         inherited_libraries_.insert(*i);
177
178       // Inherited library settings.
179       all_lib_dirs_.append(dep->all_lib_dirs());
180       all_libs_.append(dep->all_libs());
181     }
182   }
183
184   // Forward direct dependent configs if requested.
185   for (size_t dep = 0; dep < forward_dependent_configs_.size(); dep++) {
186     const Target* from_target = forward_dependent_configs_[dep].ptr;
187
188     // The forward_dependent_configs_ must be in the deps already, so we
189     // don't need to bother copying to our configs, only forwarding.
190     DCHECK(std::find_if(deps_.begin(), deps_.end(),
191                         LabelPtrPtrEquals<Target>(from_target)) !=
192            deps_.end());
193     direct_dependent_configs_.insert(
194         direct_dependent_configs_.end(),
195         from_target->direct_dependent_configs().begin(),
196         from_target->direct_dependent_configs().end());
197   }
198 }