Currently, cfg attributes are passed in via flags to rustc; however, I believe that there is also a case for crates exposing CFG attributes as well.
For example, eventfd
is a function that is available on Linux as of 2.6.27. Rust supports Linux as of 2.6.18, so in order to write crates that are compatible with all platforms that Rust supports, it is not possible to assume the presence of eventfd
.
The nix crate provides the bindings to more advanced *nix platform APIs. The nix crate would have a build.rs
script that would feature detect whether eventfd
is present on the system (though, in practice, it would also allow the user to opt out even if it is present), and conditionally expose the eventfd
binding if it is available.
The problem is that, mio would like to use eventfd
if it exists, but has no way of knowing whether or not eventfd
has been defined.
Cargo features are not a solution to this problem since the availability of eventfd
is not opt-in by the user, but detected based on the system. Also, cargo features must be “re-exported” by each dependency where as, this case is really an environmental concern: does eventfd
exist on the target platform.
Proposed Solution
What I propose is for crates to be able to expose attributes that are usable by dependencies via the CFG system.
For example, in the nix crate, I could do the following:
#[cfg(has_event_fd)] // detected by builders
attribute event_fd = "yes";
Then, in the mio crate, I could do the following:
extern crate nix;
#[cfg(nix::event_fd)]
// use eventfd
#[cfg(not(nix::event_fd)]
// fallback on using a self pipe strategy
Another option that wouldn’t require a keyword could be to annotate a constant. In the nix crate again:
#[attribute = "event_fd"]
const HAS_EVENTFD: &'static str = "yes";
I’m not sure what the best way to “export” attributes from a crate would be and am hoping to get community feedback!