Allow Rust targets to link against Rust cdylibs There was previously a deficiency in the Rust binary target generator that caused GN to fail to emit a link argument for Rust cdylib dependencies. This fixes the issue by linking against Rust cdylibs the same way that other non-Rust native dependencies are handled. This also fixes an issue in the unit test toolchain that prevented Rust cdylib/dylib outputs from being set. Fixes https://bugs.chromium.org/p/gn/issues/detail?id=233 . Change-Id: Ief9c5f0dd652c0430ada756cbe09b5800d069962 Reviewed-on: https://gn-review.googlesource.com/c/gn/+/11320 Reviewed-by: Brett Wilson <brettw@chromium.org> Reviewed-by: Tyler Mandry <tmandry@google.com> Commit-Queue: Brett Wilson <brettw@chromium.org>
diff --git a/src/gn/json_project_writer_unittest.cc b/src/gn/json_project_writer_unittest.cc index a22511b..1915c30 100644 --- a/src/gn/json_project_writer_unittest.cc +++ b/src/gn/json_project_writer_unittest.cc
@@ -172,7 +172,7 @@ "lib_switch": "-l", "linker_arg": "-Clink-arg=", "output_prefix": "lib", - "outputs": [ "" ] + "outputs": [ "{{target_out_dir}}/{{target_output_name}}{{output_extension}}" ] }, "rust_dylib": { "command": "{{rustenv}} rustc --crate-name {{crate_name}} {{source}} --crate-type {{crate_type}} {{rustflags}} -o {{output}} {{rustdeps}} {{externs}}", @@ -182,7 +182,7 @@ "lib_switch": "-l", "linker_arg": "-Clink-arg=", "output_prefix": "lib", - "outputs": [ "" ] + "outputs": [ "{{target_out_dir}}/{{target_output_name}}{{output_extension}}" ] }, "rust_macro": { "command": "{{rustenv}} rustc --crate-name {{crate_name}} {{source}} --crate-type {{crate_type}} {{rustflags}} -o {{output}} {{rustdeps}} {{externs}}", @@ -391,7 +391,7 @@ "lib_switch": "-l", "linker_arg": "-Clink-arg=", "output_prefix": "lib", - "outputs": [ "" ] + "outputs": [ "{{target_out_dir}}/{{target_output_name}}{{output_extension}}" ] }, "rust_dylib": { "command": "{{rustenv}} rustc --crate-name {{crate_name}} {{source}} --crate-type {{crate_type}} {{rustflags}} -o {{output}} {{rustdeps}} {{externs}}", @@ -401,7 +401,7 @@ "lib_switch": "-l", "linker_arg": "-Clink-arg=", "output_prefix": "lib", - "outputs": [ "" ] + "outputs": [ "{{target_out_dir}}/{{target_output_name}}{{output_extension}}" ] }, "rust_macro": { "command": "{{rustenv}} rustc --crate-name {{crate_name}} {{source}} --crate-type {{crate_type}} {{rustflags}} -o {{output}} {{rustdeps}} {{externs}}", @@ -634,7 +634,7 @@ "lib_switch": "-l", "linker_arg": "-Clink-arg=", "output_prefix": "lib", - "outputs": [ "" ] + "outputs": [ "{{target_out_dir}}/{{target_output_name}}{{output_extension}}" ] }, "rust_dylib": { "command": "{{rustenv}} rustc --crate-name {{crate_name}} {{source}} --crate-type {{crate_type}} {{rustflags}} -o {{output}} {{rustdeps}} {{externs}}", @@ -644,7 +644,7 @@ "lib_switch": "-l", "linker_arg": "-Clink-arg=", "output_prefix": "lib", - "outputs": [ "" ] + "outputs": [ "{{target_out_dir}}/{{target_output_name}}{{output_extension}}" ] }, "rust_macro": { "command": "{{rustenv}} rustc --crate-name {{crate_name}} {{source}} --crate-type {{crate_type}} {{rustflags}} -o {{output}} {{rustdeps}} {{externs}}",
diff --git a/src/gn/ninja_rust_binary_target_writer.cc b/src/gn/ninja_rust_binary_target_writer.cc index 38f4686..568c2b4 100644 --- a/src/gn/ninja_rust_binary_target_writer.cc +++ b/src/gn/ninja_rust_binary_target_writer.cc
@@ -154,7 +154,9 @@ order_only_deps.push_back(non_linkable_dep->dependency_output_file()); } for (const auto* linkable_dep : classified_deps.linkable_deps) { - if (linkable_dep->source_types_used().RustSourceUsed()) { + // Rust cdylibs are treated as non-Rust dependencies for linking purposes. + if (linkable_dep->source_types_used().RustSourceUsed() && + linkable_dep->rust_values().crate_type() != RustValues::CRATE_CDYLIB) { rustdeps.push_back(linkable_dep->link_output_file()); } else { nonrustdeps.push_back(linkable_dep->link_output_file());
diff --git a/src/gn/ninja_rust_binary_target_writer_unittest.cc b/src/gn/ninja_rust_binary_target_writer_unittest.cc index 6840b72..a65a961 100644 --- a/src/gn/ninja_rust_binary_target_writer_unittest.cc +++ b/src/gn/ninja_rust_binary_target_writer_unittest.cc
@@ -890,3 +890,80 @@ EXPECT_EQ(expected, out_str) << expected << "\n" << out_str; } } + +TEST_F(NinjaRustBinaryTargetWriterTest, CdylibDeps) { + Err err; + TestWithScope setup; + Target cdylib(setup.settings(), Label(SourceDir("//bar/"), "mylib")); + cdylib.set_output_type(Target::SHARED_LIBRARY); + cdylib.visibility().SetPublic(); + SourceFile barlib("//bar/lib.rs"); + cdylib.sources().push_back(barlib); + cdylib.source_types_used().Set(SourceFile::SOURCE_RS); + cdylib.rust_values().set_crate_type(RustValues::CRATE_CDYLIB); + cdylib.rust_values().set_crate_root(barlib); + cdylib.rust_values().crate_name() = "mylib"; + cdylib.SetToolchain(setup.toolchain()); + ASSERT_TRUE(cdylib.OnResolved(&err)); + { + std::ostringstream out; + NinjaRustBinaryTargetWriter writer(&cdylib, out); + writer.Run(); + const char expected[] = + "crate_name = mylib\n" + "crate_type = cdylib\n" + "output_extension = .so\n" + "output_dir = \n" + "rustflags =\n" + "rustenv =\n" + "root_out_dir = .\n" + "target_out_dir = obj/bar\n" + "target_output_name = libmylib\n" + "\n" + "build obj/bar/libmylib.so: rust_cdylib ../../bar/lib.rs | " + "../../bar/lib.rs\n" + " externs =\n" + " rustdeps =\n" + " sources = ../../bar/lib.rs\n"; + std::string out_str = out.str(); + EXPECT_EQ(expected, out_str) << expected << "\n" << out_str; + } + + 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.private_deps().push_back(LabelTargetPair(&cdylib)); + 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_extension = \n" + "output_dir = \n" + "rustflags =\n" + "rustenv =\n" + "root_out_dir = .\n" + "target_out_dir = obj/foo\n" + "target_output_name = bar\n" + "\n" + "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs " + "../../foo/main.rs obj/bar/libmylib.so\n" + " externs =\n" + " rustdeps = -Ldependency=obj/bar -Lnative=obj/bar " + "-Clink-arg=obj/bar/libmylib.so\n" + " sources = ../../foo/source.rs ../../foo/main.rs\n"; + std::string out_str = out.str(); + EXPECT_EQ(expected, out_str) << expected << "\n" << out_str; + } +}
diff --git a/src/gn/test_with_scope.cc b/src/gn/test_with_scope.cc index 583eebb..757dd34 100644 --- a/src/gn/test_with_scope.cc +++ b/src/gn/test_with_scope.cc
@@ -252,7 +252,7 @@ cdylib_tool->set_output_prefix("lib"); cdylib_tool->set_default_output_extension(".so"); cdylib_tool->set_outputs(SubstitutionList::MakeForTest( - "{{root_output_dir}}/{{target_output_name}}{{output_extension}}")); + "{{target_out_dir}}/{{target_output_name}}{{output_extension}}")); toolchain->SetTool(std::move(cdylib_tool)); // DYLIB @@ -265,7 +265,7 @@ dylib_tool->set_output_prefix("lib"); dylib_tool->set_default_output_extension(".so"); dylib_tool->set_outputs(SubstitutionList::MakeForTest( - "{{root_output_dir}}/{{target_output_name}}{{output_extension}}")); + "{{target_out_dir}}/{{target_output_name}}{{output_extension}}")); toolchain->SetTool(std::move(dylib_tool)); // RUST_PROC_MACRO