about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs70
-rw-r--r--tests/run-make/pass-linker-flags-flavor/Makefile8
-rw-r--r--tests/run-make/pass-linker-flags-flavor/rs.rs1
4 files changed, 49 insertions, 34 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index ac13d61229e..be895417bbe 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -44,7 +44,7 @@ use tempfile::Builder as TempFileBuilder;
 use itertools::Itertools;
 use std::cell::OnceCell;
 use std::collections::BTreeSet;
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
 use std::fs::{read, File, OpenOptions};
 use std::io::{BufWriter, Write};
 use std::ops::Deref;
@@ -2527,7 +2527,7 @@ fn add_native_libs_from_crate(
             NativeLibKind::WasmImportModule => {}
             NativeLibKind::LinkArg => {
                 if link_static {
-                    cmd.arg(name);
+                    cmd.linker_arg(OsStr::new(name), verbatim);
                 }
             }
         }
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 4dd688c2234..f65afd99e39 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -196,6 +196,14 @@ pub trait Linker {
     fn add_no_exec(&mut self) {}
     fn add_as_needed(&mut self) {}
     fn reset_per_library_state(&mut self) {}
+    fn linker_arg(&mut self, arg: &OsStr, verbatim: bool) {
+        self.linker_args(&[arg], verbatim);
+    }
+    fn linker_args(&mut self, args: &[&OsStr], _verbatim: bool) {
+        args.into_iter().for_each(|a| {
+            self.cmd().arg(a);
+        });
+    }
 }
 
 impl dyn Linker + '_ {
@@ -223,38 +231,12 @@ pub struct GccLinker<'a> {
 }
 
 impl<'a> GccLinker<'a> {
-    /// Passes an argument directly to the linker.
-    ///
-    /// When the linker is not ld-like such as when using a compiler as a linker, the argument is
-    /// prepended by `-Wl,`.
-    fn linker_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
-        self.linker_args(&[arg]);
-        self
+    fn linker_arg(&mut self, arg: impl AsRef<OsStr>) {
+        Linker::linker_arg(self, arg.as_ref(), false);
     }
-
-    /// Passes a series of arguments directly to the linker.
-    ///
-    /// When the linker is ld-like, the arguments are simply appended to the command. When the
-    /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by
-    /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a
-    /// single argument is appended to the command to ensure that the order of the arguments is
-    /// preserved by the compiler.
-    fn linker_args(&mut self, args: &[impl AsRef<OsStr>]) -> &mut Self {
-        if self.is_ld {
-            args.into_iter().for_each(|a| {
-                self.cmd.arg(a);
-            });
-        } else {
-            if !args.is_empty() {
-                let mut s = OsString::from("-Wl");
-                for a in args {
-                    s.push(",");
-                    s.push(a);
-                }
-                self.cmd.arg(s);
-            }
-        }
-        self
+    fn linker_args(&mut self, args: &[impl AsRef<OsStr>]) {
+        let args_vec: Vec<&OsStr> = args.iter().map(|x| x.as_ref()).collect();
+        Linker::linker_args(self, &args_vec, false);
     }
 
     fn takes_hints(&self) -> bool {
@@ -361,6 +343,30 @@ impl<'a> GccLinker<'a> {
 }
 
 impl<'a> Linker for GccLinker<'a> {
+    /// Passes a series of arguments directly to the linker.
+    ///
+    /// When the linker is ld-like, the arguments are simply appended to the command. When the
+    /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by
+    /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a
+    /// single argument is appended to the command to ensure that the order of the arguments is
+    /// preserved by the compiler.
+    fn linker_args(&mut self, args: &[&OsStr], verbatim: bool) {
+        if self.is_ld || verbatim {
+            args.into_iter().for_each(|a| {
+                self.cmd.arg(a);
+            });
+        } else {
+            if !args.is_empty() {
+                let mut s = OsString::from("-Wl");
+                for a in args {
+                    s.push(",");
+                    s.push(a);
+                }
+                self.cmd.arg(s);
+            }
+        }
+    }
+
     fn cmd(&mut self) -> &mut Command {
         &mut self.cmd
     }
@@ -531,7 +537,7 @@ impl<'a> Linker for GccLinker<'a> {
             self.linker_arg("-force_load");
             self.linker_arg(&lib);
         } else {
-            self.linker_arg("--whole-archive").cmd.arg(lib);
+            self.linker_args(&[OsString::from("--whole-archive"), lib.into()]);
             self.linker_arg("--no-whole-archive");
         }
     }
diff --git a/tests/run-make/pass-linker-flags-flavor/Makefile b/tests/run-make/pass-linker-flags-flavor/Makefile
new file mode 100644
index 00000000000..bd3d3ed882f
--- /dev/null
+++ b/tests/run-make/pass-linker-flags-flavor/Makefile
@@ -0,0 +1,8 @@
+# only-linux
+
+include ../tools.mk
+
+all:
+	$(RUSTC) rs.rs -Z unstable-options -C linker-flavor=gnu-cc -l static=l1 -l link-arg=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*-Wl,a1.*l2.*-Wl,a2.*d1.*-Wl,a3'
+	$(RUSTC) rs.rs -Z unstable-options -C linker-flavor=gnu-cc -l static=l1 -l link-arg:+verbatim=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*-Wl,a2.*d1.*-Wl,a3'
+	$(RUSTC) rs.rs -Z unstable-options -C linker-flavor=ld -l static=l1 -l link-arg=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*"a2".*d1.*"a3"'
diff --git a/tests/run-make/pass-linker-flags-flavor/rs.rs b/tests/run-make/pass-linker-flags-flavor/rs.rs
new file mode 100644
index 00000000000..f328e4d9d04
--- /dev/null
+++ b/tests/run-make/pass-linker-flags-flavor/rs.rs
@@ -0,0 +1 @@
+fn main() {}