Add ResolvedTargetData::GetInheritedLibraries()

This CL removes Target::inherited_libraries() and moves
the computation of the corresponding value to the
ResolvedTargetData class instead, where it will be
created on-demand by the GetInheritedLibraries() method.

Bug: 331
Change-Id: I65f73d9d895f4db1318363b6c8a8775d7225252b
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/15326
Reviewed-by: Takuto Ikuta <tikuta@google.com>
Commit-Queue: David Turner <digit@google.com>
diff --git a/src/gn/ninja_binary_target_writer.cc b/src/gn/ninja_binary_target_writer.cc
index b1dbbef..5fb8929 100644
--- a/src/gn/ninja_binary_target_writer.cc
+++ b/src/gn/ninja_binary_target_writer.cc
@@ -137,8 +137,8 @@
   }
 
   // Inherited libraries.
-  for (auto* inherited_target : target_->inherited_libraries().GetOrdered()) {
-    ClassifyDependency(inherited_target, &classified_deps);
+  for (const auto& inherited : resolved().GetInheritedLibraries(target_)) {
+    ClassifyDependency(inherited.target(), &classified_deps);
   }
 
   // Data deps.
diff --git a/src/gn/ninja_c_binary_target_writer.cc b/src/gn/ninja_c_binary_target_writer.cc
index f74d208..9978b63 100644
--- a/src/gn/ninja_c_binary_target_writer.cc
+++ b/src/gn/ninja_c_binary_target_writer.cc
@@ -668,7 +668,8 @@
   // rlibs only depended on inside a shared library dependency).
   std::vector<OutputFile> transitive_rustlibs;
   if (target_->IsFinal()) {
-    for (const auto* dep : target_->inherited_libraries().GetOrdered()) {
+    for (const auto& inherited : resolved().GetInheritedLibraries(target_)) {
+      const Target* dep = inherited.target();
       if (dep->output_type() == Target::RUST_LIBRARY) {
         transitive_rustlibs.push_back(dep->dependency_output_file());
         implicit_deps.push_back(dep->dependency_output_file());
diff --git a/src/gn/resolved_target_data.cc b/src/gn/resolved_target_data.cc
index 467e2fb..d944123 100644
--- a/src/gn/resolved_target_data.cc
+++ b/src/gn/resolved_target_data.cc
@@ -88,3 +88,86 @@
   info->hard_deps = std::move(all_hard_deps);
   info->has_hard_deps = true;
 }
+
+void ResolvedTargetData::ComputeInheritedLibs(TargetInfo* info) const {
+  TargetPublicPairListBuilder inherited_libraries;
+
+  ComputeInheritedLibsFor(info->deps.public_deps(), true, &inherited_libraries);
+  ComputeInheritedLibsFor(info->deps.private_deps(), false,
+                          &inherited_libraries);
+
+  info->inherited_libs = inherited_libraries.Build();
+  info->has_inherited_libs = true;
+}
+
+void ResolvedTargetData::ComputeInheritedLibsFor(
+    base::span<const Target*> deps,
+    bool is_public,
+    TargetPublicPairListBuilder* inherited_libraries) const {
+  for (const Target* dep : deps) {
+    // Direct dependent libraries.
+    if (dep->output_type() == Target::STATIC_LIBRARY ||
+        dep->output_type() == Target::SHARED_LIBRARY ||
+        dep->output_type() == Target::RUST_LIBRARY ||
+        dep->output_type() == Target::SOURCE_SET ||
+        (dep->output_type() == Target::CREATE_BUNDLE &&
+         dep->bundle_data().is_framework())) {
+      inherited_libraries->Append(dep, is_public);
+    }
+    if (dep->output_type() == Target::SHARED_LIBRARY) {
+      // Shared library dependendencies are inherited across public shared
+      // library boundaries.
+      //
+      // In this case:
+      //   EXE -> INTERMEDIATE_SHLIB --[public]--> FINAL_SHLIB
+      // The EXE will also link to to FINAL_SHLIB. The public dependency means
+      // that the EXE can use the headers in FINAL_SHLIB so the FINAL_SHLIB
+      // will need to appear on EXE's link line.
+      //
+      // However, if the dependency is private:
+      //   EXE -> INTERMEDIATE_SHLIB --[private]--> FINAL_SHLIB
+      // the dependency will not be propagated because INTERMEDIATE_SHLIB is
+      // not granting permission to call functions from FINAL_SHLIB. If EXE
+      // wants to use functions (and link to) FINAL_SHLIB, it will need to do
+      // so explicitly.
+      //
+      // Static libraries and source sets aren't inherited across shared
+      // library boundaries because they will be linked into the shared
+      // library. Rust dylib deps are handled above and transitive deps are
+      // resolved by the compiler.
+      const TargetInfo* dep_info = GetTargetInheritedLibs(dep);
+      for (const auto& pair : dep_info->inherited_libs) {
+        if (pair.target()->output_type() == Target::SHARED_LIBRARY &&
+            pair.is_public()) {
+          inherited_libraries->Append(pair.target(), is_public);
+        }
+      }
+    } else if (!dep->IsFinal()) {
+      // The current target isn't linked, so propagate linked deps and
+      // libraries up the dependency tree.
+      const TargetInfo* dep_info = GetTargetInheritedLibs(dep);
+      for (const auto& pair : dep_info->inherited_libs) {
+        // Proc macros are not linked into targets that depend on them, so do
+        // not get inherited; they are consumed by the Rust compiler and only
+        // need to be specified in --extern.
+        if (pair.target()->output_type() != Target::RUST_PROC_MACRO)
+          inherited_libraries->Append(pair.target(),
+                                      is_public && pair.is_public());
+      }
+    } else if (dep->complete_static_lib()) {
+      // Inherit only final targets through _complete_ static libraries.
+      //
+      // Inherited final libraries aren't linked into complete static
+      // libraries. They are forwarded here so that targets that depend on
+      // complete static libraries can link them in. Conversely, since
+      // complete static libraries link in non-final targets, they shouldn't be
+      // inherited.
+      const TargetInfo* dep_info = GetTargetInheritedLibs(dep);
+      for (const auto& pair : dep_info->inherited_libs) {
+        if (pair.target()->IsFinal())
+          inherited_libraries->Append(pair.target(),
+                                      is_public && pair.is_public());
+      }
+    }
+  }
+}
diff --git a/src/gn/resolved_target_data.h b/src/gn/resolved_target_data.h
index bc992a1..0dc36be 100644
--- a/src/gn/resolved_target_data.h
+++ b/src/gn/resolved_target_data.h
@@ -103,6 +103,13 @@
     return GetTargetHardDeps(target)->hard_deps;
   }
 
+  // Retrieves an ordered list of (target, is_public) pairs for all link-time
+  // libraries inherited by this target.
+  const std::vector<TargetPublicPair>& GetInheritedLibraries(
+      const Target* target) const {
+    return GetTargetInheritedLibs(target)->inherited_libs;
+  }
+
  private:
   // The information associated with a given Target pointer.
   struct TargetInfo {
@@ -120,6 +127,7 @@
     bool has_lib_info = false;
     bool has_framework_info = false;
     bool has_hard_deps = false;
+    bool has_inherited_libs = false;
 
     // Only valid if |has_lib_info| is true.
     std::vector<SourceDir> lib_dirs;
@@ -132,6 +140,9 @@
 
     // Only valid if |has_hard_deps| is true.
     TargetSet hard_deps;
+
+    // Only valid if |has_inherited_libs| is true.
+    std::vector<TargetPublicPair> inherited_libs;
   };
 
   // Retrieve TargetInfo value associated with |target|. Create
@@ -165,12 +176,28 @@
     return info;
   }
 
+  const TargetInfo* GetTargetInheritedLibs(const Target* target) const {
+    TargetInfo* info = GetTargetInfo(target);
+    if (!info->has_inherited_libs) {
+      ComputeInheritedLibs(info);
+      DCHECK(info->has_inherited_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.
   void ComputeLibInfo(TargetInfo* info) const;
   void ComputeFrameworkInfo(TargetInfo* info) const;
   void ComputeHardDeps(TargetInfo* info) const;
+  void ComputeInheritedLibs(TargetInfo* info) const;
+
+  // Helper function usde by ComputeInheritedLibs().
+  void ComputeInheritedLibsFor(
+      base::span<const Target*> deps,
+      bool is_public,
+      TargetPublicPairListBuilder* inherited_libraries) const;
 
   // A { Target* -> TargetInfo } map that will create entries
   // on demand (hence the mutable qualifier). Implemented with a
diff --git a/src/gn/resolved_target_data_unittest.cc b/src/gn/resolved_target_data_unittest.cc
index 5871d39..d4f60b4 100644
--- a/src/gn/resolved_target_data_unittest.cc
+++ b/src/gn/resolved_target_data_unittest.cc
@@ -167,3 +167,244 @@
   const auto& framework_dirs3 = resolved.GetLinkedFrameworkDirs(&exec);
   EXPECT_EQ(0u, framework_dirs3.size());
 }
+
+TEST(ResolvedTargetDataTest, InheritLibs) {
+  TestWithScope setup;
+  Err err;
+
+  // Create a dependency chain:
+  //   A (executable) -> B (shared lib) -> C (static lib) -> D (source set)
+  TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
+  TestTarget b(setup, "//foo:b", Target::SHARED_LIBRARY);
+  TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
+  TestTarget d(setup, "//foo:d", Target::SOURCE_SET);
+  a.private_deps().push_back(LabelTargetPair(&b));
+  b.private_deps().push_back(LabelTargetPair(&c));
+  c.private_deps().push_back(LabelTargetPair(&d));
+
+  ASSERT_TRUE(d.OnResolved(&err));
+  ASSERT_TRUE(c.OnResolved(&err));
+  ASSERT_TRUE(b.OnResolved(&err));
+  ASSERT_TRUE(a.OnResolved(&err));
+
+  ResolvedTargetData resolved;
+
+  // C should have D in its inherited libs.
+  const auto& c_inherited_libs = resolved.GetInheritedLibraries(&c);
+  ASSERT_EQ(1u, c_inherited_libs.size());
+  EXPECT_EQ(&d, c_inherited_libs[0].target());
+
+  // B should have C and D in its inherited libs.
+  const auto& b_inherited = resolved.GetInheritedLibraries(&b);
+  ASSERT_EQ(2u, b_inherited.size());
+  EXPECT_EQ(&c, b_inherited[0].target());
+  EXPECT_EQ(&d, b_inherited[1].target());
+
+  // A should have B in its inherited libs, but not any others (the shared
+  // library will include the static library and source set).
+  const auto& a_inherited = resolved.GetInheritedLibraries(&a);
+  ASSERT_EQ(1u, a_inherited.size());
+  EXPECT_EQ(&b, a_inherited[0].target());
+}
+
+TEST(ResolvedTargetData, NoActionDepPropgation) {
+  TestWithScope setup;
+  Err err;
+  ResolvedTargetData resolved;
+  // Create a dependency chain:
+  //   A (exe) -> B (action) -> C (source_set)
+  {
+    TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
+    TestTarget b(setup, "//foo:b", Target::ACTION);
+    TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
+
+    a.private_deps().push_back(LabelTargetPair(&b));
+    b.private_deps().push_back(LabelTargetPair(&c));
+
+    ASSERT_TRUE(c.OnResolved(&err));
+    ASSERT_TRUE(b.OnResolved(&err));
+    ASSERT_TRUE(a.OnResolved(&err));
+
+    // The executable should not have inherited the source set across the
+    // action.
+    ASSERT_TRUE(resolved.GetInheritedLibraries(&a).empty());
+  }
+}
+
+TEST(ResolvedTargetDataTest, InheritCompleteStaticLib) {
+  TestWithScope setup;
+  Err err;
+
+  ResolvedTargetData resolved;
+
+  // Create a dependency chain:
+  //   A (executable) -> B (complete static lib) -> C (source set)
+  TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
+  TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
+  b.set_complete_static_lib(true);
+
+  const LibFile lib("foo");
+  const SourceDir lib_dir("/foo_dir/");
+  TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
+  c.config_values().libs().push_back(lib);
+  c.config_values().lib_dirs().push_back(lib_dir);
+
+  a.public_deps().push_back(LabelTargetPair(&b));
+  b.public_deps().push_back(LabelTargetPair(&c));
+
+  ASSERT_TRUE(c.OnResolved(&err));
+  ASSERT_TRUE(b.OnResolved(&err));
+  ASSERT_TRUE(a.OnResolved(&err));
+
+  // B should have C in its inherited libs.
+  const auto& b_inherited = resolved.GetInheritedLibraries(&b);
+  ASSERT_EQ(1u, b_inherited.size());
+  EXPECT_EQ(&c, b_inherited[0].target());
+
+  // A should have B in its inherited libs, but not any others (the complete
+  // static library will include the source set).
+  const auto& a_inherited = resolved.GetInheritedLibraries(&a);
+  ASSERT_EQ(1u, a_inherited.size());
+  EXPECT_EQ(&b, a_inherited[0].target());
+
+  // A should inherit the libs and lib_dirs from the C.
+  const auto& a_libs = resolved.GetLinkedLibraries(&a);
+  ASSERT_EQ(1u, a_libs.size());
+  EXPECT_EQ(lib, a_libs[0]);
+
+  const auto& a_lib_dirs = resolved.GetLinkedLibraryDirs(&a);
+  ASSERT_EQ(1u, a_lib_dirs.size());
+  EXPECT_EQ(lib_dir, a_lib_dirs[0]);
+}
+
+TEST(ResolvedTargetDataTest, InheritCompleteStaticLibStaticLibDeps) {
+  TestWithScope setup;
+  Err err;
+
+  // Create a dependency chain:
+  //   A (executable) -> B (complete static lib) -> C (static lib)
+  TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
+  TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
+  b.set_complete_static_lib(true);
+  TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
+  a.public_deps().push_back(LabelTargetPair(&b));
+  b.public_deps().push_back(LabelTargetPair(&c));
+
+  ASSERT_TRUE(c.OnResolved(&err));
+  ASSERT_TRUE(b.OnResolved(&err));
+  ASSERT_TRUE(a.OnResolved(&err));
+
+  ResolvedTargetData resolved;
+
+  // B should have C in its inherited libs.
+  const auto& b_inherited = resolved.GetInheritedLibraries(&b);
+  ASSERT_EQ(1u, b_inherited.size());
+  EXPECT_EQ(&c, b_inherited[0].target());
+
+  // A should have B in its inherited libs, but not any others (the complete
+  // static library will include the static library).
+  const auto& a_inherited = resolved.GetInheritedLibraries(&a);
+  ASSERT_EQ(1u, a_inherited.size());
+  EXPECT_EQ(&b, a_inherited[0].target());
+}
+
+TEST(ResolvedTargetDataTest,
+     InheritCompleteStaticLibInheritedCompleteStaticLibDeps) {
+  TestWithScope setup;
+  Err err;
+
+  // Create a dependency chain:
+  //   A (executable) -> B (complete static lib) -> C (complete static lib)
+  TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
+  TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
+  b.set_complete_static_lib(true);
+  TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
+  c.set_complete_static_lib(true);
+
+  a.private_deps().push_back(LabelTargetPair(&b));
+  b.private_deps().push_back(LabelTargetPair(&c));
+
+  ASSERT_TRUE(c.OnResolved(&err));
+  ASSERT_TRUE(b.OnResolved(&err));
+  ASSERT_TRUE(a.OnResolved(&err));
+
+  ResolvedTargetData resolved;
+
+  // B should have C in its inherited libs.
+  const auto& b_inherited = resolved.GetInheritedLibraries(&b);
+  ASSERT_EQ(1u, b_inherited.size());
+  EXPECT_EQ(&c, b_inherited[0].target());
+
+  // A should have B and C in its inherited libs.
+  const auto& a_inherited = resolved.GetInheritedLibraries(&a);
+  ASSERT_EQ(2u, a_inherited.size());
+  EXPECT_EQ(&b, a_inherited[0].target());
+  EXPECT_EQ(&c, a_inherited[1].target());
+}
+
+TEST(ResolvedTargetDataTest, NoActionDepPropgation) {
+  TestWithScope setup;
+  Err err;
+  ResolvedTargetData resolved;
+
+  // Create a dependency chain:
+  //   A (exe) -> B (action) -> C (source_set)
+  {
+    TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
+    TestTarget b(setup, "//foo:b", Target::ACTION);
+    TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
+
+    a.private_deps().push_back(LabelTargetPair(&b));
+    b.private_deps().push_back(LabelTargetPair(&c));
+
+    ASSERT_TRUE(c.OnResolved(&err));
+    ASSERT_TRUE(b.OnResolved(&err));
+    ASSERT_TRUE(a.OnResolved(&err));
+
+    // The executable should not have inherited the source set across the
+    // action.
+    const auto& libs = resolved.GetInheritedLibraries(&a);
+    ASSERT_TRUE(libs.empty());
+  }
+}
+
+// Shared libraries should be inherited across public shared library
+// boundaries.
+TEST(ResolvedTargetDataTest, SharedInheritance) {
+  TestWithScope setup;
+  Err err;
+
+  // Create two leaf shared libraries.
+  TestTarget pub(setup, "//foo:pub", Target::SHARED_LIBRARY);
+  ASSERT_TRUE(pub.OnResolved(&err));
+
+  TestTarget priv(setup, "//foo:priv", Target::SHARED_LIBRARY);
+  ASSERT_TRUE(priv.OnResolved(&err));
+
+  // Intermediate shared library with the leaf shared libraries as
+  // dependencies, one public, one private.
+  TestTarget inter(setup, "//foo:inter", Target::SHARED_LIBRARY);
+  inter.public_deps().push_back(LabelTargetPair(&pub));
+  inter.private_deps().push_back(LabelTargetPair(&priv));
+  ASSERT_TRUE(inter.OnResolved(&err));
+
+  // The intermediate shared library should have both "pub" and "priv" in its
+  // inherited libraries.
+  ResolvedTargetData resolved;
+  const auto& inter_inherited = resolved.GetInheritedLibraries(&inter);
+  ASSERT_EQ(2u, inter_inherited.size());
+  EXPECT_EQ(&pub, inter_inherited[0].target());
+  EXPECT_EQ(&priv, inter_inherited[1].target());
+
+  // Make a toplevel executable target depending on the intermediate one.
+  TestTarget exe(setup, "//foo:exe", Target::SHARED_LIBRARY);
+  exe.private_deps().push_back(LabelTargetPair(&inter));
+  ASSERT_TRUE(exe.OnResolved(&err));
+
+  // The exe's inherited libraries should be "inter" (because it depended
+  // directly on it) and "pub" (because inter depended publicly on it).
+  const auto& exe_inherited = resolved.GetInheritedLibraries(&exe);
+  ASSERT_EQ(2u, exe_inherited.size());
+  EXPECT_EQ(&inter, exe_inherited[0].target());
+  EXPECT_EQ(&pub, exe_inherited[1].target());
+}
diff --git a/src/gn/target.cc b/src/gn/target.cc
index 84cfbfa..5bdfdef 100644
--- a/src/gn/target.cc
+++ b/src/gn/target.cc
@@ -739,16 +739,6 @@
 }
 
 void Target::PullDependentTargetLibsFrom(const Target* dep, bool is_public) {
-  // Direct dependent libraries.
-  if (dep->output_type() == STATIC_LIBRARY ||
-      dep->output_type() == SHARED_LIBRARY ||
-      dep->output_type() == RUST_LIBRARY ||
-      dep->output_type() == SOURCE_SET ||
-      (dep->output_type() == CREATE_BUNDLE &&
-       dep->bundle_data().is_framework())) {
-    inherited_libraries_.Append(dep, 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 ||
@@ -780,64 +770,6 @@
     rust_transitive_inherited_libs_.Append(dep, true);
     rust_transitive_inheritable_libs_.Append(dep, is_public);
   }
-
-  if (dep->output_type() == SHARED_LIBRARY) {
-    // Shared library dependendencies are inherited across public shared
-    // library boundaries.
-    //
-    // In this case:
-    //   EXE -> INTERMEDIATE_SHLIB --[public]--> FINAL_SHLIB
-    // The EXE will also link to to FINAL_SHLIB. The public dependency means
-    // that the EXE can use the headers in FINAL_SHLIB so the FINAL_SHLIB
-    // will need to appear on EXE's link line.
-    //
-    // However, if the dependency is private:
-    //   EXE -> INTERMEDIATE_SHLIB --[private]--> FINAL_SHLIB
-    // the dependency will not be propagated because INTERMEDIATE_SHLIB is
-    // not granting permission to call functions from FINAL_SHLIB. If EXE
-    // wants to use functions (and link to) FINAL_SHLIB, it will need to do
-    // so explicitly.
-    //
-    // Static libraries and source sets aren't inherited across shared
-    // library boundaries because they will be linked into the shared
-    // library. Rust dylib deps are handled above and transitive deps are
-    // resolved by the compiler.
-    inherited_libraries_.AppendPublicSharedLibraries(dep->inherited_libraries(),
-                                                     is_public);
-  } else {
-    InheritedLibraries transitive;
-
-    if (!dep->IsFinal()) {
-      // The current target isn't linked, so propagate linked deps and
-      // libraries up the dependency tree.
-      for (const auto& [inherited, inherited_is_public] :
-           dep->inherited_libraries().GetOrderedAndPublicFlag()) {
-        transitive.Append(inherited, is_public && inherited_is_public);
-      }
-    } else if (dep->complete_static_lib()) {
-      // Inherit only final targets through _complete_ static libraries.
-      //
-      // Inherited final libraries aren't linked into complete static libraries.
-      // They are forwarded here so that targets that depend on complete
-      // static libraries can link them in. Conversely, since complete static
-      // libraries link in non-final targets they shouldn't be inherited.
-      for (const auto& [inherited, inherited_is_public] :
-           dep->inherited_libraries().GetOrderedAndPublicFlag()) {
-        if (inherited->IsFinal()) {
-          transitive.Append(inherited, is_public && inherited_is_public);
-        }
-      }
-    }
-
-    for (const auto& [target, pub] : transitive.GetOrderedAndPublicFlag()) {
-      // Proc macros are not linked into targets that depend on them, so do not
-      // get inherited; they are consumed by the Rust compiler and only need to
-      // be specified in --extern.
-      if (target->output_type() != RUST_PROC_MACRO) {
-        inherited_libraries_.Append(target, pub);
-      }
-    }
-  }
 }
 
 void Target::PullDependentTargetLibs() {
diff --git a/src/gn/target.h b/src/gn/target.h
index d672985..348f49f 100644
--- a/src/gn/target.h
+++ b/src/gn/target.h
@@ -14,7 +14,6 @@
 #include "gn/action_values.h"
 #include "gn/bundle_data.h"
 #include "gn/config_values.h"
-#include "gn/inherited_libraries.h"
 #include "gn/item.h"
 #include "gn/label_pattern.h"
 #include "gn/label_ptr.h"
@@ -298,10 +297,6 @@
   const LabelPtrPair<Pool>& pool() const { return pool_; }
   void set_pool(LabelPtrPair<Pool> pool) { pool_ = std::move(pool); }
 
-  const InheritedLibraries& inherited_libraries() const {
-    return inherited_libraries_;
-  }
-
   // This config represents the configuration set directly on this target.
   ConfigValues& config_values();
   const ConfigValues& config_values() const;
@@ -485,10 +480,6 @@
 
   LabelPtrPair<Pool> pool_;
 
-  // Static libraries, shared libraries, and source sets from transitive deps
-  // that need to be linked.
-  InheritedLibraries inherited_libraries_;
-
   std::vector<LabelPattern> friends_;
   std::vector<LabelPattern> assert_no_deps_;
 
diff --git a/src/gn/target_unittest.cc b/src/gn/target_unittest.cc
index 6031fed..d6554fd 100644
--- a/src/gn/target_unittest.cc
+++ b/src/gn/target_unittest.cc
@@ -203,173 +203,6 @@
   EXPECT_EQ(&all_dependent, a.all_dependent_configs()[0].ptr);
 }
 
-TEST_F(TargetTest, InheritLibs) {
-  TestWithScope setup;
-  Err err;
-
-  // Create a dependency chain:
-  //   A (executable) -> B (shared lib) -> C (static lib) -> D (source set)
-  TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
-  TestTarget b(setup, "//foo:b", Target::SHARED_LIBRARY);
-  TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
-  TestTarget d(setup, "//foo:d", Target::SOURCE_SET);
-  a.private_deps().push_back(LabelTargetPair(&b));
-  b.private_deps().push_back(LabelTargetPair(&c));
-  c.private_deps().push_back(LabelTargetPair(&d));
-
-  ASSERT_TRUE(d.OnResolved(&err));
-  ASSERT_TRUE(c.OnResolved(&err));
-  ASSERT_TRUE(b.OnResolved(&err));
-  ASSERT_TRUE(a.OnResolved(&err));
-
-  // C should have D in its inherited libs.
-  std::vector<const Target*> c_inherited = c.inherited_libraries().GetOrdered();
-  ASSERT_EQ(1u, c_inherited.size());
-  EXPECT_EQ(&d, c_inherited[0]);
-
-  // B should have C and D in its inherited libs.
-  std::vector<const Target*> b_inherited = b.inherited_libraries().GetOrdered();
-  ASSERT_EQ(2u, b_inherited.size());
-  EXPECT_EQ(&c, b_inherited[0]);
-  EXPECT_EQ(&d, b_inherited[1]);
-
-  // A should have B in its inherited libs, but not any others (the shared
-  // library will include the static library and source set).
-  std::vector<const Target*> a_inherited = a.inherited_libraries().GetOrdered();
-  ASSERT_EQ(1u, a_inherited.size());
-  EXPECT_EQ(&b, a_inherited[0]);
-}
-
-TEST_F(TargetTest, InheritCompleteStaticLib) {
-  TestWithScope setup;
-  Err err;
-
-  // Create a dependency chain:
-  //   A (executable) -> B (complete static lib) -> C (source set)
-  TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
-  TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
-  b.set_complete_static_lib(true);
-
-  const LibFile lib("foo");
-  const SourceDir lib_dir("/foo_dir/");
-  TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
-  c.config_values().libs().push_back(lib);
-  c.config_values().lib_dirs().push_back(lib_dir);
-
-  a.public_deps().push_back(LabelTargetPair(&b));
-  b.public_deps().push_back(LabelTargetPair(&c));
-
-  ASSERT_TRUE(c.OnResolved(&err));
-  ASSERT_TRUE(b.OnResolved(&err));
-  ASSERT_TRUE(a.OnResolved(&err));
-
-  // B should have C in its inherited libs.
-  std::vector<const Target*> b_inherited = b.inherited_libraries().GetOrdered();
-  ASSERT_EQ(1u, b_inherited.size());
-  EXPECT_EQ(&c, b_inherited[0]);
-
-  // A should have B in its inherited libs, but not any others (the complete
-  // static library will include the source set).
-  std::vector<const Target*> a_inherited = a.inherited_libraries().GetOrdered();
-  ASSERT_EQ(1u, a_inherited.size());
-  EXPECT_EQ(&b, a_inherited[0]);
-
-  // A should inherit the libs and lib_dirs from the C.
-  ResolvedTargetData resolved;
-  const auto& a_all_libs = resolved.GetLinkedLibraries(&a);
-  ASSERT_EQ(1u, a_all_libs.size());
-  EXPECT_EQ(lib, a_all_libs[0]);
-
-  const auto& a_all_lib_dirs = resolved.GetLinkedLibraryDirs(&a);
-  ASSERT_EQ(1u, a_all_lib_dirs.size());
-  EXPECT_EQ(lib_dir, a_all_lib_dirs[0]);
-}
-
-TEST_F(TargetTest, InheritCompleteStaticLibStaticLibDeps) {
-  TestWithScope setup;
-  Err err;
-
-  // Create a dependency chain:
-  //   A (executable) -> B (complete static lib) -> C (static lib)
-  TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
-  TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
-  b.set_complete_static_lib(true);
-  TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
-  a.public_deps().push_back(LabelTargetPair(&b));
-  b.public_deps().push_back(LabelTargetPair(&c));
-
-  ASSERT_TRUE(c.OnResolved(&err));
-  ASSERT_TRUE(b.OnResolved(&err));
-  ASSERT_TRUE(a.OnResolved(&err));
-
-  // B should have C in its inherited libs.
-  std::vector<const Target*> b_inherited = b.inherited_libraries().GetOrdered();
-  ASSERT_EQ(1u, b_inherited.size());
-  EXPECT_EQ(&c, b_inherited[0]);
-
-  // A should have B in its inherited libs, but not any others (the complete
-  // static library will include the static library).
-  std::vector<const Target*> a_inherited = a.inherited_libraries().GetOrdered();
-  ASSERT_EQ(1u, a_inherited.size());
-  EXPECT_EQ(&b, a_inherited[0]);
-}
-
-TEST_F(TargetTest, InheritCompleteStaticLibInheritedCompleteStaticLibDeps) {
-  TestWithScope setup;
-  Err err;
-
-  // Create a dependency chain:
-  //   A (executable) -> B (complete static lib) -> C (complete static lib)
-  TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
-  TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
-  b.set_complete_static_lib(true);
-  TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
-  c.set_complete_static_lib(true);
-
-  a.private_deps().push_back(LabelTargetPair(&b));
-  b.private_deps().push_back(LabelTargetPair(&c));
-
-  ASSERT_TRUE(c.OnResolved(&err));
-  ASSERT_TRUE(b.OnResolved(&err));
-  ASSERT_TRUE(a.OnResolved(&err));
-
-  // B should have C in its inherited libs.
-  std::vector<const Target*> b_inherited = b.inherited_libraries().GetOrdered();
-  ASSERT_EQ(1u, b_inherited.size());
-  EXPECT_EQ(&c, b_inherited[0]);
-
-  // A should have B and C in its inherited libs.
-  std::vector<const Target*> a_inherited = a.inherited_libraries().GetOrdered();
-  ASSERT_EQ(2u, a_inherited.size());
-  EXPECT_EQ(&b, a_inherited[0]);
-  EXPECT_EQ(&c, a_inherited[1]);
-}
-
-TEST_F(TargetTest, NoActionDepPropgation) {
-  TestWithScope setup;
-  Err err;
-
-  // Create a dependency chain:
-  //   A (exe) -> B (action) -> C (source_set)
-  {
-    TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
-    TestTarget b(setup, "//foo:b", Target::ACTION);
-    TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
-
-    a.private_deps().push_back(LabelTargetPair(&b));
-    b.private_deps().push_back(LabelTargetPair(&c));
-
-    ASSERT_TRUE(c.OnResolved(&err));
-    ASSERT_TRUE(b.OnResolved(&err));
-    ASSERT_TRUE(a.OnResolved(&err));
-
-    // The executable should not have inherited the source set across the
-    // action.
-    std::vector<const Target*> libs = a.inherited_libraries().GetOrdered();
-    ASSERT_TRUE(libs.empty());
-  }
-}
-
 TEST_F(TargetTest, GetComputedOutputName) {
   TestWithScope setup;
   Err err;
@@ -934,48 +767,6 @@
   EXPECT_EQ("//out/Debug/one", computed_outputs[0].value());
 }
 
-// Shared libraries should be inherited across public shared library
-// boundaries.
-TEST_F(TargetTest, SharedInheritance) {
-  TestWithScope setup;
-  Err err;
-
-  // Create two leaf shared libraries.
-  TestTarget pub(setup, "//foo:pub", Target::SHARED_LIBRARY);
-  ASSERT_TRUE(pub.OnResolved(&err));
-
-  TestTarget priv(setup, "//foo:priv", Target::SHARED_LIBRARY);
-  ASSERT_TRUE(priv.OnResolved(&err));
-
-  // Intermediate shared library with the leaf shared libraries as
-  // dependencies, one public, one private.
-  TestTarget inter(setup, "//foo:inter", Target::SHARED_LIBRARY);
-  inter.public_deps().push_back(LabelTargetPair(&pub));
-  inter.private_deps().push_back(LabelTargetPair(&priv));
-  ASSERT_TRUE(inter.OnResolved(&err));
-
-  // The intermediate shared library should have both "pub" and "priv" in its
-  // inherited libraries.
-  std::vector<const Target*> inter_inherited =
-      inter.inherited_libraries().GetOrdered();
-  ASSERT_EQ(2u, inter_inherited.size());
-  EXPECT_EQ(&pub, inter_inherited[0]);
-  EXPECT_EQ(&priv, inter_inherited[1]);
-
-  // Make a toplevel executable target depending on the intermediate one.
-  TestTarget exe(setup, "//foo:exe", Target::SHARED_LIBRARY);
-  exe.private_deps().push_back(LabelTargetPair(&inter));
-  ASSERT_TRUE(exe.OnResolved(&err));
-
-  // The exe's inherited libraries should be "inter" (because it depended
-  // directly on it) and "pub" (because inter depended publicly on it).
-  std::vector<const Target*> exe_inherited =
-      exe.inherited_libraries().GetOrdered();
-  ASSERT_EQ(2u, exe_inherited.size());
-  EXPECT_EQ(&inter, exe_inherited[0]);
-  EXPECT_EQ(&pub, exe_inherited[1]);
-}
-
 TEST_F(TargetTest, GeneratedInputs) {
   TestWithScope setup;
   Err err;