diff --git a/crates/wdk-build/Cargo.toml b/crates/wdk-build/Cargo.toml index 4f12dd50..ad92f32f 100644 --- a/crates/wdk-build/Cargo.toml +++ b/crates/wdk-build/Cargo.toml @@ -35,11 +35,6 @@ windows = { workspace = true, features = [ [dev-dependencies] windows = { workspace = true, features = ["Win32_UI_Shell"] } -[features] -default = [] - -hid = [] - [lints.rust.unexpected_cfgs] level = "warn" check-cfg = ["cfg(wdk_build_unstable)", "cfg(skip_umdf_static_crt_check)"] diff --git a/crates/wdk-build/src/lib.rs b/crates/wdk-build/src/lib.rs index 1d9d1230..28162ae0 100644 --- a/crates/wdk-build/src/lib.rs +++ b/crates/wdk-build/src/lib.rs @@ -190,6 +190,13 @@ rustflags = [\"-C\", \"target-feature=+crt-static\"] SerdeError(#[from] metadata::Error), } +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum ApiSubset { + Base, + Wdf, + Hid, +} + impl Default for Config { #[must_use] fn default() -> Self { @@ -629,53 +636,70 @@ impl Config { .map(std::string::ToString::to_string) } - pub fn base_headers(&self) -> impl Iterator { - match &self.driver_config { - DriverConfig::Wdm | DriverConfig::Kmdf(_) => { - vec!["ntifs.h", "ntddk.h"] - } - DriverConfig::Umdf(_) => { - vec!["windows.h"] + pub fn headers(&self, api_subset: ApiSubset) -> impl Iterator { + match api_subset { + ApiSubset::Base => match &self.driver_config { + DriverConfig::Wdm | DriverConfig::Kmdf(_) => { + vec!["ntifs.h", "ntddk.h"] + } + DriverConfig::Umdf(_) => { + vec!["windows.h"] + } + }, + ApiSubset::Wdf => { + if let DriverConfig::Kmdf(_) | DriverConfig::Umdf(_) = self.driver_config { + vec!["wdf.h"] + } else { + vec![] + } } - } - .into_iter() - .map(std::string::ToString::to_string) - } + ApiSubset::Hid => { + // HID Headers list from https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/_hid/ + let mut hid_headers = vec!["hidclass.h", "hidsdi.h", "hidpi.h", "vhf.h"]; - pub fn wdf_headers(&self) -> impl Iterator { - ["wdf.h"].into_iter().map(std::string::ToString::to_string) - } + if let DriverConfig::Wdm | DriverConfig::Kmdf(_) = self.driver_config { + hid_headers.extend(["hidpddi.h", "hidport.h", "kbdmou.h", "ntdd8042.h"]); + } - #[cfg(feature = "hid")] - pub fn hid_headers(&self) -> impl Iterator { - // HID Headers list from https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/_hid/ - { - let mut hid_headers = vec!["hidclass.h", "hidsdi.h", "hidpi.h", "vhf.h"]; - if let DriverConfig::Wdm | DriverConfig::Kmdf(_) = self.driver_config { - hid_headers.extend(["hidpddi.h", "hidport.h", "kbdmou.h", "ntdd8042.h"]); - } - if let DriverConfig::Kmdf(_) = self.driver_config { - hid_headers.extend(["HidSpiCx/1.0/hidspicx.h"]); + if let DriverConfig::Kmdf(_) = self.driver_config { + hid_headers.extend(["HidSpiCx/1.0/hidspicx.h"]); + } + + hid_headers } - hid_headers } .into_iter() .map(std::string::ToString::to_string) } - pub fn bindgen_base_header_contents(&self) -> String { - let mut header_contents = self.base_headers().fold(String::new(), |mut acc, header| { - acc.push_str(r#"#include ""#); - acc.push_str(&header); - acc.push_str("\"\n"); - acc - }); + pub fn bindgen_header_contents( + &self, + api_subsets: impl IntoIterator, + ) -> String { + api_subsets + .into_iter() + .fold(String::new(), |mut acc, api_subset| { + acc.push_str( + self.headers(api_subset) + .fold(String::new(), |mut acc, header| { + acc.push_str(r#"#include ""#); + acc.push_str(&header); + acc.push_str("\"\n"); + acc + }) + .as_str(), + ); - if let DriverConfig::Wdm | DriverConfig::Kmdf(_) = self.driver_config { - // TODO: Why is there no definition for this struct? Maybe blocklist this struct - // in bindgen. - header_contents.push_str( - r" + if api_subset == ApiSubset::Base + && matches!( + self.driver_config, + DriverConfig::Wdm | DriverConfig::Kmdf(_) + ) + { + // TODO: Why is there no definition for this struct? Maybe blocklist this struct + // in bindgen. + acc.push_str( + r" typedef union _KGDTENTRY64 { struct @@ -729,32 +753,10 @@ typedef union _KIDTENTRY64 unsigned __int64 Alignment; } KIDTENTRY64, *PKIDTENTRY64; ", - ); - } - - header_contents - } - - pub fn bindgen_wdf_header_contents(&self) -> Option { - if let DriverConfig::Kmdf(_) | DriverConfig::Umdf(_) = self.driver_config { - return Some(self.wdf_headers().fold(String::new(), |mut acc, header| { - acc.push_str(r#"#include ""#); - acc.push_str(&header); - acc.push_str("\"\n"); + ); + } acc - })); - } - None - } - - #[cfg(feature = "hid")] - pub fn bindgen_hid_header_contents(&self) -> String { - self.hid_headers().fold(String::new(), |mut acc, header| { - acc.push_str(r#"#include ""#); - acc.push_str(&header); - acc.push_str("\"\n"); - acc - }) + }) } /// Configure a Cargo build of a library that depends on the WDK. This diff --git a/crates/wdk-sys/Cargo.toml b/crates/wdk-sys/Cargo.toml index f76caef2..531c4adf 100644 --- a/crates/wdk-sys/Cargo.toml +++ b/crates/wdk-sys/Cargo.toml @@ -37,7 +37,7 @@ wdk-macros.workspace = true [features] default = [] -hid = ["wdk-build/hid"] +hid = [] nightly = ["wdk-macros/nightly"] test-stubs = [] diff --git a/crates/wdk-sys/build.rs b/crates/wdk-sys/build.rs index d78c90a3..bc36c00e 100644 --- a/crates/wdk-sys/build.rs +++ b/crates/wdk-sys/build.rs @@ -25,6 +25,7 @@ use tracing_subscriber::{ }; use wdk_build::{ configure_wdk_library_build_and_then, + ApiSubset, BuilderExt, Config, ConfigError, @@ -217,21 +218,12 @@ fn initialize_tracing() -> Result<(), ParseError> { fn generate_constants(out_path: &Path, config: &Config) -> Result<(), ConfigError> { info!("Generating bindings to WDK: constants.rs"); - let header_contents = { - let mut contents = config.bindgen_base_header_contents(); - - if let Some(wdf_header_contents) = config.bindgen_wdf_header_contents() { - contents.push_str(&wdf_header_contents); - } - + let header_contents = config.bindgen_header_contents([ + ApiSubset::Base, + ApiSubset::Wdf, #[cfg(feature = "hid")] - if env::var("CARGO_FEATURE_HID").is_ok() { - // TODO: this check can be removed? - contents.push_str(&config.bindgen_hid_header_contents()); - }; - - contents - }; + ApiSubset::Hid, + ]); trace!(header_contents = ?header_contents); let bindgen_builder = bindgen::Builder::wdk_default(config)? @@ -248,20 +240,12 @@ fn generate_constants(out_path: &Path, config: &Config) -> Result<(), ConfigErro fn generate_types(out_path: &Path, config: &Config) -> Result<(), ConfigError> { info!("Generating bindings to WDK: types.rs"); - let header_contents = { - let mut contents = config.bindgen_base_header_contents(); - - if let Some(wdf_header_contents) = config.bindgen_wdf_header_contents() { - contents.push_str(&wdf_header_contents); - } - + let header_contents = config.bindgen_header_contents([ + ApiSubset::Base, + ApiSubset::Wdf, #[cfg(feature = "hid")] - if env::var("CARGO_FEATURE_HID").is_ok() { - contents.push_str(&config.bindgen_hid_header_contents()); - }; - - contents - }; + ApiSubset::Hid, + ]); trace!(header_contents = ?header_contents); let bindgen_builder = bindgen::Builder::wdk_default(config)? @@ -282,7 +266,7 @@ fn generate_base(out_path: &Path, config: &Config) -> Result<(), ConfigError> { }; info!("Generating bindings to WDK: {outfile_name}.rs"); - let header_contents = config.bindgen_base_header_contents(); + let header_contents = config.bindgen_header_contents([ApiSubset::Base]); trace!(header_contents = ?header_contents); let bindgen_builder = bindgen::Builder::wdk_default(config)? @@ -297,14 +281,10 @@ fn generate_base(out_path: &Path, config: &Config) -> Result<(), ConfigError> { } fn generate_wdf(out_path: &Path, config: &Config) -> Result<(), ConfigError> { - if let Some(wdf_header_contents) = config.bindgen_wdf_header_contents() { + if let DriverConfig::Kmdf(_) | DriverConfig::Umdf(_) = config.driver_config { info!("Generating bindings to WDK: wdf.rs"); - let header_contents = { - let mut contents = config.bindgen_base_header_contents(); - contents.push_str(&wdf_header_contents); - contents - }; + let header_contents = config.bindgen_header_contents([ApiSubset::Base, ApiSubset::Wdf]); trace!(header_contents = ?header_contents); let bindgen_builder = bindgen::Builder::wdk_default(config)? @@ -337,19 +317,7 @@ fn generate_hid(out_path: &Path, config: &Config) -> Result<(), ConfigError> { if #[cfg(feature = "hid")] { info!("Generating bindings to WDK: hid.rs"); - let header_contents = { - let mut contents = config.bindgen_base_header_contents(); - - if let Some(wdf_header_contents) = config.bindgen_wdf_header_contents() { - contents.push_str(&wdf_header_contents); - } - - if env::var("CARGO_FEATURE_HID").is_ok() { - contents.push_str(&config.bindgen_hid_header_contents()); - }; - - contents - }; + let header_contents = config.bindgen_header_contents([ApiSubset::Base, ApiSubset::Wdf, ApiSubset::Hid]); trace!(header_contents = ?header_contents); let bindgen_builder = { @@ -358,9 +326,8 @@ fn generate_hid(out_path: &Path, config: &Config) -> Result<(), ConfigError> { .header_contents("hid-input.h", &header_contents); // Only allowlist files in the hid-specific files to avoid duplicate definitions - for header_file in config.hid_headers() + for header_file in config.headers(ApiSubset::Hid) { - builder = builder.allowlist_file(format!("(?i).*{header_file}.*")); } @@ -524,7 +491,7 @@ fn main() -> anyhow::Result<()> { } }); - if let Some(wdf_header_contents) = config.bindgen_wdf_header_contents() { + if let DriverConfig::Kmdf(_) | DriverConfig::Umdf(_) = config.driver_config { let current_span = Span::current(); let config = &config; let out_path = &out_path; @@ -545,13 +512,14 @@ fn main() -> anyhow::Result<()> { { let mut wdf_c_file = File::create(&wdf_c_file_path)?; wdf_c_file.write_all( - config.bindgen_base_header_contents().as_bytes(), - )?; - wdf_c_file.write_all(wdf_header_contents.as_bytes())?; - - #[cfg(feature = "hid")] - wdf_c_file.write_all( - config.bindgen_hid_header_contents().as_bytes(), + config + .bindgen_header_contents([ + ApiSubset::Base, + ApiSubset::Wdf, + #[cfg(feature = "hid")] + ApiSubset::Hid, + ]) + .as_bytes(), )?; // Explicitly sync_all to surface any IO errors (File::drop