about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMads Marquart <mads@marquart.dk>2024-11-24 01:20:28 +0100
committerMads Marquart <mads@marquart.dk>2024-11-24 01:20:28 +0100
commit45791dde8e0d258d794e561b9dff53f1dbb16377 (patch)
tree0c67058dcbf6011434835aa2423b3e9884d22bbf
parenta47555110cf09b3ed59811d9b02235443e76a595 (diff)
downloadrust-45791dde8e0d258d794e561b9dff53f1dbb16377.tar.gz
rust-45791dde8e0d258d794e561b9dff53f1dbb16377.zip
Support linker arguments that contain commas
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs51
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker/tests.rs25
2 files changed, 67 insertions, 9 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 6ee599c9964..162ea38dfd5 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -24,6 +24,9 @@ use super::command::Command;
 use super::symbol_export;
 use crate::errors;
 
+#[cfg(test)]
+mod tests;
+
 /// Disables non-English messages from localized linkers.
 /// Such messages may cause issues with text encoding on Windows (#35785)
 /// and prevent inspection of linker output in case of errors, which we occasionally do.
@@ -178,23 +181,53 @@ fn verbatim_args<L: Linker + ?Sized>(
     }
     l
 }
+/// Add underlying linker arguments to C compiler command, by wrapping them in
+/// `-Wl` or `-Xlinker`.
+fn convert_link_args_to_cc_args(
+    cmd: &mut Command,
+    args: impl IntoIterator<Item: AsRef<OsStr>, IntoIter: ExactSizeIterator>,
+) {
+    let args = args.into_iter();
+    if args.len() == 0 {
+        return;
+    }
+
+    let mut combined_arg = OsString::from("-Wl");
+    for arg in args {
+        // If the argument itself contains a comma, we need to emit it
+        // as `-Xlinker`, otherwise we can use `-Wl`.
+        if arg.as_ref().as_encoded_bytes().contains(&b',') {
+            // Emit current `-Wl` argument, if any has been built.
+            if combined_arg != OsStr::new("-Wl") {
+                cmd.arg(combined_arg);
+                // Begin next `-Wl` argument.
+                combined_arg = OsString::from("-Wl");
+            }
+
+            // Emit `-Xlinker` argument.
+            cmd.arg("-Xlinker");
+            cmd.arg(arg);
+        } else {
+            // Append to `-Wl` argument.
+            combined_arg.push(",");
+            combined_arg.push(arg);
+        }
+    }
+    // Emit final `-Wl` argument.
+    if combined_arg != OsStr::new("-Wl") {
+        cmd.arg(combined_arg);
+    }
+}
 /// Arguments for the underlying linker.
 /// Add options to pass them through cc wrapper if `Linker` is a cc wrapper.
 fn link_args<L: Linker + ?Sized>(
     l: &mut L,
     args: impl IntoIterator<Item: AsRef<OsStr>, IntoIter: ExactSizeIterator>,
 ) -> &mut L {
-    let args = args.into_iter();
     if !l.is_cc() {
         verbatim_args(l, args);
-    } else if args.len() != 0 {
-        // FIXME: Support arguments with commas, see `rpaths_to_flags` for the example.
-        let mut combined_arg = OsString::from("-Wl");
-        for arg in args {
-            combined_arg.push(",");
-            combined_arg.push(arg);
-        }
-        l.cmd().arg(combined_arg);
+    } else {
+        convert_link_args_to_cc_args(l.cmd(), args);
     }
     l
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/linker/tests.rs b/compiler/rustc_codegen_ssa/src/back/linker/tests.rs
new file mode 100644
index 00000000000..293ed6634ae
--- /dev/null
+++ b/compiler/rustc_codegen_ssa/src/back/linker/tests.rs
@@ -0,0 +1,25 @@
+use super::*;
+
+#[test]
+fn test_xlinker() {
+    let mut cmd = Command::new("foo");
+    convert_link_args_to_cc_args(&mut cmd, &[
+        "arg1",
+        "arg2",
+        "arg3,with,comma",
+        "arg4,with,comma",
+        "arg5",
+        "arg6,with,comma",
+    ]);
+
+    assert_eq!(cmd.get_args(), [
+        OsStr::new("-Wl,arg1,arg2"),
+        OsStr::new("-Xlinker"),
+        OsStr::new("arg3,with,comma"),
+        OsStr::new("-Xlinker"),
+        OsStr::new("arg4,with,comma"),
+        OsStr::new("-Wl,arg5"),
+        OsStr::new("-Xlinker"),
+        OsStr::new("arg6,with,comma"),
+    ]);
+}