diff --git a/CHANGELOG.md b/CHANGELOG.md index 96dba823..f27fdbef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.3.2] - UNRELEASED + +### Changed +- Always use `RtlGenRandom` on Windows targets when compiling with pre-1.78 Rust [#610] + +[#610]: https://github.com/rust-random/getrandom/pull/610 + ## [0.3.1] - 2025-01-28 ### Fixed @@ -526,6 +533,8 @@ Publish initial implementation. ## [0.0.0] - 2019-01-19 Publish an empty template library. +[0.3.2]: https://github.com/rust-random/getrandom/compare/v0.3.0...v0.3.2 +[0.3.1]: https://github.com/rust-random/getrandom/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/rust-random/getrandom/compare/v0.2.15...v0.3.0 [0.2.15]: https://github.com/rust-random/getrandom/compare/v0.2.14...v0.2.15 [0.2.14]: https://github.com/rust-random/getrandom/compare/v0.2.13...v0.2.14 diff --git a/Cargo.toml b/Cargo.toml index 2441555b..a5fb2dbe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,7 +67,7 @@ libc = { version = "0.2.154", default-features = false } wasi = { version = "0.14", default-features = false } # windows7 -[target.'cfg(all(windows, not(target_vendor = "win7")))'.dependencies] +[target.'cfg(all(windows, not(target_vendor = "win7"), not(getrandom_windows_legacy)))'.dependencies] windows-targets = "0.53" # wasm_js @@ -83,6 +83,7 @@ level = "warn" check-cfg = [ 'cfg(getrandom_backend, values("custom", "rdrand", "rndr", "linux_getrandom", "wasm_js"))', 'cfg(getrandom_msan)', + 'cfg(getrandom_windows_legacy)', 'cfg(getrandom_test_linux_fallback)', 'cfg(getrandom_test_linux_without_fallback)', 'cfg(getrandom_test_netbsd_fallback)', diff --git a/README.md b/README.md index 79082409..6fb9b00e 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ fn get_random_u128() -> Result { | Target | Target Triple | Implementation | ------------------ | ------------------ | -------------- | Linux, Android | `*‑linux‑*` | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random` -| Windows 10+ | `*‑windows‑*` | [`ProcessPrng`] +| Windows 10+ | `*‑windows‑*` | [`ProcessPrng`] on Rust 1.78+, [`RtlGenRandom`] otherwise | Windows 7, 8 | `*-win7‑windows‑*` | [`RtlGenRandom`] | macOS | `*‑apple‑darwin` | [`getentropy`][3] | iOS, tvOS, watchOS | `*‑apple‑{ios,tvos,watchos}` | [`CCRandomGenerateBytes`] diff --git a/build.rs b/build.rs index 15d41919..ea9baaaa 100644 --- a/build.rs +++ b/build.rs @@ -1,9 +1,57 @@ -// Automatically detect cfg(sanitize = "memory") even if cfg(sanitize) isn't -// supported. Build scripts get cfg() info, even if the cfg is unstable. +use std::{env, ffi::OsString, process::Command}; + +/// Tries to get the minor version of the Rust compiler in use. +/// If it fails for any reason, returns `None`. +/// +/// Based on the `rustc_version` crate. +fn rustc_minor_version() -> Option { + let rustc = env::var_os("RUSTC").unwrap_or_else(|| OsString::from("rustc")); + let mut cmd = if let Some(wrapper) = env::var_os("RUSTC_WRAPPER").filter(|w| !w.is_empty()) { + let mut cmd = Command::new(wrapper); + cmd.arg(rustc); + cmd + } else { + Command::new(rustc) + }; + + let out = cmd.arg("-vV").output().ok()?; + + if !out.status.success() { + return None; + } + + let stdout = std::str::from_utf8(&out.stdout).ok()?; + + // Assumes that the first line contains "rustc 1.xx.0-channel (abcdef 2025-01-01)" + // where "xx" is the minor version which we want to extract + let mut lines = stdout.lines(); + let first_line = lines.next()?; + let minor_ver_str = first_line.split(".").nth(1)?; + minor_ver_str.parse().ok() +} + fn main() { + // Automatically detect cfg(sanitize = "memory") even if cfg(sanitize) isn't + // supported. Build scripts get cfg() info, even if the cfg is unstable. println!("cargo:rerun-if-changed=build.rs"); let santizers = std::env::var("CARGO_CFG_SANITIZE").unwrap_or_default(); if santizers.contains("memory") { println!("cargo:rustc-cfg=getrandom_msan"); } + + // Use `RtlGenRandom` on older compiler versions since win7 targets + // were introduced only in Rust 1.78 + let target_family = env::var_os("CARGO_CFG_TARGET_FAMILY").and_then(|f| f.into_string().ok()); + if target_family.as_deref() == Some("windows") { + /// Minor version of the Rust compiler in which win7 targets were inroduced + const WIN7_INTRODUCED_MINOR_VER: u64 = 78; + + match rustc_minor_version() { + Some(minor_ver) if minor_ver < WIN7_INTRODUCED_MINOR_VER => { + println!("cargo:rustc-cfg=getrandom_windows_legacy"); + } + None => println!("cargo:warning=Couldn't detect minor version of the Rust compiler"), + _ => {} + } + } } diff --git a/src/backends.rs b/src/backends.rs index 3b98a61d..f97059c4 100644 --- a/src/backends.rs +++ b/src/backends.rs @@ -145,7 +145,7 @@ cfg_if! { } else if #[cfg(target_os = "solid_asp3")] { mod solid; pub use solid::*; - } else if #[cfg(all(windows, target_vendor = "win7"))] { + } else if #[cfg(all(windows, any(target_vendor = "win7", getrandom_windows_legacy)))] { mod windows7; pub use windows7::*; } else if #[cfg(windows)] {