• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 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 #ifndef TOOLS_GN_RESOLVED_TARGET_DATA_H_
6 #define TOOLS_GN_RESOLVED_TARGET_DATA_H_
7 
8 #include <memory>
9 #include <vector>
10 
11 #include "base/containers/span.h"
12 #include "gn/lib_file.h"
13 #include "gn/resolved_target_deps.h"
14 #include "gn/source_dir.h"
15 #include "gn/target.h"
16 #include "gn/target_public_pair.h"
17 #include "gn/unique_vector.h"
18 
19 // A class used to compute target-specific data by collecting information
20 // from its tree of dependencies.
21 //
22 // For example, linkable targets can call GetLinkedLibraries() and
23 // GetLinkedLibraryDirs() to find the library files and library search
24 // paths to add to their final linker command string, based on the
25 // definitions of the `libs` and `lib_dirs` config values of their
26 // transitive dependencies.
27 //
28 // Values are computed on demand, but memorized by the class instance in order
29 // to speed up multiple queries for targets that share dependencies.
30 //
31 // Usage is:
32 //
33 //  1) Create instance.
34 //
35 //  2) Call any of the methods to retrieve the value of the corresponding
36 //     data. For all methods, the input Target instance passed as argument
37 //     must have been fully resolved (meaning that Target::OnResolved()
38 //     must have been called and completed). Input target pointers are
39 //     const and thus are never modified. This allows using multiple
40 //     ResolvedTargetData instances from the same input graph in multiple
41 //     threads safely.
42 //
43 class ResolvedTargetData {
44  public:
45   // Return the public/private/data/dependencies of a given target
46   // as a ResolvedTargetDeps instance.
GetTargetDeps(const Target * target)47   const ResolvedTargetDeps& GetTargetDeps(const Target* target) const {
48     return GetTargetInfo(target)->deps;
49   }
50 
51   // Return the data dependencies of a given target.
52   // Convenience shortcut for GetTargetDeps(target).data_deps().
GetDataDeps(const Target * target)53   base::span<const Target*> GetDataDeps(const Target* target) const {
54     return GetTargetDeps(target).data_deps();
55   }
56 
57   // Return the public and private dependencies of a given target.
58   // Convenience shortcut for GetTargetDeps(target).linked_deps().
GetLinkedDeps(const Target * target)59   base::span<const Target*> GetLinkedDeps(const Target* target) const {
60     return GetTargetDeps(target).linked_deps();
61   }
62 
63   // The list of all library directory search path to add to the final link
64   // command of linkable binary. For example, if this returns ['dir1', 'dir2']
65   // a command for a C++ linker would typically use `-Ldir1 -Ldir2`.
GetLinkedLibraryDirs(const Target * target)66   const std::vector<SourceDir>& GetLinkedLibraryDirs(
67       const Target* target) const {
68     return GetTargetLibInfo(target)->lib_dirs;
69   }
70 
71   // The list of all library files to add to the final link command of linkable
72   // binaries. For example, if this returns ['foo', '/path/to/bar'], the command
73   // for a C++ linker would typically use '-lfoo /path/to/bar'.
GetLinkedLibraries(const Target * target)74   const std::vector<LibFile>& GetLinkedLibraries(const Target* target) const {
75     return GetTargetLibInfo(target)->libs;
76   }
77 
78   // The list of framework directories search paths to use at link time
79   // when generating macOS or iOS linkable binaries.
GetLinkedFrameworkDirs(const Target * target)80   const std::vector<SourceDir>& GetLinkedFrameworkDirs(
81       const Target* target) const {
82     return GetTargetFrameworkInfo(target)->framework_dirs;
83   }
84 
85   // The list of framework names to use at link time when generating macOS
86   // or iOS linkable binaries.
GetLinkedFrameworks(const Target * target)87   const std::vector<std::string>& GetLinkedFrameworks(
88       const Target* target) const {
89     return GetTargetFrameworkInfo(target)->frameworks;
90   }
91 
92   // The list of weak framework names to use at link time when generating macOS
93   // or iOS linkable binaries.
GetLinkedWeakFrameworks(const Target * target)94   const std::vector<std::string>& GetLinkedWeakFrameworks(
95       const Target* target) const {
96     return GetTargetFrameworkInfo(target)->weak_frameworks;
97   }
98 
99   // Retrieves a set of hard dependencies for this target.
100   // All hard deps from this target and all dependencies, but not the
101   // target itself.
GetHardDeps(const Target * target)102   const TargetSet& GetHardDeps(const Target* target) const {
103     return GetTargetHardDeps(target)->hard_deps;
104   }
105 
106   // Retrieves an ordered list of (target, is_public) pairs for all link-time
107   // libraries inherited by this target.
GetInheritedLibraries(const Target * target)108   const std::vector<TargetPublicPair>& GetInheritedLibraries(
109       const Target* target) const {
110     return GetTargetInheritedLibs(target)->inherited_libs;
111   }
112 
113   // Retrieves an ordered list of (target, is_public) paris for all link-time
114   // libraries for Rust-specific binary targets.
GetRustInheritedLibraries(const Target * target)115   const std::vector<TargetPublicPair>& GetRustInheritedLibraries(
116       const Target* target) const {
117     return GetTargetRustLibs(target)->rust_inherited_libs;
118   }
119 
120   // List of dependent target that generate a .swiftmodule. The current target
121   // is assumed to depend on those modules, and will add them to the module
122   // search path.
GetSwiftModuleDependencies(const Target * target)123   base::span<const Target*> GetSwiftModuleDependencies(
124       const Target* target) const {
125     const TargetInfo* info = GetTargetSwiftValues(target);
126     if (!info->swift_values.get())
127       return {};
128     return info->swift_values->modules;
129   }
130 
131  private:
132   // The information associated with a given Target pointer.
133   struct TargetInfo {
134     TargetInfo() = default;
135 
TargetInfoTargetInfo136     TargetInfo(const Target* target)
137         : target(target),
138           deps(target->public_deps(),
139                target->private_deps(),
140                target->data_deps()) {}
141 
142     const Target* target = nullptr;
143     ResolvedTargetDeps deps;
144 
145     bool has_lib_info = false;
146     bool has_framework_info = false;
147     bool has_hard_deps = false;
148     bool has_inherited_libs = false;
149     bool has_rust_libs = false;
150     bool has_swift_values = false;
151 
152     // Only valid if |has_lib_info| is true.
153     std::vector<SourceDir> lib_dirs;
154     std::vector<LibFile> libs;
155 
156     // Only valid if |has_framework_info| is true.
157     std::vector<SourceDir> framework_dirs;
158     std::vector<std::string> frameworks;
159     std::vector<std::string> weak_frameworks;
160 
161     // Only valid if |has_hard_deps| is true.
162     TargetSet hard_deps;
163 
164     // Only valid if |has_inherited_libs| is true.
165     std::vector<TargetPublicPair> inherited_libs;
166 
167     // Only valid if |has_rust_libs| is true.
168     std::vector<TargetPublicPair> rust_inherited_libs;
169     std::vector<TargetPublicPair> rust_inheritable_libs;
170 
171     // Only valid if |has_swift_values| is true.
172     // Most targets will not have Swift dependencies, so only
173     // allocate a SwiftValues struct when needed. A null pointer
174     // indicates empty lists.
175     struct SwiftValues {
176       std::vector<const Target*> modules;
177       std::vector<const Target*> public_modules;
178 
SwiftValuesTargetInfo::SwiftValues179       SwiftValues(std::vector<const Target*> modules,
180                   std::vector<const Target*> public_modules)
181           : modules(std::move(modules)),
182             public_modules(std::move(public_modules)) {}
183     };
184     std::unique_ptr<SwiftValues> swift_values;
185   };
186 
187   // Retrieve TargetInfo value associated with |target|. Create
188   // a new empty instance on demand if none is already available.
189   TargetInfo* GetTargetInfo(const Target* target) const;
190 
GetTargetLibInfo(const Target * target)191   const TargetInfo* GetTargetLibInfo(const Target* target) const {
192     TargetInfo* info = GetTargetInfo(target);
193     if (!info->has_lib_info) {
194       ComputeLibInfo(info);
195       DCHECK(info->has_lib_info);
196     }
197     return info;
198   }
199 
GetTargetFrameworkInfo(const Target * target)200   const TargetInfo* GetTargetFrameworkInfo(const Target* target) const {
201     TargetInfo* info = GetTargetInfo(target);
202     if (!info->has_framework_info) {
203       ComputeFrameworkInfo(info);
204       DCHECK(info->has_framework_info);
205     }
206     return info;
207   }
208 
GetTargetHardDeps(const Target * target)209   const TargetInfo* GetTargetHardDeps(const Target* target) const {
210     TargetInfo* info = GetTargetInfo(target);
211     if (!info->has_hard_deps) {
212       ComputeHardDeps(info);
213       DCHECK(info->has_hard_deps);
214     }
215     return info;
216   }
217 
GetTargetInheritedLibs(const Target * target)218   const TargetInfo* GetTargetInheritedLibs(const Target* target) const {
219     TargetInfo* info = GetTargetInfo(target);
220     if (!info->has_inherited_libs) {
221       ComputeInheritedLibs(info);
222       DCHECK(info->has_inherited_libs);
223     }
224     return info;
225   }
226 
GetTargetRustLibs(const Target * target)227   const TargetInfo* GetTargetRustLibs(const Target* target) const {
228     TargetInfo* info = GetTargetInfo(target);
229     if (!info->has_rust_libs) {
230       ComputeRustLibs(info);
231       DCHECK(info->has_rust_libs);
232     }
233     return info;
234   }
235 
GetTargetSwiftValues(const Target * target)236   const TargetInfo* GetTargetSwiftValues(const Target* target) const {
237     TargetInfo* info = GetTargetInfo(target);
238     if (!info->has_swift_values) {
239       ComputeSwiftValues(info);
240       DCHECK(info->has_swift_values);
241     }
242     return info;
243   }
244 
245   // Compute the portion of TargetInfo guarded by one of the |has_xxx|
246   // booleans. This performs recursive and expensive computations and
247   // should only be called once per TargetInfo instance.
248   void ComputeLibInfo(TargetInfo* info) const;
249   void ComputeFrameworkInfo(TargetInfo* info) const;
250   void ComputeHardDeps(TargetInfo* info) const;
251   void ComputeInheritedLibs(TargetInfo* info) const;
252   void ComputeRustLibs(TargetInfo* info) const;
253   void ComputeSwiftValues(TargetInfo* info) const;
254 
255   // Helper function used by ComputeInheritedLibs().
256   void ComputeInheritedLibsFor(
257       base::span<const Target*> deps,
258       bool is_public,
259       TargetPublicPairListBuilder* inherited_libraries) const;
260 
261   // Helper data structure and function used by ComputeRustLibs().
262   struct RustLibsBuilder {
263     TargetPublicPairListBuilder inherited;
264     TargetPublicPairListBuilder inheritable;
265   };
266 
267   void ComputeRustLibsFor(base::span<const Target*> deps,
268                           bool is_public,
269                           RustLibsBuilder* rust_libs) const;
270 
271   // A { Target* -> TargetInfo } map that will create entries
272   // on demand (hence the mutable qualifier). Implemented with a
273   // UniqueVector<> and a parallel vector of unique TargetInfo
274   // instances for best performance.
275   mutable UniqueVector<const Target*> targets_;
276   mutable std::vector<std::unique_ptr<TargetInfo>> infos_;
277 };
278 
279 #endif  // TOOLS_GN_RESOLVED_TARGET_DATA_H_
280