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_;