Skip to content

feat: add linker directive for VHF lib + move static linker directives from wdk-build to wdk-sys - #685

Open
Alan632 wants to merge 37 commits into
microsoft:mainfrom
Alan632:vhf_lib_linker_args-v2
Open

feat: add linker directive for VHF lib + move static linker directives from wdk-build to wdk-sys#685
Alan632 wants to merge 37 commits into
microsoft:mainfrom
Alan632:vhf_lib_linker_args-v2

Conversation

@Alan632

@Alan632 Alan632 commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds conditionally compiled linker directives for the VHF library tied to the "hid" feature.

Moves build script emitted static linker directives (cargo::rustc-link-lib=static=*) from wdk-build/src/lib.rs into bindgen generated files as conditionally compiled attributes. The Rust source insertion happens in wdk-sys/build.rs while the backend logic and Rust source string build lives in wdk-build/src/lib.rs (closely following the pattern the bindgen generated headers use). This allows conditional compilation of linker directives (and eventually link args) without having to rely on cross crate feature signaling, and guards against issues from version drift (in case multiple versions of wdk-build are used in one project).

This PR is a redesign of and supersedes PR!653.

Verification

Verified both kmdf and umdf drivers built with "hid" and Vhf functions linked against VhfKm.lib and VhfUm.lib respectively. Additionally, inspected each driver's linker .map file for evidence of the respective Vhf symbols.

Bindgen generated files are also inspected post build for the presence of the link attributes.

… directives from wdk-build/src/lib.rs into wdk-sys/build.rs
Copilot AI review requested due to automatic review settings June 18, 2026 18:48
@Alan632 Alan632 self-assigned this Jun 18, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates how native WDK libraries are linked by moving static rustc-link-lib directives out of wdk-build’s configure_binary_build prints and into wdk-sys’s generated bindings via #[link(...)] attributes. It also adds conditional linker directives for the VHF library when the hid feature is enabled, selecting VhfKm vs VhfUm based on driver model.

Changes:

  • Emit base driver-model-specific native library link directives into bindgen output (ntddk.rs/windows.rs) from wdk-sys/build.rs.
  • Add hid-gated #[link] directives for VhfKm (KMDF/WDM) and VhfUm (UMDF).
  • Remove the corresponding cargo::rustc-link-lib=static=* emissions from wdk-build::Config::configure_binary_build (leaving link-arg prints in place).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
crates/wdk-sys/build.rs Adds a reusable #[link] directive helper and injects conditional link directives into generated bindings (including VHF for hid).
crates/wdk-build/src/lib.rs Stops emitting static rustc-link-lib lines (now handled by wdk-sys), retaining cdylib link-args and documenting future move.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/wdk-sys/build.rs Outdated
Comment thread crates/wdk-build/src/lib.rs Outdated
Comment thread crates/wdk-sys/build.rs Outdated
@codecov-commenter

codecov-commenter commented Jun 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.07%. Comparing base (66223e9) to head (3378625).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #685      +/-   ##
==========================================
+ Coverage   80.47%   81.07%   +0.59%     
==========================================
  Files          26       26              
  Lines        5722     5901     +179     
  Branches     5722     5901     +179     
==========================================
+ Hits         4605     4784     +179     
  Misses        989      989              
  Partials      128      128              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI review requested due to automatic review settings June 18, 2026 23:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

Comment thread crates/wdk-build/src/lib.rs Outdated
Comment thread crates/wdk-build/src/lib.rs
Comment thread crates/wdk-build/src/lib.rs
Comment thread crates/wdk-build/src/lib.rs Outdated
Comment thread crates/wdk-build/src/lib.rs Outdated
Comment thread crates/wdk-sys/build.rs Outdated
Comment thread crates/wdk-build/src/lib.rs Outdated
Comment thread crates/wdk-build/src/lib.rs Outdated
Comment thread crates/wdk-build/src/lib.rs Outdated
Alan Ngo added 2 commits June 19, 2026 11:29
…utes out when building non-driver test wdk-sys-tests (wdk-sys-tests does not call configure_binary_build thus no search paths are emitted and ungated link attributes fail the build/test)
…on, library selection, and link directive string creation)

-removed raw strings in lieu of types to tightly constrain LinkDirective creation w/o needing assert checks
-removed and compacted unneeded functions from original implementation
Copilot AI review requested due to automatic review settings June 19, 2026 23:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

… attributes to ensure wdk-sys builds correctly when compiled for test

