about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-08-21 22:30:46 -0700
committerGitHub <noreply@github.com>2016-08-21 22:30:46 -0700
commitc44534ef5a6b95cb032c6ce28c8893cf530903b9 (patch)
tree64defd927884f2ffdd0319e3e7ca41ff49dff311
parent42584d36f6a2d8021c0b642ec0cbf1afed750f32 (diff)
parentc08b7b9f754c6969e3cc630cfea76a8b8ce8876b (diff)
downloadrust-c44534ef5a6b95cb032c6ce28c8893cf530903b9.tar.gz
rust-c44534ef5a6b95cb032c6ce28c8893cf530903b9.zip
Auto merge of #35821 - nbaksalyar:solaris-trans-fix, r=alexcrichton
Fix linker on Solaris/Illumos

This patch provides a fix for the `GnuLinker::export_symbols` function that currently relies on a `--retain-symbols-file` option which is not supported by the Solaris & Illumos linker.

Instead, a [version script](https://www.gnu.org/software/gnulib/manual/html_node/LD-Version-Scripts.html) is used on this platform to achieve the same goal. Here's an example of a similar approach in LLVM's CMake script: https://github.com/llvm-mirror/llvm/blob/master/cmake/modules/AddLLVM.cmake#L88-L94.

Perhaps other platforms like OpenBSD could benefit from this as well. /cc @semarie
-rw-r--r--src/librustc_trans/back/linker.rs58
1 files changed, 39 insertions, 19 deletions
diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs
index cb990ead8e8..f2d5b128d27 100644
--- a/src/librustc_trans/back/linker.rs
+++ b/src/librustc_trans/back/linker.rs
@@ -247,29 +247,49 @@ impl<'a> Linker for GnuLinker<'a> {
             return
         }
 
+        let mut arg = OsString::new();
         let path = tmpdir.join("list");
-        let prefix = if self.sess.target.target.options.is_like_osx {
-            "_"
-        } else {
-            ""
-        };
-        let res = (|| -> io::Result<()> {
-            let mut f = BufWriter::new(File::create(&path)?);
-            for sym in &self.info.cdylib_exports {
-                writeln!(f, "{}{}", prefix, sym)?;
+
+        if self.sess.target.target.options.is_like_solaris {
+            let res = (|| -> io::Result<()> {
+                let mut f = BufWriter::new(File::create(&path)?);
+                writeln!(f, "{{\n  global:")?;
+                for sym in &self.info.cdylib_exports {
+                    writeln!(f, "    {};", sym)?;
+                }
+                writeln!(f, "\n  local:\n    *;\n}};")?;
+                Ok(())
+            })();
+            if let Err(e) = res {
+                self.sess.fatal(&format!("failed to write version script: {}", e));
             }
-            Ok(())
-        })();
-        if let Err(e) = res {
-            self.sess.fatal(&format!("failed to write lib.def file: {}", e));
-        }
-        let mut arg = OsString::new();
-        if self.sess.target.target.options.is_like_osx {
-            arg.push("-Wl,-exported_symbols_list,");
+
+            arg.push("-Wl,-M,");
+            arg.push(&path);
         } else {
-            arg.push("-Wl,--retain-symbols-file=");
+            let prefix = if self.sess.target.target.options.is_like_osx {
+                "_"
+            } else {
+                ""
+            };
+            let res = (|| -> io::Result<()> {
+                let mut f = BufWriter::new(File::create(&path)?);
+                for sym in &self.info.cdylib_exports {
+                    writeln!(f, "{}{}", prefix, sym)?;
+                }
+                Ok(())
+            })();
+            if let Err(e) = res {
+                self.sess.fatal(&format!("failed to write lib.def file: {}", e));
+            }
+            if self.sess.target.target.options.is_like_osx {
+                arg.push("-Wl,-exported_symbols_list,");
+            } else {
+                arg.push("-Wl,--retain-symbols-file=");
+            }
+            arg.push(&path);
         }
-        arg.push(&path);
+
         self.cmd.arg(arg);
     }
 }