rust feature主要作为条件依赖起到一定的功能,我理解主要有两点:
1.作为lib,向外部提供可选的功能项
2.作为二进制文件,可以在编译是通过cargo build --features="*"来缩小可执行文件的体积。
需要说明的是,在代码中所有开启feature的地方都要加上属性说明。
以一个简单的例子为例,在ws-rs中提供了两个feature,既可以使用ssl feature,也可以使用nativessl feature。但是需要在开启feature的地方加上相应的代码:
impl io::Read for Stream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match *self {
Tcp(ref mut sock) => sock.read(buf),
#[cfg(any(feature = "ssl", feature = "nativetls"))]
Tls(TlsStream::Live(ref mut sock)) => sock.read(buf),
#[cfg(any(feature = "ssl", feature = "nativetls"))]
Tls(ref mut tls_stream) => {
trace!("Attempting to read ssl handshake.");
match replace(tls_stream, TlsStream::Upgrading) {
TlsStream::Live(_) | TlsStream::Upgrading => unreachable!(),
TlsStream::Handshake {
sock,
mut negotiating,
} => match sock.handshake() {
Ok(mut sock) => {
trace!("Completed SSL Handshake");
let res = sock.read(buf);
*tls_stream = TlsStream::Live(sock);
res
}
#[cfg(feature = "ssl")]
Err(HandshakeError::SetupFailure(err)) => {
Err(io::Error::new(io::ErrorKind::Other, err))
}
#[cfg(feature = "ssl")]
Err(HandshakeError::Failure(mid))
| Err(HandshakeError::WouldBlock(mid)) => {
if mid.error().code() == SslErrorCode::WANT_READ {
negotiating = true;
}
let err = if let Some(io_error) = mid.error().io_error() {
Err(io::Error::new(
io_error.kind(),
format!("{:?}", io_error.get_ref()),
))
} else {
Err(io::Error::new(
io::ErrorKind::Other,
format!("{}", mid.error()),
))
};
*tls_stream = TlsStream::Handshake {
sock: mid,
negotiating,
};
err
}
#[cfg(feature = "nativetls")]
Err(HandshakeError::WouldBlock(mid)) => {
negotiating = true;
*tls_stream = TlsStream::Handshake {
sock: mid,
negotiating: negotiating,
};
Err(io::Error::new(io::ErrorKind::WouldBlock, "SSL would block"))
}
#[cfg(feature = "nativetls")]
Err(HandshakeError::Failure(err)) => {
Err(io::Error::new(io::ErrorKind::Other, format!("{}", err)))
}
},
}
}
}
}
}
另外编译的时候还提供了cargo build --features =" "和cargo run --features = " ",
需要说明的是,默认提供了default feature,
并且所有feature中使用到的依赖需要配置为可选依赖。
例如:
ssl = ["openssl"]
nativetls = ["native-tls"]
可选依赖如下:
[dependencies.openssl]
optional = true
version = "0.10"
[dependencies.native-tls]
optional = true
version = "0.2"
当lib放入Cargo.toml文件中时,使用例子:
ryu = { version = "0.2", default-features = false } 关闭default-features
compiletest_rs = { version = "0.3", features = ["stable"] } 使用stable feature + default feature?
cargo run同理:
cargo run --features="openssl" --no-default-features
default-features 不使用需手动关闭。
网友评论