- add unit tests
- add PartialEq and Eq traits to LinkKind, LinkModifier, and LinkDirective
@Alan632
Alan632 marked this pull request as ready for review June 23, 2026 00:45
Copilot AI review requested due to automatic review settings June 23, 2026 00:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

@leon-xd leon-xd left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work. Few changes here and there but the overall shape is very solid!

Comment thread tests/wdk-sys-tests/Cargo.toml
Comment thread crates/wdk-build/src/lib.rs Outdated
Comment thread crates/wdk-build/src/lib.rs Outdated
Comment thread crates/wdk-build/src/lib.rs Outdated
Comment thread crates/wdk-build/src/lib.rs Outdated
Comment thread crates/wdk-build/src/lib.rs Outdated
Comment thread crates/wdk-build/src/lib.rs
Comment thread crates/wdk-build/src/lib.rs Outdated
Comment thread crates/wdk-build/src/lib.rs Outdated
Comment thread tests/wdk-sys-tests/Cargo.toml
Copilot AI review requested due to automatic review settings July 2, 2026 16:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

tests/mixed-package-kmdf-workspace/crates/driver/Cargo.toml:25

  • This comment is inaccurate: gating the DriverEntry export name does not stop driver_entry from being codegen’d; it only avoids exporting/renaming the symbol for the driver entry point. The function can still be compiled, so the rationale for not needing test-stubs should be stated in terms of not requiring WDF link symbols during unit tests (or keeping tests from reaching WDF call sites).
# The feature "test-stubs" isn't needed since gating the DriverEntry export_name keeps
# driver_entry from being codegen'd, so nothing references WDF functions. Switch to "test-stubs"
# if a test ever reaches a call_unsafe_wdf_function_binding! call site.

Comment on lines +1600 to +1610
fn render(&self) -> String {
format!(
r#"#[cfg({cfg})]
#[link(name = "{name}", kind = "static", modifiers = "-bundle")]
unsafe extern "C" {{}}
"#,
cfg = NOT_TEST_CFG,
name = self.name,
)
}
}
Copilot AI review requested due to automatic review settings July 29, 2026 23:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

tests/mixed-package-kmdf-workspace/crates/driver/Cargo.toml:26

  • The dev-dependency comment is misleading: gating the DriverEntry export_name does not prevent driver_entry from being codegen’d; it only avoids exporting the symbol as DriverEntry in cargo test builds. The test-friendly behavior here mainly comes from enabling wdk-sys/no-link to suppress generated #[link] directives, plus not referencing WDF functions in tests. Consider rewriting the comment to reflect what’s actually happening so future changes don’t rely on a false assumption.
# The feature "test-stubs" isn't needed since gating the DriverEntry export_name keeps
# driver_entry from being codegen'd, so nothing references WDF functions. Switch to "test-stubs"
# if a test ever reaches a call_unsafe_wdf_function_binding! call site.
wdk-sys = { features = ["no-link"], workspace = true }

…e to `-D clippy::negative-feature-names`

- formatting test_stubs.rs doc comment
Copilot AI review requested due to automatic review settings July 29, 2026 23:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

tests/mixed-package-kmdf-workspace/crates/driver/Cargo.toml:26

  • The dev-dependency comment is misleading: gating export_name = "DriverEntry" does not prevent driver_entry from being codegen’d, and this crate still contains WDF call sites (e.g. call_unsafe_wdf_function_binding!(WdfDriverCreate, ...)) that could get pulled into the test binary depending on codegen-unit/LTO behavior. The comment should describe the real purpose (avoiding exporting DriverEntry during tests to prevent symbol conflicts) and when to switch to test-stubs.
# The feature "test-stubs" isn't needed since gating the DriverEntry export_name keeps
# driver_entry from being codegen'd, so nothing references WDF functions. Switch to "test-stubs"
# if a test ever reaches a call_unsafe_wdf_function_binding! call site.
wdk-sys = { features = ["omit-wdk-libs"], workspace = true }

Copilot AI review requested due to automatic review settings July 30, 2026 00:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (2)

tests/mixed-package-kmdf-workspace/crates/driver/Cargo.toml:25

  • The dev-dependency enables the test-stubs feature, but the accompanying comment says test-stubs “isn't needed” and suggests switching to it later. This is internally inconsistent and makes it unclear why the feature is enabled for tests.
# The feature "test-stubs" isn't needed since gating the DriverEntry export_name keeps
# driver_entry from being codegen'd, so nothing references WDF functions. Switch to "test-stubs"
# if a test ever reaches a call_unsafe_wdf_function_binding! call site.
wdk-sys = { features = ["test-stubs"], workspace = true }

