Rollup merge of #150804 - std_detect_less_features, r=tgross35
Remove std_detect_file_io and std_detect_dlsym_getauxval features They were introduced back when std_detect was a standalone crate published to crates.io. The [motivation](https://github.com/rust-lang/stdarch/issues/655) for `std_detect_dlsym_getauxval` was to allow using `getauxval` without `dlopen` when statically linking musl, which we now unconditionally do for musl. And for `std_detect_file_io` to allow `no_std` usage, which std_detect now supports even with that feature enabled as it directly uses libc. This also prevents accidentally disabling runtime feature detection when using `cargo build -Zbuild-std -Zbuild-std-features=`
This commit is contained in:
commit
26da51d2a0
10 changed files with 91 additions and 158 deletions
|
|
@ -128,10 +128,6 @@ debug_refcell = ["core/debug_refcell"]
|
|||
|
||||
llvm_enzyme = ["core/llvm_enzyme"]
|
||||
|
||||
# Enable std_detect features:
|
||||
std_detect_file_io = ["std_detect/std_detect_file_io"]
|
||||
std_detect_dlsym_getauxval = ["std_detect/std_detect_dlsym_getauxval"]
|
||||
|
||||
# Enable using raw-dylib for Windows imports.
|
||||
# This will eventually be the default.
|
||||
windows_raw_dylib = ["windows-targets/windows_raw_dylib"]
|
||||
|
|
|
|||
|
|
@ -7,11 +7,6 @@ authors = [
|
|||
"Gonzalo Brito Gadeschi <gonzalobg88@gmail.com>",
|
||||
]
|
||||
description = "`std::detect` - Rust's standard library run-time CPU feature detection."
|
||||
homepage = "https://github.com/rust-lang/stdarch"
|
||||
repository = "https://github.com/rust-lang/stdarch"
|
||||
readme = "README.md"
|
||||
keywords = ["std", "run-time", "feature", "detection"]
|
||||
categories = ["hardware-support"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2024"
|
||||
|
||||
|
|
@ -25,10 +20,7 @@ core = { version = "1.0.0", package = 'rustc-std-workspace-core' }
|
|||
alloc = { version = "1.0.0", package = 'rustc-std-workspace-alloc' }
|
||||
|
||||
[target.'cfg(not(windows))'.dependencies]
|
||||
libc = { version = "0.2.0", optional = true, default-features = false }
|
||||
libc = { version = "0.2.0", default-features = false }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
std_detect_file_io = [ "libc" ]
|
||||
std_detect_dlsym_getauxval = [ "libc" ]
|
||||
std_detect_env_override = [ "libc" ]
|
||||
std_detect_env_override = []
|
||||
|
|
|
|||
|
|
@ -21,32 +21,6 @@ run-time feature detection support than the one offered by Rust's standard
|
|||
library. We intend to make `std_detect` more flexible and configurable in this
|
||||
regard to better serve the needs of `#[no_std]` targets.
|
||||
|
||||
# Features
|
||||
|
||||
* `std_detect_dlsym_getauxval` (enabled by default, requires `libc`): Enable to
|
||||
use `libc::dlsym` to query whether [`getauxval`] is linked into the binary. When
|
||||
this is not the case, this feature allows other fallback methods to perform
|
||||
run-time feature detection. When this feature is disabled, `std_detect` assumes
|
||||
that [`getauxval`] is linked to the binary. If that is not the case the behavior
|
||||
is undefined.
|
||||
|
||||
Note: This feature is ignored on `*-linux-{gnu,musl,ohos}*` and `*-android*` targets
|
||||
because we can safely assume `getauxval` is linked to the binary.
|
||||
* `*-linux-gnu*` targets ([since Rust 1.64](https://blog.rust-lang.org/2022/08/01/Increasing-glibc-kernel-requirements.html))
|
||||
have glibc requirements higher than [glibc 2.16 that added `getauxval`](https://sourceware.org/legacy-ml/libc-announce/2012/msg00000.html).
|
||||
* `*-linux-musl*` targets ([at least since Rust 1.15](https://github.com/rust-lang/rust/blob/1.15.0/src/ci/docker/x86_64-musl/build-musl.sh#L15))
|
||||
use musl newer than [musl 1.1.0 that added `getauxval`](https://git.musl-libc.org/cgit/musl/tree/WHATSNEW?h=v1.1.0#n1197)
|
||||
* `*-linux-ohos*` targets use a [fork of musl 1.2](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/native-lib/musl.md)
|
||||
* `*-android*` targets ([since Rust 1.68](https://blog.rust-lang.org/2023/01/09/android-ndk-update-r25.html))
|
||||
have the minimum supported API level higher than [Android 4.3 (API level 18) that added `getauxval`](https://github.com/aosp-mirror/platform_bionic/blob/d3ebc2f7c49a9893b114124d4a6b315f3a328764/libc/include/sys/auxv.h#L49).
|
||||
|
||||
* `std_detect_file_io` (enabled by default, requires `std`): Enable to perform run-time feature
|
||||
detection using file APIs (e.g. `/proc/self/auxv`, etc.) if other more performant
|
||||
methods fail. This feature requires `libstd` as a dependency, preventing the
|
||||
crate from working on applications in which `std` is not available.
|
||||
|
||||
[`getauxval`]: https://man7.org/linux/man-pages/man3/getauxval.3.html
|
||||
|
||||
# Platform support
|
||||
|
||||
* All `x86`/`x86_64` targets are supported on all platforms by querying the
|
||||
|
|
|
|||
|
|
@ -47,21 +47,21 @@ cfg_select! {
|
|||
#[path = "os/x86.rs"]
|
||||
mod os;
|
||||
}
|
||||
all(any(target_os = "linux", target_os = "android"), feature = "libc") => {
|
||||
any(target_os = "linux", target_os = "android") => {
|
||||
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||
#[path = "os/riscv.rs"]
|
||||
mod riscv;
|
||||
#[path = "os/linux/mod.rs"]
|
||||
mod os;
|
||||
}
|
||||
all(target_os = "freebsd", feature = "libc") => {
|
||||
target_os = "freebsd" => {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[path = "os/aarch64.rs"]
|
||||
mod aarch64;
|
||||
#[path = "os/freebsd/mod.rs"]
|
||||
mod os;
|
||||
}
|
||||
all(target_os = "openbsd", feature = "libc") => {
|
||||
target_os = "openbsd" => {
|
||||
#[allow(dead_code)] // we don't use code that calls the mrs instruction.
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[path = "os/aarch64.rs"]
|
||||
|
|
@ -73,7 +73,7 @@ cfg_select! {
|
|||
#[path = "os/windows/aarch64.rs"]
|
||||
mod os;
|
||||
}
|
||||
all(target_vendor = "apple", target_arch = "aarch64", feature = "libc") => {
|
||||
all(target_vendor = "apple", target_arch = "aarch64") => {
|
||||
#[path = "os/darwin/aarch64.rs"]
|
||||
mod os;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,77 +1,70 @@
|
|||
use super::auxvec::auxv_from_file;
|
||||
use super::*;
|
||||
|
||||
#[cfg(feature = "std_detect_file_io")]
|
||||
mod auxv_from_file {
|
||||
use super::auxvec::auxv_from_file;
|
||||
use super::*;
|
||||
// The baseline hwcaps used in the (artificial) auxv test files.
|
||||
fn baseline_hwcaps() -> AtHwcap {
|
||||
AtHwcap {
|
||||
fp: true,
|
||||
asimd: true,
|
||||
aes: true,
|
||||
pmull: true,
|
||||
sha1: true,
|
||||
sha2: true,
|
||||
crc32: true,
|
||||
atomics: true,
|
||||
fphp: true,
|
||||
asimdhp: true,
|
||||
asimdrdm: true,
|
||||
lrcpc: true,
|
||||
dcpop: true,
|
||||
asimddp: true,
|
||||
ssbs: true,
|
||||
..AtHwcap::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn linux_empty_hwcap2_aarch64() {
|
||||
let file = concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/src/detect/test_data/linux-empty-hwcap2-aarch64.auxv"
|
||||
);
|
||||
println!("file: {file}");
|
||||
let v = auxv_from_file(file).unwrap();
|
||||
println!("HWCAP : 0x{:0x}", v.hwcap);
|
||||
println!("HWCAP2: 0x{:0x}", v.hwcap2);
|
||||
assert_eq!(AtHwcap::from(v), baseline_hwcaps());
|
||||
}
|
||||
#[test]
|
||||
fn linux_no_hwcap2_aarch64() {
|
||||
let file = concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/src/detect/test_data/linux-no-hwcap2-aarch64.auxv"
|
||||
);
|
||||
println!("file: {file}");
|
||||
let v = auxv_from_file(file).unwrap();
|
||||
println!("HWCAP : 0x{:0x}", v.hwcap);
|
||||
println!("HWCAP2: 0x{:0x}", v.hwcap2);
|
||||
assert_eq!(AtHwcap::from(v), baseline_hwcaps());
|
||||
}
|
||||
#[test]
|
||||
fn linux_hwcap2_aarch64() {
|
||||
let file =
|
||||
concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/linux-hwcap2-aarch64.auxv");
|
||||
println!("file: {file}");
|
||||
let v = auxv_from_file(file).unwrap();
|
||||
println!("HWCAP : 0x{:0x}", v.hwcap);
|
||||
println!("HWCAP2: 0x{:0x}", v.hwcap2);
|
||||
assert_eq!(
|
||||
AtHwcap::from(v),
|
||||
AtHwcap {
|
||||
// Some other HWCAP bits.
|
||||
paca: true,
|
||||
pacg: true,
|
||||
// HWCAP2-only bits.
|
||||
dcpodp: true,
|
||||
frint: true,
|
||||
rng: true,
|
||||
bti: true,
|
||||
mte: true,
|
||||
..baseline_hwcaps()
|
||||
}
|
||||
);
|
||||
// The baseline hwcaps used in the (artificial) auxv test files.
|
||||
fn baseline_hwcaps() -> AtHwcap {
|
||||
AtHwcap {
|
||||
fp: true,
|
||||
asimd: true,
|
||||
aes: true,
|
||||
pmull: true,
|
||||
sha1: true,
|
||||
sha2: true,
|
||||
crc32: true,
|
||||
atomics: true,
|
||||
fphp: true,
|
||||
asimdhp: true,
|
||||
asimdrdm: true,
|
||||
lrcpc: true,
|
||||
dcpop: true,
|
||||
asimddp: true,
|
||||
ssbs: true,
|
||||
..AtHwcap::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn linux_empty_hwcap2_aarch64() {
|
||||
let file = concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/src/detect/test_data/linux-empty-hwcap2-aarch64.auxv"
|
||||
);
|
||||
println!("file: {file}");
|
||||
let v = auxv_from_file(file).unwrap();
|
||||
println!("HWCAP : 0x{:0x}", v.hwcap);
|
||||
println!("HWCAP2: 0x{:0x}", v.hwcap2);
|
||||
assert_eq!(AtHwcap::from(v), baseline_hwcaps());
|
||||
}
|
||||
#[test]
|
||||
fn linux_no_hwcap2_aarch64() {
|
||||
let file =
|
||||
concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/linux-no-hwcap2-aarch64.auxv");
|
||||
println!("file: {file}");
|
||||
let v = auxv_from_file(file).unwrap();
|
||||
println!("HWCAP : 0x{:0x}", v.hwcap);
|
||||
println!("HWCAP2: 0x{:0x}", v.hwcap2);
|
||||
assert_eq!(AtHwcap::from(v), baseline_hwcaps());
|
||||
}
|
||||
#[test]
|
||||
fn linux_hwcap2_aarch64() {
|
||||
let file =
|
||||
concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/linux-hwcap2-aarch64.auxv");
|
||||
println!("file: {file}");
|
||||
let v = auxv_from_file(file).unwrap();
|
||||
println!("HWCAP : 0x{:0x}", v.hwcap);
|
||||
println!("HWCAP2: 0x{:0x}", v.hwcap2);
|
||||
assert_eq!(
|
||||
AtHwcap::from(v),
|
||||
AtHwcap {
|
||||
// Some other HWCAP bits.
|
||||
paca: true,
|
||||
pacg: true,
|
||||
// HWCAP2-only bits.
|
||||
dcpodp: true,
|
||||
frint: true,
|
||||
rng: true,
|
||||
bti: true,
|
||||
mte: true,
|
||||
..baseline_hwcaps()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,20 +44,16 @@ pub(crate) struct AuxVec {
|
|||
///
|
||||
/// There is no perfect way of reading the auxiliary vector.
|
||||
///
|
||||
/// - If the `std_detect_dlsym_getauxval` cargo feature is enabled, this will use
|
||||
/// `getauxval` if its linked to the binary, and otherwise proceed to a fallback implementation.
|
||||
/// When `std_detect_dlsym_getauxval` is disabled, this will assume that `getauxval` is
|
||||
/// linked to the binary - if that is not the case the behavior is undefined.
|
||||
/// - Otherwise, if the `std_detect_file_io` cargo feature is enabled, it will
|
||||
/// - If [`getauxval`] is linked to the binary we use it, and otherwise it will
|
||||
/// try to read `/proc/self/auxv`.
|
||||
/// - If that fails, this function returns an error.
|
||||
///
|
||||
/// Note that run-time feature detection is not invoked for features that can
|
||||
/// be detected at compile-time.
|
||||
///
|
||||
/// Note: The `std_detect_dlsym_getauxval` cargo feature is ignored on
|
||||
/// `*-linux-{gnu,musl,ohos}*` and `*-android*` targets because we can safely assume `getauxval`
|
||||
/// is linked to the binary.
|
||||
/// Note: We always directly use `getauxval` on `*-linux-{gnu,musl,ohos}*` and
|
||||
/// `*-android*` targets rather than `dlsym` it because we can safely assume
|
||||
/// `getauxval` is linked to the binary.
|
||||
/// - `*-linux-gnu*` targets ([since Rust 1.64](https://blog.rust-lang.org/2022/08/01/Increasing-glibc-kernel-requirements.html))
|
||||
/// have glibc requirements higher than [glibc 2.16 that added `getauxval`](https://sourceware.org/legacy-ml/libc-announce/2012/msg00000.html).
|
||||
/// - `*-linux-musl*` targets ([at least since Rust 1.15](https://github.com/rust-lang/rust/blob/1.15.0/src/ci/docker/x86_64-musl/build-musl.sh#L15))
|
||||
|
|
@ -71,6 +67,7 @@ pub(crate) struct AuxVec {
|
|||
///
|
||||
/// [auxvec_h]: https://github.com/torvalds/linux/blob/master/include/uapi/linux/auxvec.h
|
||||
/// [auxv_docs]: https://docs.rs/auxv/0.3.3/auxv/
|
||||
/// [`getauxval`]: https://man7.org/linux/man-pages/man3/getauxval.3.html
|
||||
pub(crate) fn auxv() -> Result<AuxVec, ()> {
|
||||
// Try to call a getauxval function.
|
||||
if let Ok(hwcap) = getauxval(AT_HWCAP) {
|
||||
|
|
@ -115,16 +112,9 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
|
|||
let _ = hwcap;
|
||||
}
|
||||
|
||||
#[cfg(feature = "std_detect_file_io")]
|
||||
{
|
||||
// If calling getauxval fails, try to read the auxiliary vector from
|
||||
// its file:
|
||||
auxv_from_file("/proc/self/auxv").map_err(|_| ())
|
||||
}
|
||||
#[cfg(not(feature = "std_detect_file_io"))]
|
||||
{
|
||||
Err(())
|
||||
}
|
||||
// If calling getauxval fails, try to read the auxiliary vector from
|
||||
// its file:
|
||||
auxv_from_file("/proc/self/auxv").map_err(|_| ())
|
||||
}
|
||||
|
||||
/// Tries to read the `key` from the auxiliary vector by calling the
|
||||
|
|
@ -132,14 +122,16 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
|
|||
fn getauxval(key: usize) -> Result<usize, ()> {
|
||||
type F = unsafe extern "C" fn(libc::c_ulong) -> libc::c_ulong;
|
||||
cfg_select! {
|
||||
all(
|
||||
feature = "std_detect_dlsym_getauxval",
|
||||
not(all(
|
||||
any(
|
||||
all(
|
||||
target_os = "linux",
|
||||
any(target_env = "gnu", target_env = "musl", target_env = "ohos"),
|
||||
)),
|
||||
not(target_os = "android"),
|
||||
),
|
||||
target_os = "android",
|
||||
) => {
|
||||
let ffi_getauxval: F = libc::getauxval;
|
||||
}
|
||||
_ => {
|
||||
let ffi_getauxval: F = unsafe {
|
||||
let ptr = libc::dlsym(libc::RTLD_DEFAULT, c"getauxval".as_ptr());
|
||||
if ptr.is_null() {
|
||||
|
|
@ -148,23 +140,18 @@ fn getauxval(key: usize) -> Result<usize, ()> {
|
|||
core::mem::transmute(ptr)
|
||||
};
|
||||
}
|
||||
_ => {
|
||||
let ffi_getauxval: F = libc::getauxval;
|
||||
}
|
||||
}
|
||||
Ok(unsafe { ffi_getauxval(key as libc::c_ulong) as usize })
|
||||
}
|
||||
|
||||
/// Tries to read the auxiliary vector from the `file`. If this fails, this
|
||||
/// function returns `Err`.
|
||||
#[cfg(feature = "std_detect_file_io")]
|
||||
pub(super) fn auxv_from_file(file: &str) -> Result<AuxVec, alloc::string::String> {
|
||||
let file = super::read_file(file)?;
|
||||
auxv_from_file_bytes(&file)
|
||||
}
|
||||
|
||||
/// Read auxiliary vector from a slice of bytes.
|
||||
#[cfg(feature = "std_detect_file_io")]
|
||||
pub(super) fn auxv_from_file_bytes(bytes: &[u8]) -> Result<AuxVec, alloc::string::String> {
|
||||
// See <https://github.com/torvalds/linux/blob/v5.15/include/uapi/linux/auxvec.h>.
|
||||
//
|
||||
|
|
@ -181,7 +168,6 @@ pub(super) fn auxv_from_file_bytes(bytes: &[u8]) -> Result<AuxVec, alloc::string
|
|||
|
||||
/// Tries to interpret the `buffer` as an auxiliary vector. If that fails, this
|
||||
/// function returns `Err`.
|
||||
#[cfg(feature = "std_detect_file_io")]
|
||||
fn auxv_from_buf(buf: &[usize]) -> Result<AuxVec, alloc::string::String> {
|
||||
// Targets with only AT_HWCAP:
|
||||
#[cfg(any(
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ fn auxv_dump() {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std_detect_file_io")]
|
||||
cfg_select! {
|
||||
target_arch = "arm" => {
|
||||
// The tests below can be executed under qemu, where we do not have access to the test
|
||||
|
|
@ -86,7 +85,6 @@ cfg_select! {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "std_detect_file_io")]
|
||||
fn auxv_dump_procfs() {
|
||||
if let Ok(auxvec) = auxv_from_file("/proc/self/auxv") {
|
||||
println!("{:?}", auxvec);
|
||||
|
|
@ -103,7 +101,6 @@ fn auxv_dump_procfs() {
|
|||
target_arch = "s390x",
|
||||
))]
|
||||
#[test]
|
||||
#[cfg(feature = "std_detect_file_io")]
|
||||
fn auxv_crate_procfs() {
|
||||
if let Ok(procfs_auxv) = auxv_from_file("/proc/self/auxv") {
|
||||
assert_eq!(auxv().unwrap(), procfs_auxv);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
//! Run-time feature detection on Linux
|
||||
//!
|
||||
#[cfg(feature = "std_detect_file_io")]
|
||||
|
||||
use alloc::vec::Vec;
|
||||
|
||||
mod auxvec;
|
||||
|
||||
#[cfg(feature = "std_detect_file_io")]
|
||||
fn read_file(orig_path: &str) -> Result<Vec<u8>, alloc::string::String> {
|
||||
use alloc::format;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,7 @@
|
|||
extern crate std;
|
||||
|
||||
// rust-lang/rust#83888: removing `extern crate` gives an error that `vec_spare>
|
||||
#[cfg_attr(feature = "std_detect_file_io", allow(unused_extern_crates))]
|
||||
#[cfg(feature = "std_detect_file_io")]
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate alloc;
|
||||
|
||||
#[doc(hidden)]
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ test = { path = "../test", public = true }
|
|||
|
||||
# Forward features to the `std` crate as necessary
|
||||
[features]
|
||||
default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"]
|
||||
default = ["panic-unwind"]
|
||||
backtrace = ["std/backtrace"]
|
||||
backtrace-trace-only = ["std/backtrace-trace-only"]
|
||||
compiler-builtins-c = ["std/compiler-builtins-c"]
|
||||
|
|
@ -32,7 +32,5 @@ system-llvm-libunwind = ["std/system-llvm-libunwind"]
|
|||
optimize_for_size = ["std/optimize_for_size"]
|
||||
panic-unwind = ["std/panic-unwind"]
|
||||
profiler = ["dep:profiler_builtins"]
|
||||
std_detect_file_io = ["std/std_detect_file_io"]
|
||||
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
|
||||
windows_raw_dylib = ["std/windows_raw_dylib"]
|
||||
llvm_enzyme = ["std/llvm_enzyme"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue