diff --git a/Cargo.toml b/Cargo.toml index 4a982ee7..160b76d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,13 @@ rustc-dep-of-std = ["dep:compiler_builtins", "dep:core"] # i.e. avoid unconditionally enabling it in library crates. wasm_js = ["dep:wasm-bindgen", "dep:js-sys"] +# Optional backend: custom-fallback +# This flag enables the use of a 3rd party backend when this crate does not have a suitable option. +# This flag can be overridden using the getrandom_no_fallback RUSTFLAG. +# WARNING: It is highly recommended to enable this feature only for binary crates and tests, +# i.e. avoid unconditionally enabling it in library crates. +custom-fallback = [] + [dependencies] cfg-if = "1" @@ -90,6 +97,7 @@ check-cfg = [ 'cfg(getrandom_test_linux_without_fallback)', 'cfg(getrandom_test_netbsd_fallback)', 'cfg(target_os, values("cygwin"))', # TODO(MSRV 1.86): Remove this. + 'cfg(getrandom_no_fallback)', ] [package.metadata.docs.rs] diff --git a/src/backends.rs b/src/backends.rs index dbe93456..fcf04852 100644 --- a/src/backends.rs +++ b/src/backends.rs @@ -8,6 +8,8 @@ cfg_if! { if #[cfg(getrandom_backend = "custom")] { + // We allow 3rd party backends when `getrandom_backend = "custom"` is enabled, as it can + // only be enabled by the final binary, even when `custom-fallback` isn't enabled. mod custom; pub use custom::*; } else if #[cfg(getrandom_backend = "linux_getrandom")] { @@ -31,6 +33,7 @@ cfg_if! { mod wasm_js; pub use wasm_js::*; } else { + // If `wasm_js` is enabled the user intended for it to be used, compiler error compile_error!(concat!( "The \"wasm_js\" backend requires the `wasm_js` feature \ for `getrandom`. For more information see: \ @@ -142,11 +145,17 @@ cfg_if! { } else if #[cfg(target_env = "p2")] { mod wasi_p2; pub use wasi_p2::*; - } else { + } else if #[cfg(not(feature = "custom-fallback"))] { + // If the user has not enabled `custom-fallback` then no backend is available compile_error!( "Unknown version of WASI (only previews 1 and 2 are supported) \ or Rust version older than 1.80 was used" ); + } else if #[cfg(getrandom_no_fallback)] { + compile_error!( + "The `getrandom_no_fallback` RUSTFLAG has been set,\ + but the \"custom-fallback\" feature has been enabled." + ); } } } else if #[cfg(target_os = "hermit")] { @@ -167,6 +176,19 @@ cfg_if! { } else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] { mod rdrand; pub use rdrand::*; + } else if #[cfg(all(feature = "custom-fallback", not(getrandom_no_fallback)))] { + // Since `getrandom_no_fallback` is not enabled, allow 3rd party backends via `custom`. + // This is a duplicate of the first branch in this cfg_if statement to allow `custom` to either + // be the highest or lowest priority based on `getrandom_backend = "custom"`. + mod custom; + pub use custom::*; + } else if #[cfg(all(feature = "custom-fallback", getrandom_no_fallback))] { + compile_error!( + "The `getrandom_no_fallback` RUSTFLAG has been set,\ + but the \"custom-fallback\" feature has been enabled.\ + This typically happens when a dependency provides a custom fallback\ + but you have forbidden it using `getrandom_no_fallback`." + ); } else if #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))] { compile_error!(concat!( "The wasm32-unknown-unknown targets are not supported by default; \ @@ -177,7 +199,8 @@ cfg_if! { )); } else { compile_error!(concat!( - "target is not supported. You may need to define a custom backend see: \ + "target is not supported by a first party backend.\ + You may need to define a custom backend see: \ https://docs.rs/getrandom/", env!("CARGO_PKG_VERSION"), "/#custom-backend" )); }