Propagate Rust libraries through SOURCE_SET targets. Inherited private deps should be included as -Ldependency flags to the Rust compiler. Inherited public deps should also be listed as -Ldependency, but also be listed as a full path to the rlib via --extern. R=brettw@chromium.org, digit@chromium.org Bug: 276, 281 Change-Id: I64556b419651f9a54d35cb1db0f29acb7f8bb2d6 Reviewed-on: https://gn-review.googlesource.com/c/gn/+/13280 Reviewed-by: David Turner <digit@google.com> Reviewed-by: Brett Wilson <brettw@chromium.org> Commit-Queue: Brett Wilson <brettw@chromium.org>
diff --git a/src/gn/ninja_rust_binary_target_writer_unittest.cc b/src/gn/ninja_rust_binary_target_writer_unittest.cc index 308e742..68d5970 100644 --- a/src/gn/ninja_rust_binary_target_writer_unittest.cc +++ b/src/gn/ninja_rust_binary_target_writer_unittest.cc
@@ -1659,3 +1659,90 @@ EXPECT_EQ(expected, out_str) << expected << "\n" << out_str; } } + +TEST_F(NinjaRustBinaryTargetWriterTest, TransitiveRustDepsThroughSourceSet) { + Err err; + TestWithScope setup; + + Target rlib_pub(setup.settings(), + Label(SourceDir("//public/"), "behind_sourceset_public")); + rlib_pub.set_output_type(Target::RUST_LIBRARY); + rlib_pub.visibility().SetPublic(); + SourceFile rlib_pub_root("//public/lib.rs"); + rlib_pub.sources().push_back( + SourceFile("//public/behind_sourceset_public.rs")); + rlib_pub.sources().push_back(rlib_pub_root); + rlib_pub.source_types_used().Set(SourceFile::SOURCE_RS); + rlib_pub.rust_values().set_crate_root(rlib_pub_root); + rlib_pub.rust_values().crate_name() = "behind_sourceset_public"; + rlib_pub.SetToolchain(setup.toolchain()); + ASSERT_TRUE(rlib_pub.OnResolved(&err)); + + Target rlib_priv(setup.settings(), + Label(SourceDir("//private/"), "behind_sourceset_private")); + rlib_priv.set_output_type(Target::RUST_LIBRARY); + rlib_priv.visibility().SetPublic(); + SourceFile rlib_priv_root("//private/lib.rs"); + rlib_priv.sources().push_back( + SourceFile("//private/behind_sourceset_private.rs")); + rlib_priv.sources().push_back(rlib_priv_root); + rlib_priv.source_types_used().Set(SourceFile::SOURCE_RS); + rlib_priv.rust_values().set_crate_root(rlib_priv_root); + rlib_priv.rust_values().crate_name() = "behind_sourceset_private"; + rlib_priv.SetToolchain(setup.toolchain()); + ASSERT_TRUE(rlib_priv.OnResolved(&err)); + + Target sset(setup.settings(), Label(SourceDir("//sset/"), "bar")); + sset.set_output_type(Target::SOURCE_SET); + sset.visibility().SetPublic(); + sset.sources().push_back(SourceFile("//sset/input1.cc")); + sset.source_types_used().Set(SourceFile::SOURCE_CPP); + sset.SetToolchain(setup.toolchain()); + sset.public_deps().push_back(LabelTargetPair(&rlib_pub)); + sset.private_deps().push_back(LabelTargetPair(&rlib_priv)); + ASSERT_TRUE(sset.OnResolved(&err)); + + Target target(setup.settings(), Label(SourceDir("//linked/"), "exe")); + target.set_output_type(Target::EXECUTABLE); + target.visibility().SetPublic(); + SourceFile main("//linked/exe.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() = "exe"; + target.private_deps().push_back(LabelTargetPair(&sset)); + target.SetToolchain(setup.toolchain()); + ASSERT_TRUE(target.OnResolved(&err)); + + { + std::ostringstream out; + NinjaRustBinaryTargetWriter writer(&target, out); + writer.Run(); + + const char expected[] = + "crate_name = exe\n" + "crate_type = bin\n" + "output_extension = \n" + "output_dir = \n" + "rustflags =\n" + "rustenv =\n" + "root_out_dir = .\n" + "target_out_dir = obj/linked\n" + "target_output_name = exe\n" + "\n" + "build ./exe: rust_bin ../../linked/exe.rs | ../../linked/exe.rs " + "obj/sset/bar.input1.o obj/public/libbehind_sourceset_public.rlib " + "obj/private/libbehind_sourceset_private.rlib || obj/sset/bar.stamp\n" + " source_file_part = exe.rs\n" + " source_name_part = exe\n" + " externs = --extern " + "behind_sourceset_public=obj/public/libbehind_sourceset_public.rlib\n" + " rustdeps = -Ldependency=obj/public -Ldependency=obj/private " + "-Lnative=obj/sset -Clink-arg=-Bdynamic " + "-Clink-arg=obj/sset/bar.input1.o\n" + " ldflags =\n" + " sources = ../../linked/exe.rs\n"; + std::string out_str = out.str(); + EXPECT_EQ(expected, out_str) << expected << "\n" << out_str; + } +}
diff --git a/src/gn/target.cc b/src/gn/target.cc index 55649d4..f0c897e 100644 --- a/src/gn/target.cc +++ b/src/gn/target.cc
@@ -770,7 +770,8 @@ // transitively part of the current target. if (dep->output_type() == STATIC_LIBRARY || dep->output_type() == SHARED_LIBRARY || - dep->output_type() == RUST_LIBRARY || dep->output_type() == GROUP) { + 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