-
Notifications
You must be signed in to change notification settings - Fork 170
Remove weak symbols, use abort
for defaults.
#254
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
Conversation
I think there may be something else that I need to do to the linker script, since as it is now it currently fails to build on one of the projects I'm working on with the error
|
Try to rebase from |
@rslawson please, add a brief note in |
Yep, they did disappear. I'll make the change to |
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.
LGTM.
I would like to discuss this work with @rust-embedded/all in the next meeting in case there is a better approach to deal with weak symbols and LTO optimizations in Rust.
afb8517
to
aa8cff9
Compare
In the meantime I'll try to keep this rebased with an up-to-date master branch from this repo. |
We discussed this today and... we didn't come up with a better solution. Let's leave this PR and #247 open to keep discussing what to do with weak symbols. We must:
@rslawson , would you be happy to keep working on this PR until we decide what to do with the remaining weak symbols? |
Sure thing, I can do that. |
Is this only a problem with Maybe until there is a stable solution for weak linkage in Rust, we could recommend using a different linker instead of introducing nightly-only features? |
Sorry for the late reply, got caught up in a work project for a while. I'm unsure if the problem is with the linker or in codegen, though bjorn3's answer suggests to me that it's the latter. |
Has there been progress regarding the fate of other weak symbols? Or regarding whether that fate should continue blocking this PR? |
There has not been progress as far as I know. I'm currently working on #238 and plan to work on this issue later. Of course, if someone investigates this and gets into a nice solution, it is more than welcome! |
Remaining weak symbols
|
Please let me know what you think about this. |
I think that this is a fair compromise. No comment on the HARTs situation since every use case I have is single HART, so unsure of what the pros and cons are of this, so any other input is welcome. Also, by opt-in and opt-out I assume you mean adding these features to the default features of the crate, yes? |
So, for the Option 1: Additive feature, part of
|
I am not sure which approach is the best, or which approach is more aligned with the Rust ecosystem. Maybe option 1? In any case, I'm sure option 2 is non-breaking, while I'm not that sure about option 1. If we decide to go for option 1, then we might need to review the Again, just thinking out loud. I'm far from an expert in these topics. Let me know what you think. |
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.
This alternative uses a no-abort
feature to opt-out the definition of the abort
symbol.
I think I prefer this approach of no-symbol
features instead of using default features. With the no-symbol
scheme, crates can explicitly drop parts of the riscv-rt
crate. I'm not sure how default features work when one dependent crate uses no-default-features
but other dependent crate does not explicitly disable default features.
If a crate depends on a non-additive feature (even if it's through the default feature) of one of its dependencies, then that feature is part of their public API. If it happens that they don't need this feature (and don't want it to be part of their public API, i.e. they don't need it at the moment), then it's a defect of that crate to depend on that feature, and that crate should be fixed. So in your example, that "other dependent crate [that] does not explicitly disable default features" is the problem, not the So I wouldn't worry too much about libraries misusing non-additive features, we can't improve the situation other than having no default features (or at least avoiding adding more). And I agree with your conclusion that option 2 is better because it doesn't add a default feature. Note that when option 1 says "additive feature" this is technically wrong. The name sounds additive, but the feature is not, because symbols are not covariant, they are invariant. Code may require a symbol to be present or absent. This is different from adding a method to a type, because code cannot depend on this method being absent (only present). |
I'd recommend against a As you mention, anything we want in the default builds should be additive features that get added to the |
The default state of Cargo features, in which the only way to turn off a default feature is to turn them all off and put the rest back (very fragile), is not ideal. That said, yeah, a lot of machinery depends on being able to turn on all the features simultaneously and have everything still compile and work the same as before. Better to have an on-by-default feature than break convention, I think. |
To clarify the situation, because, as @ia0 said, I'm not sure if additive/subtractive is a good terminology: In When linking to other crates or C libraries (e.g., #197), there is a chance that the Option 1:
|
I also believe we shouldn't rely on default features because they only make sense for additive features. And I also believe they are a misfeature. They should only be enabled by default in final crates (binaries) and not in libraries, but that's out of our hands and even out of those of Cargo's team since it would be a major breaking change. I think using For those who think |
The |
Since this would be a breaking change anyway (requiring a minor version release), we could still use an
I really dislike the
If you think that default features are a misfeature, maybe take it up with the main compiler team. I would very much like to get some popcorn for that conversation :) I agree that If we have mutually dependent features, we should group them together in another feature, and recommend the grouped feature. I don't know of a way to enforce feature invariants without build script magic.
No, it's subtractive because it literally conditionally excludes code from the library. It "subtracts" the
I also think this is a good compromise, if we decide not to wait for The feature-gate would then look like: #[cfg(not(feature = "custom-abort"))]
// default-abort-routine |
Even if it is a breaking change, I would try my best not to break current "standard" applications. This is, the I personally prefer not to use So, my vote is |
That's also not what "additive feature" means. A feature is additive if enabling it doesn't break code (which happens through feature unification). It's true that for methods and functions (outside traits), a feature adding that method or function is additive. However this is not the case for trait methods and symbols which could all be considered "adding code". In particular in the case of And note that the oppositive feature |
This makes no sense, you are literally saying the opposite thing in those two sentences. We are talking about a feature that would be used for defining a global assembly block. Rust code is compiled down into assembly. Explain the concrete difference. From the Cargo Book: A consequence of this is that features should be additive.
That is, enabling a feature should not disable functionality,
and it should usually be safe to enable any combination of features.
A feature should not introduce a [SemVer-incompatible change](https://doc.rust-lang.org/cargo/reference/features.html#semver-compatibility).
Maybe it is the best solution given the situation that most (how are we measuring that?) current users expect a default Another notable exception to the above convention is the
Either way, we are breaking the convention by introducing a feature with a Honestly, I would prefer to wait for the proper fix provided by a stable |
It can take years before In general, symbols such as |
Well, I just thought that there is a third option, which is very similar to the current state of this PR: defining In this PR, there is an The main drawback here is that, even if the So, even though there is no perfect solution until |
@rslawson could you please rename |
Yep, will do. Sorry for the delay - was ill, and have a couple things on my plate at work before I can get to this. It's on the docket for sure though (: |
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.
Conflicts solved, just needs to change _abort
to _default_abort
and is ready to go
Co-authored-by: Román Cárdenas Rodríguez <[email protected]>
As per #247, using weak symbols for overridable functions has proven problematic with
lto = true
. This is a partial reversion of that, though there are still other functions this may yet be done with. There is also another solution to be done as a sort of nightly-only thing with naked functions and#[linkage = "weak"]
, however I have opted not to go with that seeing as this project doesn't currently require nightly and I don't think this is an issue worth changing that over.