Add -Lnative link search paths for non-Rust deps

Make non-Rust deps of Rust targets use -Lnative instead of -Ldependency

Change-Id: I205c60bde0ff2d969a5ff6cbc7990666896b4999
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/5160
Commit-Queue: Julie Hockett <juliehockett@google.com>
Reviewed-by: Brett Wilson <brettw@google.com>
diff --git a/tools/gn/ninja_rust_binary_target_writer.cc b/tools/gn/ninja_rust_binary_target_writer.cc
index 869cac8..3014df9 100644
--- a/tools/gn/ninja_rust_binary_target_writer.cc
+++ b/tools/gn/ninja_rust_binary_target_writer.cc
@@ -127,12 +127,17 @@
       order_only_deps.push_back(input_dep);
 
     std::vector<OutputFile> rustdeps;
+    std::vector<OutputFile> nonrustdeps;
     for (const auto* non_linkable_dep : non_linkable_deps) {
       order_only_deps.push_back(non_linkable_dep->dependency_output_file());
     }
 
     for (const auto* linkable_dep : linkable_deps) {
-      rustdeps.push_back(linkable_dep->dependency_output_file());
+      if (linkable_dep->source_types_used().RustSourceUsed()) {
+        rustdeps.push_back(linkable_dep->dependency_output_file());
+      } else {
+        nonrustdeps.push_back(linkable_dep->dependency_output_file());
+      }
       deps.push_back(linkable_dep->dependency_output_file());
     }
 
@@ -142,7 +147,7 @@
     WriteCompilerBuildLine(target_->rust_values().crate_root(), deps.vector(),
                            order_only_deps, tool_->name(), tool_outputs);
     WriteExterns();
-    WriteRustdeps(rustdeps);
+    WriteRustdeps(rustdeps, nonrustdeps);
     WriteEdition();
   }
 }
@@ -191,7 +196,8 @@
 }
 
 void NinjaRustBinaryTargetWriter::WriteRustdeps(
-    std::vector<OutputFile>& rustdeps) {
+    const std::vector<OutputFile>& rustdeps,
+    const std::vector<OutputFile>& nonrustdeps) {
   if (rustdeps.empty())
     return;
   out_ << "  rustdeps =";
@@ -201,6 +207,13 @@
         out_, rustdep.AsSourceFile(settings_->build_settings()).GetDir(),
         PathOutput::DIR_NO_LAST_SLASH);
   }
+
+  for (const auto& rustdep : nonrustdeps) {
+    out_ << " -Lnative=";
+    path_output_.WriteDir(
+        out_, rustdep.AsSourceFile(settings_->build_settings()).GetDir(),
+        PathOutput::DIR_NO_LAST_SLASH);
+  }
   out_ << std::endl;
 }
 
diff --git a/tools/gn/ninja_rust_binary_target_writer.h b/tools/gn/ninja_rust_binary_target_writer.h
index ab738e2..4302abf 100644
--- a/tools/gn/ninja_rust_binary_target_writer.h
+++ b/tools/gn/ninja_rust_binary_target_writer.h
@@ -25,7 +25,8 @@
   void WriteSources(const OutputFile& input_dep,
                     const std::vector<OutputFile>& order_only_deps);
   void WriteExterns();
-  void WriteRustdeps(std::vector<OutputFile>& rustdeps);
+  void WriteRustdeps(const std::vector<OutputFile>& rustdeps,
+                     const std::vector<OutputFile>& nonrustdeps);
   void WriteEdition();
 
   const RustTool* tool_;
diff --git a/tools/gn/ninja_rust_binary_target_writer_unittest.cc b/tools/gn/ninja_rust_binary_target_writer_unittest.cc
index 9d8aee1..43bac89 100644
--- a/tools/gn/ninja_rust_binary_target_writer_unittest.cc
+++ b/tools/gn/ninja_rust_binary_target_writer_unittest.cc
@@ -245,3 +245,68 @@
     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
   }
 }
+
+TEST_F(NinjaRustBinaryTargetWriterTest, NonRustDeps) {
+  Err err;
+  TestWithScope setup;
+
+  Target rlib(setup.settings(), Label(SourceDir("//bar/"), "mylib"));
+  rlib.set_output_type(Target::RUST_LIBRARY);
+  rlib.visibility().SetPublic();
+  SourceFile barlib("//bar/lib.rs");
+  rlib.sources().push_back(SourceFile("//bar/mylib.rs"));
+  rlib.sources().push_back(barlib);
+  rlib.source_types_used().Set(SourceFile::SOURCE_RS);
+  rlib.rust_values().set_crate_root(barlib);
+  rlib.rust_values().crate_name() = "mylib";
+  rlib.rust_values().edition() = "2018";
+  rlib.SetToolchain(setup.toolchain());
+  ASSERT_TRUE(rlib.OnResolved(&err));
+
+  Target staticlib(setup.settings(), Label(SourceDir("//foo/"), "static"));
+  staticlib.set_output_type(Target::STATIC_LIBRARY);
+  staticlib.visibility().SetPublic();
+  staticlib.sources().push_back(SourceFile("//foo/static.cpp"));
+  staticlib.source_types_used().Set(SourceFile::SOURCE_CPP);
+  staticlib.SetToolchain(setup.toolchain());
+  ASSERT_TRUE(staticlib.OnResolved(&err));
+
+  Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
+  target.set_output_type(Target::EXECUTABLE);
+  target.visibility().SetPublic();
+  SourceFile main("//foo/main.rs");
+  target.sources().push_back(SourceFile("//foo/source.rs"));
+  target.sources().push_back(main);
+  target.source_types_used().Set(SourceFile::SOURCE_RS);
+  target.rust_values().set_crate_root(main);
+  target.rust_values().crate_name() = "foo_bar";
+  target.rust_values().edition() = "2018";
+  target.private_deps().push_back(LabelTargetPair(&rlib));
+  target.private_deps().push_back(LabelTargetPair(&staticlib));
+  target.SetToolchain(setup.toolchain());
+  ASSERT_TRUE(target.OnResolved(&err));
+
+  {
+    std::ostringstream out;
+    NinjaRustBinaryTargetWriter writer(&target, out);
+    writer.Run();
+
+    const char expected[] =
+        "crate_name = foo_bar\n"
+        "crate_type = bin\n"
+        "rustc_output_extension = \n"
+        "rustflags =\n"
+        "rustenv =\n"
+        "root_out_dir = .\n"
+        "target_out_dir = obj/foo\n"
+        "target_output_name = bar\n"
+        "\n"
+        "build obj/foo/foo_bar: rustc ../../foo/main.rs | ../../foo/source.rs "
+        "../../foo/main.rs obj/bar/libmylib.rlib obj/foo/libstatic.a\n"
+        "  externs = --extern mylib=obj/bar/libmylib.rlib\n"
+        "  rustdeps = -Ldependency=obj/bar -Lnative=obj/foo\n"
+        "  edition = 2018\n";
+    std::string out_str = out.str();
+    EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
+  }
+}
\ No newline at end of file