Skip to content

Commit 74e1087

Browse files
leon-xdLeon Durrenbergerwmmc88
authored
refactor!: Remove lazy static instances (#250)
Signed-off-by: Leon Durrenberger <[email protected]> Co-authored-by: Leon Durrenberger <[email protected]> Co-authored-by: Melvin Wang <[email protected]>
1 parent 4d4f997 commit 74e1087

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+573
-274
lines changed

Cargo.lock

+2-13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ cfg-if = "1.0.0"
4545
clap = "4.5.9"
4646
clap-cargo = "0.14.1"
4747
itertools = "0.13.0"
48-
lazy_static = "1.5.0"
4948
paste = "1.0.15"
5049
pretty_assertions = "1.4.1"
5150
proc-macro2 = "1.0.86"

crates/wdk-build/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ cargo_metadata.workspace = true
2020
cfg-if.workspace = true
2121
clap = { workspace = true, features = ["derive"] }
2222
clap-cargo.workspace = true
23-
lazy_static.workspace = true
2423
paste.workspace = true
2524
rustversion.workspace = true
2625
serde = { workspace = true, features = ["derive"] }

crates/wdk-build/src/lib.rs

+6-9
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ mod utils;
2222

2323
mod bindgen;
2424

25-
use std::{env, path::PathBuf};
25+
use std::{env, path::PathBuf, sync::LazyLock};
2626

2727
use cargo_metadata::MetadataCommand;
2828
use serde::{Deserialize, Serialize};
@@ -1146,14 +1146,11 @@ pub fn configure_wdk_binary_build() -> Result<(), ConfigError> {
11461146
Config::from_env_auto()?.configure_binary_build()
11471147
}
11481148

1149-
// This currently only exports the driver type, but may export more metadata in
1150-
// the future. `EXPORTED_CFG_SETTINGS` is a mapping of cfg key to allowed cfg
1151-
// values
1152-
lazy_static::lazy_static! {
1153-
// FIXME: replace lazy_static with std::Lazy once available: https://github.com/rust-lang/rust/issues/109736
1154-
static ref EXPORTED_CFG_SETTINGS: Vec<(&'static str, Vec<&'static str>)> =
1155-
vec![("DRIVER_MODEL-DRIVER_TYPE", vec!["WDM", "KMDF", "UMDF"])];
1156-
}
1149+
/// This currently only exports the driver type, but may export more metadata in
1150+
/// the future. `EXPORTED_CFG_SETTINGS` is a mapping of cfg key to allowed cfg
1151+
/// values
1152+
static EXPORTED_CFG_SETTINGS: LazyLock<Vec<(&'static str, Vec<&'static str>)>> =
1153+
LazyLock::new(|| vec![("DRIVER_MODEL-DRIVER_TYPE", vec!["WDM", "KMDF", "UMDF"])]);
11571154

11581155
#[cfg(test)]
11591156
mod tests {

crates/wdk-build/src/metadata/ser.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ impl<'a> ser::SerializeStruct for &'a mut Serializer<'a> {
370370

371371
impl<'a> Serializer<'a> {
372372
/// Create a new instance of the `Serializer` struct
373-
pub fn new(dst: &'a mut Vec<(String, String)>) -> Self {
373+
pub const fn new(dst: &'a mut Vec<(String, String)>) -> Self {
374374
Self {
375375
root_key_name: None,
376376
dst,
@@ -379,7 +379,7 @@ impl<'a> Serializer<'a> {
379379

380380
/// Create a new instance of the `Serializer` struct with a prefix used as
381381
/// the root for all keys
382-
pub fn with_prefix(prefix: String, dst: &'a mut Vec<(String, String)>) -> Self {
382+
pub const fn with_prefix(prefix: String, dst: &'a mut Vec<(String, String)>) -> Self {
383383
Self {
384384
root_key_name: Some(prefix),
385385
dst,

crates/wdk-macros/src/lib.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,24 @@ impl DerivedASTFragments {
229229
// arguments for the WDF function is safe befause WDF maintains the strict mapping between the
230230
// function table index and the correct function pointer type.
231231
unsafe {
232+
let wdf_function_table = wdk_sys::WdfFunctions;
233+
let wdf_function_count = wdk_sys::wdf::__private::get_wdf_function_count();
234+
235+
// SAFETY: This is safe because:
236+
// 1. `WdfFunctions` is valid for reads for `{NUM_WDF_FUNCTIONS_PLACEHOLDER}` * `core::mem::size_of::<WDFFUNC>()`
237+
// bytes, and is guaranteed to be aligned and it must be properly aligned.
238+
// 2. `WdfFunctions` points to `{NUM_WDF_FUNCTIONS_PLACEHOLDER}` consecutive properly initialized values of
239+
// type `WDFFUNC`.
240+
// 3. WDF does not mutate the memory referenced by the returned slice for for its entire `'static' lifetime.
241+
// 4. The total size, `{NUM_WDF_FUNCTIONS_PLACEHOLDER}` * `core::mem::size_of::<WDFFUNC>()`, of the slice must be no
242+
// larger than `isize::MAX`. This is proven by the below `const_assert!`.
243+
244+
debug_assert!(isize::try_from(wdf_function_count * core::mem::size_of::<wdk_sys::WDFFUNC>()).is_ok());
245+
let wdf_function_table = core::slice::from_raw_parts(wdf_function_table, wdf_function_count);
246+
232247
core::mem::transmute(
233248
// FIXME: investigate why _WDFFUNCENUM does not have a generated type alias without the underscore prefix
234-
wdk_sys::WDF_FUNCTION_TABLE[wdk_sys::_WDFFUNCENUM::#function_table_index as usize],
249+
wdf_function_table[wdk_sys::_WDFFUNCENUM::#function_table_index as usize],
235250
)
236251
}
237252
);

crates/wdk-sys/Cargo.toml

-5
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,13 @@ bindgen.workspace = true
2222
cargo_metadata.workspace = true
2323
cc.workspace = true
2424
cfg-if.workspace = true
25-
lazy_static.workspace = true
2625
serde_json.workspace = true
2726
thiserror.workspace = true
2827
tracing.workspace = true
2928
tracing-subscriber = { workspace = true, features = ["env-filter"] }
3029
wdk-build.workspace = true
3130

3231
[dependencies]
33-
lazy_static = { workspace = true, features = ["spin_no_std"] }
3432
rustversion.workspace = true
3533
wdk-macros.workspace = true
3634

@@ -76,6 +74,3 @@ missing_crate_level_docs = "warn"
7674
private_intra_doc_links = "warn"
7775
redundant_explicit_links = "warn"
7876
unescaped_backticks = "warn"
79-
80-
[package.metadata.cargo-machete]
81-
ignored = ["lazy_static"] # lazy_static is used in code generated by build.rs

crates/wdk-sys/build.rs

+50-86
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ use std::{
1212
io::Write,
1313
panic,
1414
path::{Path, PathBuf},
15+
sync::LazyLock,
1516
thread,
1617
};
1718

1819
use anyhow::Context;
1920
use bindgen::CodegenConfig;
20-
use lazy_static::lazy_static;
2121
use tracing::{info, info_span, trace, Span};
2222
use tracing_subscriber::{
2323
filter::{LevelFilter, ParseError},
@@ -34,61 +34,33 @@ use wdk_build::{
3434
UmdfConfig,
3535
};
3636

37-
const NUM_WDF_FUNCTIONS_PLACEHOLDER: &str =
38-
"<PLACEHOLDER FOR IDENTIFIER FOR VARIABLE CORRESPONDING TO NUMBER OF WDF FUNCTIONS>";
39-
const WDF_FUNCTION_COUNT_DECLARATION_PLACEHOLDER: &str =
40-
"<PLACEHOLDER FOR DECLARATION OF wdf_function_count VARIABLE>";
4137
const OUT_DIR_PLACEHOLDER: &str =
4238
"<PLACEHOLDER FOR LITERAL VALUE CONTAINING OUT_DIR OF wdk-sys CRATE>";
4339
const WDFFUNCTIONS_SYMBOL_NAME_PLACEHOLDER: &str =
4440
"<PLACEHOLDER FOR LITERAL VALUE CONTAINING WDFFUNCTIONS SYMBOL NAME>";
45-
46-
/// Rust code snippet that declares and initializes `wdf_function_count` based
47-
/// off the bindgen-generated `WdfFunctionCount` symbol
48-
///
49-
/// This is only used in configurations where WDF generates a
50-
/// `WdfFunctionCount`.
51-
const WDF_FUNCTION_COUNT_DECLARATION_EXTERNAL_SYMBOL: &str = "
52-
// SAFETY: `crate::WdfFunctionCount` is generated as a mutable static, but is not supposed \
53-
to be ever mutated by WDF.
54-
let wdf_function_count = unsafe { crate::WdfFunctionCount } as usize;";
55-
/// Rust code snippet that declares and initializes `wdf_function_count` based
56-
/// off the bindgen-generated `WdfFunctionTableNumEntries` constant
57-
///
58-
/// This is only used in older WDF versions that didn't generate a
59-
/// `WdfFunctionCount` symbol
60-
const WDF_FUNCTION_COUNT_DECLARATION_TABLE_INDEX: &str = "
61-
let wdf_function_count = crate::_WDFFUNCENUM::WdfFunctionTableNumEntries as usize;";
62-
63-
// FIXME: replace lazy_static with std::Lazy once available: https://github.com/rust-lang/rust/issues/109736
64-
lazy_static! {
65-
static ref WDF_FUNCTION_TABLE_TEMPLATE: String = format!(
66-
r#"
67-
// FIXME: replace lazy_static with std::Lazy once available: https://github.com/rust-lang/rust/issues/109736
68-
#[cfg(any(driver_model__driver_type = "KMDF", driver_model__driver_type = "UMDF"))]
69-
lazy_static::lazy_static! {{
70-
#[allow(missing_docs)]
71-
pub static ref WDF_FUNCTION_TABLE: &'static [crate::WDFFUNC] = {{
72-
// SAFETY: `WdfFunctions` is generated as a mutable static, but is not supposed to be ever mutated by WDF.
73-
let wdf_function_table = unsafe {{ crate::WdfFunctions }};
74-
{WDF_FUNCTION_COUNT_DECLARATION_PLACEHOLDER}
75-
76-
// SAFETY: This is safe because:
77-
// 1. `WdfFunctions` is valid for reads for `{NUM_WDF_FUNCTIONS_PLACEHOLDER}` * `core::mem::size_of::<WDFFUNC>()`
78-
// bytes, and is guaranteed to be aligned and it must be properly aligned.
79-
// 2. `WdfFunctions` points to `{NUM_WDF_FUNCTIONS_PLACEHOLDER}` consecutive properly initialized values of
80-
// type `WDFFUNC`.
81-
// 3. WDF does not mutate the memory referenced by the returned slice for for its entire `'static' lifetime.
82-
// 4. The total size, `{NUM_WDF_FUNCTIONS_PLACEHOLDER}` * `core::mem::size_of::<WDFFUNC>()`, of the slice must be no
83-
// larger than `isize::MAX`. This is proven by the below `debug_assert!`.
84-
unsafe {{
85-
debug_assert!(isize::try_from(wdf_function_count * core::mem::size_of::<crate::WDFFUNC>()).is_ok());
86-
core::slice::from_raw_parts(wdf_function_table, wdf_function_count)
87-
}}
88-
}};
89-
}}"#
90-
);
91-
static ref CALL_UNSAFE_WDF_BINDING_TEMPLATE: String = format!(
41+
const WDF_FUNCTION_COUNT_PLACEHOLDER: &str =
42+
"<PLACEHOLDER FOR EXPRESSION FOR NUMBER OF WDF FUNCTIONS IN `wdk_sys::WdfFunctions`";
43+
44+
const WDF_FUNCTION_COUNT_DECLARATION_EXTERNAL_SYMBOL: &str =
45+
"// SAFETY: `crate::WdfFunctionCount` is generated as a mutable static, but is not supposed \
46+
to be ever mutated by WDF.
47+
(unsafe { crate::WdfFunctionCount }) as usize";
48+
49+
const WDF_FUNCTION_COUNT_DECLARATION_TABLE_INDEX: &str =
50+
"crate::_WDFFUNCENUM::WdfFunctionTableNumEntries as usize";
51+
52+
static WDF_FUNCTION_COUNT_FUNCTION_TEMPLATE: LazyLock<String> = LazyLock::new(|| {
53+
format!(
54+
r"/// Returns the number of functions available in the WDF function table.
55+
/// Should not be used in public API.
56+
pub fn get_wdf_function_count() -> usize {{
57+
{WDF_FUNCTION_COUNT_PLACEHOLDER}
58+
}}"
59+
)
60+
});
61+
62+
static CALL_UNSAFE_WDF_BINDING_TEMPLATE: LazyLock<String> = LazyLock::new(|| {
63+
format!(
9264
r#"
9365
/// A procedural macro that allows WDF functions to be called by name.
9466
///
@@ -138,18 +110,20 @@ macro_rules! call_unsafe_wdf_function_binding {{
138110
)
139111
}}
140112
}}"#
141-
);
142-
static ref TEST_STUBS_TEMPLATE: String = format!(
113+
)
114+
});
115+
116+
static TEST_STUBS_TEMPLATE: LazyLock<String> = LazyLock::new(|| {
117+
format!(
143118
r"
144119
use crate::WDFFUNC;
145120
146121
/// Stubbed version of the symbol that [`WdfFunctions`] links to so that test targets will compile
147122
#[no_mangle]
148123
pub static mut {WDFFUNCTIONS_SYMBOL_NAME_PLACEHOLDER}: *const WDFFUNC = core::ptr::null();
149-
"
150-
);
151-
}
152-
124+
",
125+
)
126+
});
153127
type GenerateFn = fn(&Path, &Config) -> Result<(), ConfigError>;
154128

155129
const BINDGEN_FILE_GENERATORS_TUPLES: &[(&str, GenerateFn)] = &[
@@ -347,15 +321,15 @@ fn generate_hid(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
347321
}
348322
}
349323

350-
/// Generates a `wdf_function_table.rs` file in `OUT_DIR` which contains the
351-
/// definition of `WDF_FUNCTION_TABLE`. This is required to be generated here
352-
/// since the size of the table is derived from either a global symbol
353-
/// (`WDF_FUNCTION_COUNT`) that newer WDF versions expose, or an enum that older
354-
/// versions use.
355-
fn generate_wdf_function_table(out_path: &Path, config: &Config) -> std::io::Result<()> {
324+
/// Generates a `wdf_function_count.rs` file in `OUT_DIR` which contains the
325+
/// definition of the function `get_wdf_function_count()`. This is required to
326+
/// be generated here since the size of the table is derived from either a
327+
/// global symbol that newer WDF versions expose, or an enum that older versions
328+
/// use.
329+
fn generate_wdf_function_count(out_path: &Path, config: &Config) -> std::io::Result<()> {
356330
const MINIMUM_MINOR_VERSION_TO_GENERATE_WDF_FUNCTION_COUNT: u8 = 25;
357331

358-
let generated_file_path = out_path.join("wdf_function_table.rs");
332+
let generated_file_path = out_path.join("wdf_function_count.rs");
359333
let mut generated_file = std::fs::File::create(generated_file_path)?;
360334

361335
let is_wdf_function_count_generated = match *config {
@@ -392,26 +366,16 @@ fn generate_wdf_function_table(out_path: &Path, config: &Config) -> std::io::Res
392366
}
393367
};
394368

395-
let wdf_function_table_code_snippet = if is_wdf_function_count_generated {
396-
WDF_FUNCTION_TABLE_TEMPLATE
397-
.replace(NUM_WDF_FUNCTIONS_PLACEHOLDER, "crate::WdfFunctionCount")
398-
.replace(
399-
WDF_FUNCTION_COUNT_DECLARATION_PLACEHOLDER,
400-
WDF_FUNCTION_COUNT_DECLARATION_EXTERNAL_SYMBOL,
401-
)
402-
} else {
403-
WDF_FUNCTION_TABLE_TEMPLATE
404-
.replace(
405-
NUM_WDF_FUNCTIONS_PLACEHOLDER,
406-
"crate::_WDFFUNCENUM::WdfFunctionTableNumEntries",
407-
)
408-
.replace(
409-
WDF_FUNCTION_COUNT_DECLARATION_PLACEHOLDER,
410-
WDF_FUNCTION_COUNT_DECLARATION_TABLE_INDEX,
411-
)
412-
};
369+
let wdf_function_table_count_snippet = WDF_FUNCTION_COUNT_FUNCTION_TEMPLATE.replace(
370+
WDF_FUNCTION_COUNT_PLACEHOLDER,
371+
if is_wdf_function_count_generated {
372+
WDF_FUNCTION_COUNT_DECLARATION_EXTERNAL_SYMBOL
373+
} else {
374+
WDF_FUNCTION_COUNT_DECLARATION_TABLE_INDEX
375+
},
376+
);
413377

414-
generated_file.write_all(wdf_function_table_code_snippet.as_bytes())?;
378+
generated_file.write_all(wdf_function_table_count_snippet.as_bytes())?;
415379
Ok(())
416380
}
417381

@@ -540,8 +504,8 @@ fn main() -> anyhow::Result<()> {
540504
.expect("Scoped Thread should spawn successfully"),
541505
);
542506

543-
info_span!("wdf_function_table.rs generation").in_scope(|| {
544-
generate_wdf_function_table(out_path, config)?;
507+
info_span!("wdf_function_count.rs generation").in_scope(|| {
508+
generate_wdf_function_count(out_path, config)?;
545509
Ok::<(), std::io::Error>(())
546510
})?;
547511

crates/wdk-sys/src/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
66
#![no_std]
77

8-
#[cfg(any(driver_model__driver_type = "KMDF", driver_model__driver_type = "UMDF"))]
9-
pub use wdf::WDF_FUNCTION_TABLE;
108
#[cfg(any(
119
driver_model__driver_type = "WDM",
1210
driver_model__driver_type = "KMDF",

crates/wdk-sys/src/wdf.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,13 @@ mod bindings {
2020
include!(concat!(env!("OUT_DIR"), "/wdf.rs"));
2121
}
2222

23-
include!(concat!(env!("OUT_DIR"), "/wdf_function_table.rs"));
23+
// This is a workaround to expose the generated function count to the
24+
// `call_unsafe_wdf_function_binding` proc-macro, so that the macro-generated
25+
// code can determine the slice size at runtime. When we are able to
26+
// conditionally compile based off a cfg range for WDF version, this module
27+
// can be removed and the runtime check can be replaced with a conditional
28+
// compilation: https://github.com/microsoft/windows-drivers-rs/issues/276
29+
#[doc(hidden)]
30+
pub mod __private {
31+
include!(concat!(env!("OUT_DIR"), "/wdf_function_count.rs"));
32+
}

0 commit comments

Comments
 (0)