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;
+ }
+}