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:
Stuart Cook 2026-01-11 14:27:57 +11:00 committed by GitHub
commit 26da51d2a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 91 additions and 158 deletions

View file

@ -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"]

View file

@ -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 = []

View file

@ -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

View file

@ -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;
}

View file

@ -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()
}
);
}

View file

@ -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(

View file

@ -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);

View file

@ -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;

View file

@ -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)]

View file

@ -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"]