-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Conditional compilation based on crate_type #20267
Comments
I've since rewritten all of the wrapper functions I intended to exclude from the rlib to be totally safe and documented them with their c equivalent definitions. I plan to just ensure the documentation notes that the wrapper functions are not intended to be used from rust and that the implementation defined mangled methods should be preferred. I'm leaving this open for now, but feel free to close it. It might still be useful to have, but I've given up on it for now rather than complicate my project structure further (E.G. having a rust lib and a seperate wrapper lib), in favor of better documentation and safer code. |
Triage: I believe this is fixed (see https://doc.rust-lang.org/reference.html#linkage). |
I believe so as well, and given that @BenTheElder found another way in the meantime, and nobody else has commented in a year, let's give it a close. |
This is not working, at least on these versions as I tried: Possibly a regression? Details here is an shorter version of the snippet:
|
I don't see anything about this in the link to the documentation. |
I can't find anything about this in the reference either. Using I would like to do this to not have to expose an unsage API meant to be consumed by FFI/Python. |
Reopening because I was looking for this today and it doesn't seem like it was ever implemented. I don't think an RFC would be required for this. |
I'm working on this! Can I be assigned? |
I did implement this, but I'm not sure it is possible to be intuitive as rustc allows multiple crate types in the same session. When you compile a crate with I can create a PR anyone's interested. |
A use case for this is when I have a To be able to generate With this feature I could do #[cfg(crate_type = "staticlib")]
#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
...
} which would make it possible to build the crate to both |
Another use case is the creation of plugins, where an application can dynamically load the plugins via an extern "C" function, but also be able to use the plugins statically, like a normal rust library. That way we could disable the dynamic loading function in the plugin, to be able to statically link. A quick way to solve this is to create two crates, one rlib, with the api in rust, and another cdylib, containing the function to load the plugin. Although this method is not very ergonomic, it would be much better to be able to use conditional compilation to control whether or not the extern function is defined. This has already been mentioned in: eclipse-zenoh/zenoh#89 (comment) |
It seems that using static_lib.rs:
dynamic_lib.rs:
lib.rs:
|
Unfortunately this doesn't work with cargo. But I think rust-lang/cargo#8628 can solve this and other problems. |
@dabretin 's method seems not working for implementing conditional |
I ended up needing something like this for crates that's intended to be used from C, but can also in principle be used in a Rust binary crate: All but one of the crates define an Right now, I have all crates do |
@pheki did you ever make the PR, or would you be able to? Even if there are merge conflicts or it doesn't work, it might be a good starting point for somebody else. Bit of an annoying issue when you stumble upon this. You could workaround using features instead, if you pass them manually while compiling. Gist to a playground example of what likely should work: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=18fcde81a38b7e8cb6f3f62fd5df851a |
@tgross35 I think I left the code in my rust clone and eventually cleaned it up. My bad, I should have just made the PR. I ended up just using a feature for my use case. |
As @pheki has already meantioned earlier, currently cargo always builds all The best solution at the moment seems to be using features or separate crates. My proposalMy proposalI am not sure if the way Note: I am not mentioning
So, if you were to And if your crate was used as a dependency in another crate, it should only build What this would solve
Potential problems/downsides
Example use-caseImplementing this proposal would allow one to, for example, make a // Dynamic library implementation
// If a different Rust crate adds this crate as a dependency, only `rlib` will be compiled
// and the following won't be included.
// However, if specifically building the `cdylib` type with `cargo build`, it will be included
#[cfg(crate_type = "cdylib")]
#[no_mangle]
extern "C" fn example() -> interface::MyGuard {
interface::MyGuard {
inner: 123,
}
}
// The public API of the dynamic library, that is shared both by the dynamic library itself,
// and binary that uses it. This makes it as simple as adding a dependency to your Cargo.toml
// to get access to the API, without separating the dynamic library into two crates "impl" and
// "interface" or using features.
pub mod interface {
#[repr(C)]
pub struct MyGuard {
pub(crate) inner: usize,
}
impl Drop for MyGuard {
fn drop(&mut self) {
println!("guard dropped: {}", self.inner);
}
}
} Looking forward to your comments and thoughts on this proposal. |
It is possible to achieve this behavior if you set the crate-type to rlib in Cargo.toml and use the following command:
It will only compile the crate for the crate-types specified in the command, this is possible after rust-lang/rfcs#3180 This is a way around the problem of #[cfg(crate_type = "type")], where all crates in the project are rlib only, to be used as a dependency on other crates, and when I need to create a cdylib I compile it separately. However, it would be very interesting not to compile twice to get this result. |
We need to be able to do this: rust-lang/rust#20267
We need to be able to do this: rust-lang/rust#20267
Ideally we should be able to do something like this:
Cargo.toml:
src/lib.rs:
To allow only exporting the c api in the dylib or perhaps in the dylib and static lib and not in the rust code.
This would be consistent with being able to build multiple library formats but allow the unsafe c methods to not be exported to rust code.
I checked against: http://doc.rust-lang.org/reference.html#conditional-compilation
and did some experimentation myself, with no luck.
If anyone has any better suggestions, I'd love to hear them.
I'm looking to generate very similar rust and c libraries with similar apis where the c library is just a c style wrapper around the rust api, also written in rust. Ideally i'd keep this in a single source and conditionally define the c api's in the dylib for loading from various languages with c ffi's and exclude the c api from the rust lib.
The text was updated successfully, but these errors were encountered: