-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Add internal RUSTC_INTERNAL_FORCE_PANIC_ABORT
env var for libpanic_abort
#66311
Conversation
r? @zackmdavis (rust_highfive has picked a reviewer for you, use r? to override) |
@rust-lang/compiler @oli-obk @alexcrichton I'd be interested in what you think is the best approach to ensuring that libpanic_abort is always compiled with Cc @ehuss for wg-cargo-std-aware, this might also affect you I think. |
Note that we could switch back to my original attribute+based approach if we could make the I glanced over the relevant code, and it seemed like it would require moving the creation or initialization of |
But implementation looks fine overall, if a bit unfortunate. |
Just to make sure I understand why we need this now... the reason is that with your PRs, when Couldn't we just keep aborting execution in |
@RalfJung: No, this issue occurs before any of my code runs. Run We need this now because we actually want to start using |
…_abort` Currently, we require `libpanic_abort` to always be build with the `abort` panic strategy, regardless of what panic strategy would normally be passed to `rustc` (e.g. `unwind` when building `libstd`). This ensures that when downstream crates build against `libpanic_abort`, it is properly detected as the panic runtime for the `abort` strategy. Previously, this was done by special-casing `libpanic_abort` in bootstrap. This meant that building `libpanic_abort` without using `x.py` (e.g by using `xargo`) would result in the wrong panic strategy being applied, leading to an error when trying to build against it: ``` error: the crate `panic_abort` does not have the panic strategy `abort` ``` This is a problem for tools like Miri, which require a custom-build libstd, and cannot use `x.py`. To fix this, we add a special environment variable `RUSTC_INTERNAL_FORCE_PANIC_ABORT`. This is set in the `build.rs` for `libpanic_abort`, and checked by the compiler when determining the panic strategy of the current crate. While this is still a hack, it's a much better one - the special case is now represented in the `libpanic_abort` crate itself, rather than in `bootstrap`. Ideally, this would be an internal attribute (e.g. `#[rustc_panic_abort]`) that we apply to `libpanic_abort`. Unfortunately, `emscripten` targets require that we be able to determine the panic strategy very early on, before we've even started parsing the crate: https://github.com/rust-lang/rust/blob/3fc30d884ae0c988d98452a06737705cfe34806a/src/librustc_codegen_llvm/llvm_util.rs#L77 To avoid invasive changes to emscripten and/or the codewgen backend infrastructure, I chose to add a new environment variable. Note that the hack in bootstrap needs to remain until this changes makes its way into the bootstrap compiler, to ensure that we can still build a correct `libpanic_abort` with a bootstrap compiler that doesn't know about this special environment variable.
9d5eea8
to
5a826c7
Compare
I would personally say we should not merge this PR, I think there's some misunderstandings going on here and this feels like it's just piling hacks on hacks for a tool that shouldn't necessarily be guiding the design of the compiler and injecting random environment variables to be read at various locations.
I don't actually believe that this, as-stated, is correct. Cargo, for example, in |
This is swapping out one hack for a slightly better hack. We still override the panic strategy for
That's because Normally, What In the unwind case, nothing ever tries to use the panic abort runtime, so the error never shows up (despite In the abort case, I can't find a way to stop
This error comes from here: rust/src/librustc_metadata/creader.rs Lines 598 to 600 in bc0e288
The rust/src/librustc_metadata/rmeta/encoder.rs Line 552 in 56237d7
which calls the method that this PR modifies:
The hack in Fundamentally, this error is about mixing a |
To expand on what @Aaron1011 wrote, here's the existing hack: rust/src/bootstrap/bin/rustc.rs Lines 92 to 107 in e931f00
Notice in particular the comment that says "This... is a bit of a hack how we detect this. Ideally this information should be encoded in the crate I guess?" ;) |
Yes I understsand the literal locations this error message is coming from because I basically wrote all the code here (rustbuild, rustc, error messages, etc). Again I'm not fully understanding the source of the error here though in terms of setup and environment, not so much in terms of where it comes out of rustc. It's not correct that the error comes from mixing a It sounds like the error you're talking about is that this may be a bug in xargo? When xargo builds crates it builds everything with |
In that scenario, we're using a With Xargo, we build directly from the
It's not really a bug in Xargo, because Xargo has no idea that the
I disagree that this change is 'piling on hacks'. This is moving the location of an existing hack, and moving special handling out of |
I agree that the use of a magic environment variable is really unfortunate (though I still think it's preferrable to hardcoded logic in |
Well, the alternative to this PR is to replicate the hack from rustbuild in xargo. This would, in particular, require copying the rustbuild scheme of having a So the alternative is to either have to replicate the wrapper-binary-based hack everywhere that builds libstd (this is what we do right now), or find a solution that does not require wrapper-binary-hacks (which this PR proposes). |
Everything about xargo and rustbuild is just a bunch of unstable code, which is otherwise read as "it works today but has no guarantees". I'm subjectively saying this is a bigger hack than what's there today, because an environment variable is extremely non-discoverable, there's zero gating here, and it's just a random change in the middle of the compiler to read an environment variable. This has little-to-no precedent for these sorts of compiler settings and seems very likely to be abused in the future. The rustbuild changes are a local "hack" which only applies to the Rust build system itself. It cannot be exploited by other users and is contained entirely to Rust's build sytem, not the compiler. Xargo is not a supported method of compiling the standard library. Issues that arise during that do not imply that you should change the compiler to work with a deprecated and no longer supported project. The I'm pretty firmly against modifying the compiler in this way purely to cater to a use case of Xargo in a niche area. I'd recommend giving |
I would argue that it's more discoverable than the current hack, as it's possible to find out that something special is going on by examining
The issue is that Miri currently relies on Xargo. I'm not very familiar with how far along In any case, I understand your concern about adding magic environment variables to the compiler. However, I'm concerned that full unwinding support on Miri could become blocked indefinitely on:
Note that without some kind of workaround, Miri will either lose the ability to perform abort panics (unless we add some awful hack to handle |
Hacks based on bootstrap's wrapper binaries are extremely hard to discover and debug, I find myself agreeing with @Aaron1011 there and I have also lost my own share of times wondering what the heck is going on until I realized that the wrapper binary is the culprit. On the other hand the env var is indeed a quite bad hack, too. The best solution seems to be an attribute, which is blocked by that codegen question. Cc @tlively for emscripten; who would know things about codegen backend initialization?
That's fair, the env var should only work on nightly similar to
xargo is maintained by me to the extend that Miri needs it. I am looking forward to using
Miri doesn't care about Xargo internals. It just needs a libstd built with some non-standard flags. However, as you said, using
[2 options listed] Well, there is a third option: adding a @Aaron1011 did you try adjusting the
Personally I think I am fine with not supporting |
@RalfJung: Unfortunately, Xargo only appears to support setting a global |
Here's another option: We add a flag This flag is passed unconditionally by |
I'm sorry but it's hard to read over these comments because they repeatedly have factual inaccuracies which in my opinion drastically changes the calculus of what this solution looks like:
This is not true.
That's good news to hear, but I find it pretty off-putting still. Xargo is an unsupported way to build libstd and has always been "best effort". Finding an issue and the pushing really hard for a random change in the compiler is not the right flow of effort here in my opinion. The compiler works the way it does and building libstd is not a trivial task for every single invocation. Sometimes some complications are necessary. I understand that trickery in the build system is not discoverable, but I will state again that an environment variable for this random setting in the compiler is wildly inappropriate. I am personally not a fan of a random I feel like I'm suggesting better solutions than modifying the compiler (because that's not trivial) and I'm being met with "yeah but I don't want to do that work so please land this random environment variable instead". |
No, |
You suggested using With |
Unfortunately I do not have broad enough knowledge of rustc to say what would be involved in reordering things so that the codegen backend is initialized after parsing begins. |
I doubt you can reorder anything wrt the codegen backend, because the only reason I can come up with for initializing LLVM that early is to extract information for But I hope I'm wrong, as I don't like the idea that LLVM controls early parts of the compilation. |
Well I think I've made my case here, and I do not have anything else to add.
If you're dealing with precompiled binaries the panic_abort runtime must be compiled with panic=abort. The bootstrap build system does this by using a shim. I think that the work to update xargo to use a shim needs to be done or a different patch needs to be proposed. |
@eddyb: You're right: rust/src/librustc_interface/util.rs Lines 49 to 71 in cefcc20
I think any re-ordering would have to take of moving the emscripten check, insted of moving LLVM initialzition. |
I've come up with a new approach in #66489, based on manually initializing the emscripten flag after we initialize LLVM. I'm closing this PR in favor of that one, since most of the discussion here centers around a different approach. |
Supersedes rust-lang#66311 This replaces the hack in `bootstrap`, allowing the special handling for `libpanic_abort` to be encoded into the crate source itself, rather than existing as special knowledge in the build system. This will allow Miri (and any other users of Xargo) to correctly build `libpanic_abort` without relying on `bootstrap` or custom wrapepr hacks. The trickeist part of this PR is how we handle LLVM. The `emscripten` target family requires the "-enable-emscripten-cxx-exceptions" flag to be passed to LLVM when the panic strategy is set to "unwind". Unfortunately, the location of this emscripten-specific check ends up creating a circular dependency between LLVM and attribute resoltion. When we check the panic strategy, we need to have already parsed crate attributes, so that we determine if `rustc_panic_abort_runtime` was set. However, attribute parsing requires LLVM to be initialized, so that we can proerly handle cfg-gating of target-specific features. However, the whole point of checking the panic strategy is to determinne which flags to use during LLVM initialization! To break this circular dependency, we explicitly set the "-enable-emscripten-cxx-exceptions" in LLVM's argument-parsing framework (using public but poorly-documented APIs). While this approach is unfortunate, it only affects emscripten, and only modifies a command-line flag which is never used until much later (when we create a `PassManager`).
Currently, we require
libpanic_abort
to always be build with theabort
panic strategy, regardless of what panic strategy wouldnormally be passed to
rustc
(e.g.unwind
when buildinglibstd
).This ensures that when downstream crates build against
libpanic_abort
,it is properly detected as the panic runtime for the
abort
strategy.Previously, this was done by special-casing
libpanic_abort
inbootstrap. This meant that building
libpanic_abort
without usingx.py
(e.g by usingxargo
) would result in the wrong panic strategybeing applied, leading to an error when trying to build against it:
This is a problem for tools like Miri, which require a custom-build
libstd, and cannot use
x.py
.To fix this, we add a special environment variable
RUSTC_INTERNAL_FORCE_PANIC_ABORT
. This is set in thebuild.rs
for
libpanic_abort
, and checked by the compiler when determining thepanic strategy of the current crate. While this is still a hack, it's a
much better one - the special case is now represented in the
libpanic_abort
crate itself, rather than inbootstrap
.Ideally, this would be an internal attribute (e.g.
#[rustc_panic_abort]
) that we apply tolibpanic_abort
.Unfortunately,
emscripten
targets require that we be able to determinethe panic strategy very early on, before we've even started parsing the
crate:
rust/src/librustc_codegen_llvm/llvm_util.rs
Line 77 in 3fc30d8
To avoid invasive changes to emscripten and/or the codewgen backend
infrastructure, I chose to add a new environment variable.
Note that the hack in bootstrap needs to remain until this changes makes
its way into the bootstrap compiler, to ensure that we can still build a
correct
libpanic_abort
with a bootstrap compiler that doesn't knowabout this special environment variable.