Open mzabaluev opened 6 years ago
Why would we need a stable abi? Just using the same compiler for both compilation runs should produce comparable abi, right?
@oli-obk
Why would we need a stable abi?
Rust has had support for dynamic library crates since before 1.0, it's just not the default output for a library crate, and the Cargo build system is currently geared towards static linkage. But to make dylibs practical in a software distribution, the ABI must not break between different compiler releases, unless the Rust major version changes.
I misunderstood the issue. Sorry. Everything makes sense now ;)
Rust does not have a stable ABI, and for all we know it might never have one. It might make sense to close this issue for the time being, since it isn't really actionable, and re-open it if Rust ever gets a stable ABI.
It seems that right now, the only way to be sure of ABI compatibility when loading a dynamic library is to either expose the dynamic library's functions via a C API, or to ensure that both the loader and loadee were built with exactly the same version of rustc (down to the minor version, since even nightly builds could change the ABI).
It would be great if there could be a semver-backed guarantee of ABI compatibility between rustc versions in the future, but that doesn't seem to be possible now.
It would be great if there could be a semver-backed guarantee of ABI compatibility between rustc versions in the future, but that doesn't seem to be possible now.
What do you mean by a semver-backed guarantee? Do you mean that the artifacts produced by two different Rust toolchains should be ABI compatible (as long as the semver version of the ABI is the same) ?
Note that Rust guarantees that the "rust" ABI of each Rust toolchain is incompatible with that of all other toolchains. This is an explicitly designed language feature.
If you want a stable ABI for interoperation, repr(C)
/extern "C"
are some of the language features that allow you to write that. If you use those in your library API, you are guaranteed ABI compatibility.
rust-semverver
only checks whether the APIs are semver compatible. If your exported API exports only repr(C)
types / extern "C"
functions, then API compatibility might mean ABI compatibility (not 100% sure, but feels right to me). We could add a lint to clippy that warns / errors if exported APIs aren't repr(C)
/extern "C"
but that's an issue that belongs in the clippy repo.
Sorry, to clarify, I mean that my ideal world is: two versions of rustc whose semver version numbers indicate that they're compatible (0.2 and 0.3, for example, or 1.2.5 and 1.6.10) would be guarateed to have ABI compatibility.
I understand that's significantly different than the current model, and that it imposes strict restrictions on future ABI changes and improvements. I'm not suggesting that my proposal is the right balance of tradeoffs :)
On 2019-03-15, Zachary Neely wrote:
Sorry, to clarify, I mean that my ideal world is: two versions of rustc whose semver version numbers indicate that they're compatible (0.2 and 0.3, for example, or 1.2.5 and 1.6.10) would be guarateed to have ABI compatibility.
I understand that's significantly different than the current model, and that it imposes strict restrictions on future ABI changes and improvements. I'm not suggesting that my proposal is the right balance of tradeoffs :)
-- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/rust-dev-tools/rust-semverver/issues/40#issuecomment-473355661
Independtly from that, this is not something we can properly implement in rust-semverver as of now, sadly.
@zrneely Rust semver numbers are about the Rust programming language itself, not about the ABI of Rust binaries.
The ABI of Rust binaries follow a different semver versioning. The ABI of each toolchain is incompatible with that of every other by design, so the ABI semver version of Rust 1.23.0 might be 1234.0.0 and the one of Rust 1.23.1 might be 5678.0.0. The major version number itself does not matter, what matters is that they are all different (not only the released versions, but also each nightly has a different ABI from all other nightlies and Rust releases).
As mentioned, this is a feature of the language. Changing / removing this feature would need RFCs that go through the process. That probably will never happen, but even if it does, until that happens there is nothing that can be done here.
If you want a stable ABI for interoperation, repr(C)/extern "C" are some of the language features that allow you to write that. If you use those in your library API, you are guaranteed ABI compatibility.
This issue should be focused on supporting exactly this to make sure the ABI is something that can be verified.
Strawman starting place to knockdown:
If not building as dynlib, the ABI are not equivalent (always tick minor version - never patch version).
If building as dynlib and repr(C) is not used, then the ABIs are the same (no exported functions).
If building as dynlib and repr(C) is used, then check exported struct sizes are the same with no reorderings and make sure no functions were deleted or no function arguments changed order; if an argument was added to a function make sure it's not used). If these checks pass, they are ABI equivalent.
With regards to files being saves and reopened (e.g. scratch files, sqlite files to maintain state... not sure how to do that; but catching the above would be good)
If and when the Rust stable ABI becomes a reality, there should be tool support to check dylib crates for breaking and major changes in the ABI.