Add ResolvedTargetData::GetRustInheritedLibraries() This CL removes Target::rust_transitive_inherited_libs() and moves the computation of the corresponding value to the ResolvedTargetData class, where it will be created on demand by the GetRustInheritedLibraries() method. Bug: 331 Change-Id: I7fcfaee61242aeddfb9284e2270f2882712cdb81 Reviewed-on: https://gn-review.googlesource.com/c/gn/+/15327 Reviewed-by: Takuto Ikuta <tikuta@google.com> Commit-Queue: David Turner <digit@google.com>
diff --git a/src/gn/ninja_rust_binary_target_writer.cc b/src/gn/ninja_rust_binary_target_writer.cc index 6b9c2dc..06bce2f 100644 --- a/src/gn/ninja_rust_binary_target_writer.cc +++ b/src/gn/ninja_rust_binary_target_writer.cc
@@ -180,8 +180,9 @@ // on, and the public flag represents if the target has direct access to the // dependency through a chain of public_deps. std::vector<ExternCrate> transitive_crates; - for (const auto& [dep, has_direct_access] : - target_->rust_transitive_inherited_libs().GetOrderedAndPublicFlag()) { + for (const auto& inherited : resolved().GetRustInheritedLibraries(target_)) { + const Target* dep = inherited.target(); + bool has_direct_access = inherited.is_public(); // We will tell rustc to look for crate metadata for any rust crate // dependencies except cdylibs, as they have no metadata present. if (dep->source_types_used().RustSourceUsed() &&
diff --git a/src/gn/resolved_target_data.cc b/src/gn/resolved_target_data.cc index d944123..b2692e7 100644 --- a/src/gn/resolved_target_data.cc +++ b/src/gn/resolved_target_data.cc
@@ -171,3 +171,55 @@ } } } + +void ResolvedTargetData::ComputeRustLibs(TargetInfo* info) const { + RustLibsBuilder rust_libs; + + ComputeRustLibsFor(info->deps.public_deps(), true, &rust_libs); + ComputeRustLibsFor(info->deps.private_deps(), false, &rust_libs); + + info->rust_inherited_libs = rust_libs.inherited.Build(); + info->rust_inheritable_libs = rust_libs.inheritable.Build(); + info->has_rust_libs = true; +} + +void ResolvedTargetData::ComputeRustLibsFor(base::span<const Target*> deps, + bool is_public, + RustLibsBuilder* rust_libs) const { + for (const Target* dep : deps) { + // Collect Rust libraries that are accessible from the current target, or + // transitively part of the current target. + if (dep->output_type() == Target::STATIC_LIBRARY || + dep->output_type() == Target::SHARED_LIBRARY || + dep->output_type() == Target::SOURCE_SET || + dep->output_type() == Target::RUST_LIBRARY || + dep->output_type() == Target::GROUP) { + // Here we have: `this` --[depends-on]--> `dep` + // + // The `this` target has direct access to `dep` since its a direct + // dependency, regardless of the edge being a public_dep or not, so we + // pass true for public-ness. Whereas, anything depending on `this` can + // only gain direct access to `dep` if the edge between `this` and `dep` + // is public, so we pass `is_public`. + // + // TODO(danakj): We should only need to track Rust rlibs or dylibs here, + // as it's used for passing to rustc with --extern. We currently track + // everything then drop non-Rust libs in + // ninja_rust_binary_target_writer.cc. + rust_libs->inherited.Append(dep, true); + rust_libs->inheritable.Append(dep, is_public); + + const TargetInfo* dep_info = GetTargetRustLibs(dep); + rust_libs->inherited.AppendInherited(dep_info->rust_inheritable_libs, + true); + rust_libs->inheritable.AppendInherited(dep_info->rust_inheritable_libs, + is_public); + } else if (dep->output_type() == Target::RUST_PROC_MACRO) { + // Proc-macros are inherited as a transitive dependency, but the things + // they depend on can't be used elsewhere, as the proc macro is not + // linked into the target (as it's only used during compilation). + rust_libs->inherited.Append(dep, true); + rust_libs->inheritable.Append(dep, is_public); + } + } +}
diff --git a/src/gn/resolved_target_data.h b/src/gn/resolved_target_data.h index 0dc36be..f8f6458 100644 --- a/src/gn/resolved_target_data.h +++ b/src/gn/resolved_target_data.h
@@ -110,6 +110,13 @@ return GetTargetInheritedLibs(target)->inherited_libs; } + // Retrieves an ordered list of (target, is_public) paris for all link-time + // libraries for Rust-specific binary targets. + const std::vector<TargetPublicPair>& GetRustInheritedLibraries( + const Target* target) const { + return GetTargetRustLibs(target)->rust_inherited_libs; + } + private: // The information associated with a given Target pointer. struct TargetInfo { @@ -128,6 +135,7 @@ bool has_framework_info = false; bool has_hard_deps = false; bool has_inherited_libs = false; + bool has_rust_libs = false; // Only valid if |has_lib_info| is true. std::vector<SourceDir> lib_dirs; @@ -143,6 +151,10 @@ // Only valid if |has_inherited_libs| is true. std::vector<TargetPublicPair> inherited_libs; + + // Only valid if |has_rust_libs| is true. + std::vector<TargetPublicPair> rust_inherited_libs; + std::vector<TargetPublicPair> rust_inheritable_libs; }; // Retrieve TargetInfo value associated with |target|. Create @@ -185,6 +197,15 @@ return info; } + const TargetInfo* GetTargetRustLibs(const Target* target) const { + TargetInfo* info = GetTargetInfo(target); + if (!info->has_rust_libs) { + ComputeRustLibs(info); + DCHECK(info->has_rust_libs); + } + return info; + } + // Compute the portion of TargetInfo guarded by one of the |has_xxx| // booleans. This performs recursive and expensive computations and // should only be called once per TargetInfo instance. @@ -192,13 +213,24 @@ void ComputeFrameworkInfo(TargetInfo* info) const; void ComputeHardDeps(TargetInfo* info) const; void ComputeInheritedLibs(TargetInfo* info) const; + void ComputeRustLibs(TargetInfo* info) const; - // Helper function usde by ComputeInheritedLibs(). + // Helper function used by ComputeInheritedLibs(). void ComputeInheritedLibsFor( base::span<const Target*> deps, bool is_public, TargetPublicPairListBuilder* inherited_libraries) const; + // Helper data structure and function used by ComputeRustLibs(). + struct RustLibsBuilder { + TargetPublicPairListBuilder inherited; + TargetPublicPairListBuilder inheritable; + }; + + void ComputeRustLibsFor(base::span<const Target*> deps, + bool is_public, + RustLibsBuilder* rust_libs) const; + // A { Target* -> TargetInfo } map that will create entries // on demand (hence the mutable qualifier). Implemented with a // UniqueVector<> and a parallel vector of unique TargetInfo
diff --git a/src/gn/rust_values.h b/src/gn/rust_values.h index d201014..52a7623 100644 --- a/src/gn/rust_values.h +++ b/src/gn/rust_values.h
@@ -8,7 +8,6 @@ #include <map> #include "base/containers/flat_map.h" -#include "gn/inherited_libraries.h" #include "gn/label.h" #include "gn/source_file.h"
diff --git a/src/gn/target.cc b/src/gn/target.cc index 5bdfdef..f73cd3a 100644 --- a/src/gn/target.cc +++ b/src/gn/target.cc
@@ -484,7 +484,6 @@ } PullRecursiveBundleData(); - PullDependentTargetLibs(); if (!ResolvePrecompiledHeaders(err)) return false; @@ -738,47 +737,6 @@ } } -void Target::PullDependentTargetLibsFrom(const Target* dep, bool is_public) { - // Collect Rust libraries that are accessible from the current target, or - // transitively part of the current target. - if (dep->output_type() == STATIC_LIBRARY || - dep->output_type() == SHARED_LIBRARY || - dep->output_type() == SOURCE_SET || dep->output_type() == RUST_LIBRARY || - dep->output_type() == GROUP) { - // Here we have: `this` --[depends-on]--> `dep` - // - // The `this` target has direct access to `dep` since its a direct - // dependency, regardless of the edge being a public_dep or not, so we pass - // true for public-ness. Whereas, anything depending on `this` can only gain - // direct access to `dep` if the edge between `this` and `dep` is public, so - // we pass `is_public`. - // - // TODO(danakj): We should only need to track Rust rlibs or dylibs here, as - // it's used for passing to rustc with --extern. We currently track - // everything then drop non-Rust libs in ninja_rust_binary_target_writer.cc. - rust_transitive_inherited_libs_.Append(dep, true); - rust_transitive_inheritable_libs_.Append(dep, is_public); - - rust_transitive_inherited_libs_.AppendInherited( - dep->rust_transitive_inheritable_libs(), true); - rust_transitive_inheritable_libs_.AppendInherited( - dep->rust_transitive_inheritable_libs(), is_public); - } else if (dep->output_type() == RUST_PROC_MACRO) { - // Proc-macros are inherited as a transitive dependency, but the things they - // depend on can't be used elsewhere, as the proc macro is not linked into - // the target (as it's only used during compilation). - rust_transitive_inherited_libs_.Append(dep, true); - rust_transitive_inheritable_libs_.Append(dep, is_public); - } -} - -void Target::PullDependentTargetLibs() { - for (const auto& dep : public_deps_) - PullDependentTargetLibsFrom(dep.ptr, true); - for (const auto& dep : private_deps_) - PullDependentTargetLibsFrom(dep.ptr, false); -} - void Target::PullRecursiveBundleData() { for (const auto& pair : GetDeps(DEPS_LINKED)) { // Don't propagate bundle_data once they are added to a bundle.
diff --git a/src/gn/target.h b/src/gn/target.h index 348f49f..806d14b 100644 --- a/src/gn/target.h +++ b/src/gn/target.h
@@ -319,14 +319,6 @@ const RustValues& rust_values() const; bool has_rust_values() const { return rust_values_.get(); } - // Transitive closure of libraries that are depended on by this target - const InheritedLibraries& rust_transitive_inherited_libs() const { - return rust_transitive_inherited_libs_; - } - const InheritedLibraries& rust_transitive_inheritable_libs() const { - return rust_transitive_inheritable_libs_; - } - std::vector<LabelPattern>& friends() { return friends_; } const std::vector<LabelPattern>& friends() const { return friends_; } @@ -494,19 +486,6 @@ // Used for Rust targets. std::unique_ptr<RustValues> rust_values_; - // Used by all targets, only useful to generate Rust targets though. These - // present 2 different views of the public flags: - // - // Lists all transitive libraries, and for each one the public bit says if - // there is a public chain such that this target can make direct use of the - // lib. For each library marked public: "I have access to these targets." - InheritedLibraries rust_transitive_inherited_libs_; - // Lists all transitive libraries, and for each one the public bit says if a - // target depending on this target would inherit the libraries as public too. - // For each library marked public: "If you depend on me, you get access to - // these targets." - InheritedLibraries rust_transitive_inheritable_libs_; - // User for Swift targets. std::unique_ptr<SwiftValues> swift_values_;