Make dynamic link switch... dynamic.
Previously gn hard-coded the linker switch -Bdynamic
which is incorrect on platforms where MSVC tools are used for linking.
This CL parameterizes that flag.
Bug: https://crbug.com/1271215
Change-Id: I379c86b5eb166d973bc502cdae2552b9e1c6a6a7
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/12460
Commit-Queue: Tyler Mandry <tmandry@google.com>
Reviewed-by: Takuto Ikuta <tikuta@google.com>
Reviewed-by: Tyler Mandry <tmandry@google.com>
diff --git a/docs/reference.md b/docs/reference.md
index eca3032..d04912a 100644
--- a/docs/reference.md
+++ b/docs/reference.md
@@ -3870,6 +3870,20 @@
process, but may be used when generating metadata for rust-analyzer.
(See --export-rust-project). It enables such metadata to include
information about the Rust standard library.
+
+ dynamic_link_switch
+ Valid for: Rust tools which link
+
+ A switch to be optionally inserted into linker command lines
+ to indicate that subsequent items may be dynamically linked.
+ For ld-like linkers, -Clink-arg=-Bdynamic may be a good choice.
+ This switch is inserted by gn into rustc command lines before
+ listing any non-Rust dependencies. This may be necessary because
+ sometimes rustc puts the linker into a mode where it would otherwise
+ link against static libraries by default. This flag will be
+ inserted into the {{rustdeps}} variable at the appropriate place;
+ {{ldflags}} can't be used for the same purpose because the flags
+ may not be inserted at the desired place in the command line.
```
#### **Expansions for tool variables**
diff --git a/src/gn/function_toolchain.cc b/src/gn/function_toolchain.cc
index b0fc5e1..b36b1e9 100644
--- a/src/gn/function_toolchain.cc
+++ b/src/gn/function_toolchain.cc
@@ -592,6 +592,20 @@
(See --export-rust-project). It enables such metadata to include
information about the Rust standard library.
+ dynamic_link_switch
+ Valid for: Rust tools which link
+
+ A switch to be optionally inserted into linker command lines
+ to indicate that subsequent items may be dynamically linked.
+ For ld-like linkers, -Clink-arg=-Bdynamic may be a good choice.
+ This switch is inserted by gn into rustc command lines before
+ listing any non-Rust dependencies. This may be necessary because
+ sometimes rustc puts the linker into a mode where it would otherwise
+ link against static libraries by default. This flag will be
+ inserted into the {{rustdeps}} variable at the appropriate place;
+ {{ldflags}} can't be used for the same purpose because the flags
+ may not be inserted at the desired place in the command line.
+
)" // String break to prevent overflowing the 16K max VC string length.
R"(Expansions for tool variables
diff --git a/src/gn/ninja_rust_binary_target_writer.cc b/src/gn/ninja_rust_binary_target_writer.cc
index 06bce2f..694f332 100644
--- a/src/gn/ninja_rust_binary_target_writer.cc
+++ b/src/gn/ninja_rust_binary_target_writer.cc
@@ -363,7 +363,7 @@
// that allows dynamic linking, as rustc may have previously put it into
// static-only mode.
if (nonrustdeps.size() > 0) {
- out_ << " -Clink-arg=-Bdynamic";
+ out_ << " " << tool_->dynamic_link_switch();
}
for (const auto& nonrustdep : nonrustdeps) {
out_ << " -Clink-arg=";
diff --git a/src/gn/ninja_rust_binary_target_writer_unittest.cc b/src/gn/ninja_rust_binary_target_writer_unittest.cc
index 41a9fdd..21b104f 100644
--- a/src/gn/ninja_rust_binary_target_writer_unittest.cc
+++ b/src/gn/ninja_rust_binary_target_writer_unittest.cc
@@ -896,7 +896,7 @@
" source_file_part = lib.rs\n"
" source_name_part = lib\n"
" externs =\n"
- " rustdeps = -Lnative=obj/foo -Clink-arg=-Bdynamic "
+ " rustdeps = -Lnative=obj/foo -Clink-arg=-Balternative-dynamic "
"-Clink-arg=obj/foo/libstatic.a\n"
" ldflags =\n"
" sources = ../../baz/lib.rs\n";
diff --git a/src/gn/rust_tool.cc b/src/gn/rust_tool.cc
index eaffb5b..5f2c2de 100644
--- a/src/gn/rust_tool.cc
+++ b/src/gn/rust_tool.cc
@@ -21,6 +21,7 @@
set_lib_dir_switch("-Lnative=");
set_lib_switch("-l");
set_linker_arg("-Clink-arg=");
+ set_dynamic_link_switch("-Clink-arg=-Bdynamic");
}
RustTool::~RustTool() = default;
@@ -115,6 +116,13 @@
if (!ReadString(scope, "rust_sysroot", &rust_sysroot_, err)) {
return false;
}
+
+ if (MayLink()) {
+ if (!ReadString(scope, "dynamic_link_switch", &dynamic_link_switch_, err)) {
+ return false;
+ }
+ }
+
return true;
}
diff --git a/src/gn/rust_tool.h b/src/gn/rust_tool.h
index 7b4f7ac..341c48f 100644
--- a/src/gn/rust_tool.h
+++ b/src/gn/rust_tool.h
@@ -44,8 +44,15 @@
std::string_view GetSysroot() const;
+ const std::string& dynamic_link_switch() const { return dynamic_link_switch_; }
+ void set_dynamic_link_switch(std::string s) {
+ DCHECK(!complete_);
+ dynamic_link_switch_ = std::move(s);
+ }
+
private:
std::string rust_sysroot_;
+ std::string dynamic_link_switch_;
bool SetOutputExtension(const Value* value, std::string* var, Err* err);
bool ReadOutputsPatternList(Scope* scope,
diff --git a/src/gn/test_with_scope.cc b/src/gn/test_with_scope.cc
index 757dd34..638bf32 100644
--- a/src/gn/test_with_scope.cc
+++ b/src/gn/test_with_scope.cc
@@ -242,7 +242,7 @@
"{{target_out_dir}}/{{source_name_part}}.o"));
toolchain->SetTool(std::move(swift_tool));
- // CDYLIB
+ // RUST CDYLIB
std::unique_ptr<Tool> cdylib_tool = Tool::CreateTool(RustTool::kRsToolCDylib);
SetCommandForTool(
"{{rustenv}} rustc --crate-name {{crate_name}} {{source}} "
@@ -255,7 +255,7 @@
"{{target_out_dir}}/{{target_output_name}}{{output_extension}}"));
toolchain->SetTool(std::move(cdylib_tool));
- // DYLIB
+ // RUST DYLIB
std::unique_ptr<Tool> dylib_tool = Tool::CreateTool(RustTool::kRsToolDylib);
SetCommandForTool(
"{{rustenv}} rustc --crate-name {{crate_name}} {{source}} "
@@ -295,7 +295,7 @@
"{{target_out_dir}}/{{target_output_name}}{{output_extension}}"));
toolchain->SetTool(std::move(rlib_tool));
- // STATICLIB
+ // RUST STATICLIB
std::unique_ptr<Tool> staticlib_tool =
Tool::CreateTool(RustTool::kRsToolStaticlib);
SetCommandForTool(
@@ -307,6 +307,7 @@
staticlib_tool->set_default_output_extension(".a");
staticlib_tool->set_outputs(SubstitutionList::MakeForTest(
"{{target_out_dir}}/{{target_output_name}}{{output_extension}}"));
+ static_cast<RustTool*>(staticlib_tool.get())->set_dynamic_link_switch("-Clink-arg=-Balternative-dynamic");
toolchain->SetTool(std::move(staticlib_tool));
toolchain->ToolchainSetupComplete();