-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rustc: Group linked libraries where needed #49316
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
7394e66
to
60e6480
Compare
☔ The latest upstream changes (presumably #49308) made this pull request unmergeable. Please resolve the merge conflicts. |
3b41480
to
eec0d65
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @alexcrichton! r=me with the nits addressed.
src/librustc_trans/back/link.rs
Outdated
// Linkage::NotLinked | | ||
// Linkage::IncludedFromDylib => continue, | ||
// _ => {} | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you leave this in on purpose?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
er oops, no!
if group_end.is_some() && group_start.is_none() { | ||
group_end = None; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add an assert!(group_start.is_some() == group_end.is_some())
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah unfortunately that assertion tripped when I added it, so I ended up having to implement it this way for libstd specifically
eec0d65
to
8ad2f7f
Compare
@bors: r=michaelwoerister |
📌 Commit 8ad2f7f has been approved by |
☔ The latest upstream changes (presumably #49019) made this pull request unmergeable. Please resolve the merge conflicts. |
8ad2f7f
to
50ad5f9
Compare
@bors: r=michaelwoerister |
📌 Commit 50ad5f9 has been approved by |
⌛ Testing commit 50ad5f9fcb3f69bbba7c82a39902f479b649503a with merge 0579f55645b45d0363079f88f880a64e67635259... |
💔 Test failed - status-travis |
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 rust-lang#18807 Closes rust-lang#47074
50ad5f9
to
88114f6
Compare
@bors: r=michaelwoerister |
📌 Commit 88114f6 has been approved by |
…oerister 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
☀️ Test successful - status-appveyor, status-travis |
@alexcrichton it seems that panic_fmt is not in the "missing lang items" list so this logic doesn't add {start,end}-group when only that lang item is in play. |
@japaric hm it's listed here but I may be misremembering what that's used for. Do you have an example I can poke around? |
@alexcrichton #48661 (comment) still produces a shared library that contains an undefined reference to rust_begin_unwind. The linker invocation looks like this: "cc"
"-Wl,--as-needed"
"-Wl,-z,noexecstack"
"-m64"
"-L"
"$SYSROOT/lib/rustlib/x86_64-unknown-linux-gnu/lib"
"$PWD/target/release/deps/bar.bar0.rcgu.o"
"-o"
"$PWD/target/release/deps/libbar.so"
"-Wl,--version-script=/tmp/rustc.NVjXDd5FIjVZ/list"
"-Wl,--gc-sections"
"-Wl,-z,relro,-z,now"
"-Wl,-O1"
"-nodefaultlibs"
"-L"
"/home/japaric/tmp/bar/target/release/deps"
"-L"
"$SYSROOT/lib/rustlib/x86_64-unknown-linux-gnu/lib"
"-Wl,-Bstatic"
# -Wl,--start-group
"$PWD/target/release/deps/libpanic-3f5354702551e825.rlib"
"$SYSROOT/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-4d12ce26aecbbf20.rlib"
# -Wl,--end-group
"-shared"
"-Wl,-Bdynamic" I would expect the logic added in this PR to add the {start,end}-group flags in the places where I added comments, but today's nightly doesn't add those flags to the linker invocation. If you re-invoke the linker with the {start,end}-group flags you get a shared library with a defined rust_begin_unwind symbol. |
Ok thanks for the info! I think I've narrowed this down and am testing a fix |
It turns out that the support in rust-lang#49316 wasn't enough to handle all cases notably the example in rust-lang#48661. The underlying bug was connected to panic=abort where lang items were listed in the `missing_lang_items` sets but didn't actually exist anywhere. This caused the linker backend to deduce that start-group/end-group wasn't needed because not all items were defined. Instead the missing lang items that don't actually need to have a definition are filtered out and not considered for the start-group/end-group arguments Closes rust-lang#48661
I've posted #49672 with a fix for that |
…haelwoerister Fix another circular deps link args issue It turns out that the support in #49316 wasn't enough to handle all cases notably the example in #48661. The underlying bug was connected to panic=abort where lang items were listed in the `missing_lang_items` sets but didn't actually exist anywhere. This caused the linker backend to deduce that start-group/end-group wasn't needed because not all items were defined. Instead the missing lang items that don't actually need to have a definition are filtered out and not considered for the start-group/end-group arguments Closes #48661
This commit fixes a longstanding issue with the compiler with circular
dependencies between libcore and libstd. The
core
crate requires at least onesymbol, the ability to unwind. The
std
crate is the crate which actuallydefines this symbol, but the
std
crate also depends on thecore
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
optionswhich 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