tests/wdk-sys-tests/src/lib.rs:10

  • Doctests compile in a separate crate, so wdk-sys is built as a normal dependency (without cfg(test)). The current docs imply the #[link] directives are suppressed just because it’s a doctest, but in practice suppression relies on enabling omit-wdk-libs (here via the test-stubs feature).
//! The crate-level example below doubles as a doctest.
//! `cargo test` compiles and links each doctest as its own binary.
//! The generated `#[link]` directives are cfg-suppressed, so the
//! doctest links and runs without pulling libraries into it.

Comment on lines +1600 to +1609
fn render(&self) -> String {
format!(
r#"#[cfg({cfg})]
#[link(name = "{name}", kind = "static", modifiers = "-bundle")]
unsafe extern "C" {{}}
"#,
cfg = NOT_TEST_CFG,
name = self.name,
)
}
…vers in `examples/`

- add unit test place holder in sample driver crates in `examples/`
Copilot AI review requested due to automatic review settings July 30, 2026 18:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (4)

examples/sample-wdm-driver/src/lib.rs:78

  • This unit test calls driver_exit, which routes through wdk::println and ultimately wdk_sys::ntddk::DbgPrint for WDM/KMDF. With linker directives now disabled under cfg(test), this makes the example’s cargo test prone to link failures on the host. Prefer a pure Rust invariant test that only references bindgen-generated types and does not call into kernel APIs.
mod tests {

