Skip to content

Commit

Permalink
windows: always use RtlGenRandom on pre-1.78 Rust versions (#610)
Browse files Browse the repository at this point in the history
This PR adds detection of Rust compiler version in the build script
while compiling the crate for Windows targets.

If the version is smaller than 1.78, then we switch to the `windows7`
backend for all Windows targets. This is necessary because on those
older versions we can not disambiguate between win7 and win10 based
on the target triplet.
  • Loading branch information
newpavlov authored Mar 3, 2025
1 parent 491d9d4 commit cf1f37e
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 5 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)',
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fn get_random_u128() -> Result<u128, getrandom::Error> {
| 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`]
Expand Down
52 changes: 50 additions & 2 deletions build.rs
Original file line number Diff line number Diff line change
@@ -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<u64> {
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"),
_ => {}
}
}
}
2 changes: 1 addition & 1 deletion src/backends.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)] {
Expand Down

0 comments on commit cf1f37e

Please sign in to comment.