diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2018-03-23 14:33:22 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2018-03-29 15:07:51 -0700 |
| commit | 88114f61b44dba22c6fa180e17d7638f2cf7a9d7 (patch) | |
| tree | c5e4446bfcc983fd1b7c3cb4bc615eee80cdf310 /src/librustc_trans/back/linker.rs | |
| parent | ae544ee1c90afc0f939753014dc5e884cb2749a0 (diff) | |
| download | rust-88114f61b44dba22c6fa180e17d7638f2cf7a9d7.tar.gz rust-88114f61b44dba22c6fa180e17d7638f2cf7a9d7.zip | |
rustc: Group linked libraries where needed
This commit fixes a longstanding issue with the compiler with circular dependencies between libcore and libstd. The `core` crate requires at least one symbol, the ability to unwind. The `std` crate is the crate which actually defines this symbol, but the `std` crate also depends on the `core` crate. This circular dependency is in general disallowed in Rust as crates cannot have cycles amongst them. A special exception is made just for core/std, but this is also unfortunately incompatible with how GNU linkers work. GNU linkers will process undefined symbols in a left-to-right fashion, only actually linking an rlib like libstd if there are any symbols used from it. This strategy is incompatible with circular dependencies because if we otherwise don't use symbols from libstd we don't discover that we needed it until we're later processing libcore's symbols! To fix this GNU linkers support the `--start-group` and `--end-group` options which indicate "libraries between these markers may have circular dependencies amongst them. The linker invocation has been updated to automatically pass these arguments when we're invoking a GNU linker and automatically calculate where the arguments need to go (around libstd and libcore) Closes #18807 Closes #47074
Diffstat (limited to 'src/librustc_trans/back/linker.rs')
| -rw-r--r-- | src/librustc_trans/back/linker.rs | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index a9095a66aaa..ebcf06d63be 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -125,6 +125,8 @@ pub trait Linker { fn args(&mut self, args: &[String]); fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType); fn subsystem(&mut self, subsystem: &str); + fn group_start(&mut self); + fn group_end(&mut self); // Should have been finalize(self), but we don't support self-by-value on trait objects (yet?). fn finalize(&mut self) -> Command; } @@ -420,6 +422,18 @@ impl<'a> Linker for GccLinker<'a> { ::std::mem::swap(&mut cmd, &mut self.cmd); cmd } + + fn group_start(&mut self) { + if !self.sess.target.target.options.is_like_osx { + self.linker_arg("--start-group"); + } + } + + fn group_end(&mut self) { + if !self.sess.target.target.options.is_like_osx { + self.linker_arg("--end-group"); + } + } } pub struct MsvcLinker<'a> { @@ -648,6 +662,10 @@ impl<'a> Linker for MsvcLinker<'a> { ::std::mem::swap(&mut cmd, &mut self.cmd); cmd } + + // MSVC doesn't need group indicators + fn group_start(&mut self) {} + fn group_end(&mut self) {} } pub struct EmLinker<'a> { @@ -810,6 +828,10 @@ impl<'a> Linker for EmLinker<'a> { ::std::mem::swap(&mut cmd, &mut self.cmd); cmd } + + // Appears not necessary on Emscripten + fn group_start(&mut self) {} + fn group_end(&mut self) {} } fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> { @@ -953,4 +975,8 @@ impl Linker for WasmLd { ::std::mem::swap(&mut cmd, &mut self.cmd); cmd } + + // Not needed for now with LLD + fn group_start(&mut self) {} + fn group_end(&mut self) {} } |
