Skip to content

Commit

Permalink
refactor implementation so that apis are always available to `wdk_bui…
Browse files Browse the repository at this point in the history
…ld::Config`
  • Loading branch information
wmmc88 committed Jan 16, 2025
1 parent 9909386 commit 38d4b5f
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 125 deletions.
5 changes: 0 additions & 5 deletions crates/wdk-build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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)"]
Expand Down
126 changes: 64 additions & 62 deletions crates/wdk-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -629,53 +636,70 @@ impl Config {
.map(std::string::ToString::to_string)
}

pub fn base_headers(&self) -> impl Iterator<Item = String> {
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<Item = String> {
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<Item = String> {
["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<Item = String> {
// 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<Item = ApiSubset>,
) -> 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
Expand Down Expand Up @@ -729,32 +753,10 @@ typedef union _KIDTENTRY64
unsigned __int64 Alignment;
} KIDTENTRY64, *PKIDTENTRY64;
",
);
}

header_contents
}

pub fn bindgen_wdf_header_contents(&self) -> Option<String> {
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
Expand Down
2 changes: 1 addition & 1 deletion crates/wdk-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ wdk-macros.workspace = true
[features]
default = []

hid = ["wdk-build/hid"]
hid = []

nightly = ["wdk-macros/nightly"]
test-stubs = []
Expand Down
82 changes: 25 additions & 57 deletions crates/wdk-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use tracing_subscriber::{
};
use wdk_build::{
configure_wdk_library_build_and_then,
ApiSubset,
BuilderExt,
Config,
ConfigError,
Expand Down Expand Up @@ -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)?
Expand All @@ -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)?
Expand All @@ -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)?
Expand All @@ -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)?
Expand Down Expand Up @@ -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 = {
Expand All @@ -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}.*"));
}

Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down

0 comments on commit 38d4b5f

Please sign in to comment.