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