    #[test]
    fn test_driver_exit() {
        use super::*;

examples/sample-kmdf-driver/src/lib.rs:197

  • This unit test calls driver_exit, which routes through wdk::println and ultimately wdk_sys::ntddk::DbgPrint for WDM/KMDF. With linker directives now disabled under cfg(test), this makes the example’s cargo test prone to link failures on the host. Prefer a pure Rust invariant test that only references bindgen-generated types and does not call into kernel APIs.
mod tests {

    #[test]
    fn test_driver_exit() {
        use super::*;

tests/mixed-package-kmdf-workspace/crates/driver/Cargo.toml:26

  • The comment says test-stubs “isn't needed” and that gating export_name prevents driver_entry from being codegen’d, but this dependency is explicitly enabling test-stubs. Please update the comment to reflect the actual reason the feature is enabled so future maintainers don’t remove it based on incorrect assumptions.
# The feature "test-stubs" isn't needed since gating the DriverEntry export_name keeps
# driver_entry from being codegen'd, so nothing references WDF functions. Switch to "test-stubs"
# if a test ever reaches a call_unsafe_wdf_function_binding! call site.
wdk-sys = { features = ["test-stubs"], workspace = true }

examples/sample-umdf-driver/src/lib.rs:182

  • This mod tests is currently compiled into non-test builds as well. It’s better to gate it with #[cfg(test)], and keep the test itself independent of driver runtime behavior (e.g., a type-size invariant) so it can run in CI without requiring a driver environment.
mod tests {

    #[test]
    fn test_driver_exit() {
        use super::*;

Comment on lines +9 to 11
#![cfg_attr(not(test), no_std)]

extern crate alloc;
Comment on lines +9 to 11
#![cfg_attr(not(test), no_std)]

extern crate alloc;
- formatting
- enable test-stubs in sample drivers and cfg gate DriverEntry export_name
- forgot cfg(test) for tests modules
Copilot AI review requested due to automatic review settings July 30, 2026 22:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

examples/sample-wdm-driver/src/lib.rs:81

  • The unit test calls driver_exit, which uses wdk::println! (DbgPrint). In test builds wdk-sys is enabled with omit-wdk-libs via test-stubs, so the generated #[link] directives that would pull in ntoskrnl/hal are suppressed; this makes DbgPrint unresolved at link time.
    #[test]
    fn test_driver_exit() {
        use super::*;

        driver_exit(core::ptr::null_mut())

examples/sample-kmdf-driver/src/lib.rs:200

  • The unit test calls driver_exit, which uses wdk::println! (DbgPrint). With wdk-sys built for tests using omit-wdk-libs via test-stubs, the generated #[link] directives are suppressed and DbgPrint won't be linked, causing test builds to fail at link time.
    #[test]
    fn test_driver_exit() {
        use super::*;

        driver_exit(core::ptr::null_mut())

tests/mixed-package-kmdf-workspace/crates/driver/Cargo.toml:26

  • The comment says test-stubs isn't needed, but the dependency is still declared with features = ["test-stubs"]. This is misleading for future maintenance (and test-stubs now also enables omit-wdk-libs, which is likely the real reason this is enabled).
# The feature "test-stubs" isn't needed since gating the DriverEntry export_name keeps
# driver_entry from being codegen'd, so nothing references WDF functions. Switch to "test-stubs"
# if a test ever reaches a call_unsafe_wdf_function_binding! call site.
wdk-sys = { features = ["test-stubs"], workspace = true }

- change the `DRIVER_OBJECT` type to `PDRIVER_OBJECT` in driver_entry_stub
- formatting
Copilot AI review requested due to automatic review settings July 31, 2026 19:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

Suppressed comments (3)

crates/wdk-sys/src/test_stubs.rs:36

  • The module docs still say WdfDriverGlobals is intentionally not stubbed (and that missing it is expected), but the module now defines a WdfDriverGlobals stub below. This comment is now misleading for users diagnosing linker failures under test-stubs.

Update the note to reflect the current behavior (it is stubbed, but calling into real WDF APIs in tests still requires mocks).

//!   - If "test-stubs" is enabled the Linker may complain that
//!     `WdfDriverGlobals` is missing, it is intentionally not stubbed here
//!     because it is needed when a WDF function is called, landing it outside
//!     the intent of test-stubs.

crates/wdk-sys/src/test_stubs.rs:84

  • There is trailing whitespace in the doc comment line (/// ) which can cause formatting/style checks to fail and is also inconsistent with the surrounding doc comment style. Prefer an empty doc line written as ///.
    /// Stubbed version of `WdfDriverGlobals` Symbol so that test targets will
    /// link.
    /// 

tests/mixed-package-kmdf-workspace/crates/driver/Cargo.toml:25

  • This comment contradicts the dependency configuration and is also technically inaccurate: gating only the export_name attribute does not prevent driver_entry from being codegen'd, and test-stubs is enabled unconditionally right below.

Please update the comment to reflect why test-stubs is enabled for dev/test builds (e.g., suppress generated #[link] directives via omit-wdk-libs and provide stubbed driver/WDF globals for linking).

# The feature "test-stubs" isn't needed since gating the DriverEntry export_name keeps
# driver_entry from being codegen'd, so nothing references WDF functions. Switch to "test-stubs"
# if a test ever reaches a call_unsafe_wdf_function_binding! call site.

Copilot AI review requested due to automatic review settings July 31, 2026 19:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

Suppressed comments (4)

examples/sample-wdm-driver/src/lib.rs:82

  • The new unit test calls driver_exit(), which uses wdk::println!. In WDM/KMDF, that routes through wdk_sys::ntddk::DbgPrint, but this PR also cfg-suppresses the #[link] directives during tests (cfg(test) / omit-wdk-libs). That combination is likely to produce an unresolved external for DbgPrint when running cargo test on this example. Prefer a test that only references bindgen types/consts (compile+link proof) without calling into WDK APIs.
    fn test_driver_exit() {
        use super::*;

        driver_exit(core::ptr::null_mut())
    }

examples/sample-kmdf-driver/src/lib.rs:195

  • The new unit test calls driver_exit(), which uses wdk::println! and will ultimately reference WDK symbols (e.g., DbgPrint) that are no longer linked in test builds due to cfg-suppressed #[link] directives. This is likely to break cargo test for this example. Consider switching the test to a pure type/const assertion that still proves the cdylib can host tests without requiring WDK libs.
    #[test]
    fn test_driver_exit() {
        use super::*;

        driver_exit(core::ptr::null_mut())

crates/wdk-sys/src/test_stubs.rs:36

  • The module docs still say WdfDriverGlobals is intentionally not stubbed and that enabling test-stubs may fail to link because it’s missing, but this file now defines a WdfDriverGlobals stub. Update the docs to reflect the current behavior and clarify that calling real WDF APIs is still unsupported under stubs.
//!   - If "test-stubs" is enabled the Linker may complain that
//!     `WdfDriverGlobals` is missing, it is intentionally not stubbed here
//!     because it is needed when a WDF function is called, landing it outside
//!     the intent of test-stubs.

tests/mixed-package-kmdf-workspace/crates/driver/Cargo.toml:26

  • This comment contradicts the dependency directly below it: it says the "test-stubs" feature isn’t needed and should be switched on later, but the dev-dependency already enables it. Please update/remove the comment so it matches the actual configuration and intent for tests.
# The feature "test-stubs" isn't needed since gating the DriverEntry export_name keeps
# driver_entry from being codegen'd, so nothing references WDF functions. Switch to "test-stubs"
# if a test ever reaches a call_unsafe_wdf_function_binding! call site.
wdk-sys = { features = ["test-stubs"], workspace = true }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants