Process transitive dependecies for externs When generating Rust externs, we need to handle both direct and transitive dependencies i.e. dependencies coming from public deps. Bug: crbug.com/gn/105 Change-Id: I6bc89358f8c42f1cf1fc0e3527516c13b5a9f842 Reviewed-on: https://gn-review.googlesource.com/c/gn/+/5820 Commit-Queue: Petr Hosek <phosek@google.com> Reviewed-by: Brett Wilson <brettw@chromium.org>
diff --git a/tools/gn/ninja_rust_binary_target_writer.cc b/tools/gn/ninja_rust_binary_target_writer.cc index e1e762c..1e4efbb 100644 --- a/tools/gn/ninja_rust_binary_target_writer.cc +++ b/tools/gn/ninja_rust_binary_target_writer.cc
@@ -162,7 +162,12 @@ target_, tool_, tool_->outputs(), &tool_outputs); WriteCompilerBuildLine(target_->rust_values().crate_root(), deps.vector(), order_only_deps, tool_->name(), tool_outputs); - WriteExterns(); + + std::vector<const Target*> extern_deps(linkable_deps.vector()); + std::copy(non_linkable_deps.begin(), non_linkable_deps.end(), + std::back_inserter(extern_deps)); + WriteExterns(extern_deps); + WriteRustdeps(rustdeps, nonrustdeps); WriteEdition(); } @@ -185,12 +190,13 @@ WriteSharedVars(subst); } -void NinjaRustBinaryTargetWriter::WriteExterns() { +void NinjaRustBinaryTargetWriter::WriteExterns( + const std::vector<const Target*>& deps) { std::vector<const Target*> externs; - for (const auto& pair : target_->GetDeps(Target::DEPS_LINKED)) { - if (pair.ptr->output_type() == Target::RUST_LIBRARY || - pair.ptr->rust_values().crate_type() == RustValues::CRATE_PROC_MACRO) { - externs.push_back(pair.ptr); + for (const Target* target : deps) { + if (target->output_type() == Target::RUST_LIBRARY || + target->rust_values().crate_type() == RustValues::CRATE_PROC_MACRO) { + externs.push_back(target); } } if (externs.empty())
diff --git a/tools/gn/ninja_rust_binary_target_writer.h b/tools/gn/ninja_rust_binary_target_writer.h index 4302abf..31d636b 100644 --- a/tools/gn/ninja_rust_binary_target_writer.h +++ b/tools/gn/ninja_rust_binary_target_writer.h
@@ -24,7 +24,7 @@ void WriteCompilerVars(); void WriteSources(const OutputFile& input_dep, const std::vector<OutputFile>& order_only_deps); - void WriteExterns(); + void WriteExterns(const std::vector<const Target*>& deps); void WriteRustdeps(const std::vector<OutputFile>& rustdeps, const std::vector<OutputFile>& nonrustdeps); void WriteEdition();
diff --git a/tools/gn/ninja_rust_binary_target_writer_unittest.cc b/tools/gn/ninja_rust_binary_target_writer_unittest.cc index e247f3d..5749c84 100644 --- a/tools/gn/ninja_rust_binary_target_writer_unittest.cc +++ b/tools/gn/ninja_rust_binary_target_writer_unittest.cc
@@ -185,7 +185,8 @@ "\n" "build obj/foo/foo_bar: rustc ../../foo/main.rs | ../../foo/source.rs " "../../foo/main.rs obj/foo/libdirect.rlib obj/bar/libmylib.rlib\n" - " externs = --extern direct=obj/foo/libdirect.rlib\n" + " externs = --extern direct=obj/foo/libdirect.rlib --extern " + "mylib=obj/bar/libmylib.rlib\n" " rustdeps = -Ldependency=obj/foo -Ldependency=obj/bar\n" " edition = 2018\n"; std::string out_str = out.str(); @@ -450,3 +451,91 @@ EXPECT_EQ(expected, out_str) << expected << "\n" << out_str; } } + +TEST_F(NinjaRustBinaryTargetWriterTest, GroupDeps) { + 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)); + + { + std::ostringstream out; + NinjaRustBinaryTargetWriter writer(&rlib, out); + writer.Run(); + + const char expected[] = + "crate_name = mylib\n" + "crate_type = rlib\n" + "output_dir = \n" + "rustc_output_extension = .rlib\n" + "rustc_output_prefix = lib\n" + "rustflags =\n" + "rustenv =\n" + "root_out_dir = .\n" + "target_out_dir = obj/bar\n" + "target_output_name = mylib\n" + "\n" + "build obj/bar/libmylib.rlib: rustc ../../bar/lib.rs | " + "../../bar/mylib.rs ../../bar/lib.rs\n" + " edition = 2018\n"; + std::string out_str = out.str(); + EXPECT_EQ(expected, out_str) << out_str; + } + + Target group(setup.settings(), Label(SourceDir("//baz/"), "group")); + group.set_output_type(Target::GROUP); + group.visibility().SetPublic(); + group.public_deps().push_back(LabelTargetPair(&rlib)); + group.SetToolchain(setup.toolchain()); + ASSERT_TRUE(group.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(&group)); + 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" + "output_dir = \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/baz/group.stamp\n" + " externs = --extern mylib=obj/bar/libmylib.rlib\n" + " rustdeps = -Ldependency=obj/bar\n" + " edition = 2018\n"; + std::string out_str = out.str(); + EXPECT_EQ(expected, out_str) << expected << "\n" << out_str; + } +}