feat: add cargo wdk clean command#638
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new cargo wdk clean subcommand to cargo-wdk, with logic mirroring the existing “standalone/workspace vs emulated workspace” detection approach used by the build flow.
Changes:
- Introduces
CleanAction(plus error types and unit tests) that runscargo cleaneither in the current workspace root or across immediate subdirectories (emulated workspace). - Wires the new action into the CLI as a
cleansubcommand. - Adds integration tests for
cargo wdk clean, and updates test utilities to allow invoking the new command.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/cargo-wdk/src/cli.rs | Adds clean subcommand and dispatches into CleanAction. |
| crates/cargo-wdk/src/actions/mod.rs | Exposes the new clean action module. |
| crates/cargo-wdk/src/actions/clean/mod.rs | Implements clean logic (workspace vs emulated workspace) and runs cargo clean. |
| crates/cargo-wdk/src/actions/clean/error.rs | Defines CleanActionError error types for clean flow. |
| crates/cargo-wdk/src/actions/clean/tests.rs | Adds unit tests for CleanAction. |
| crates/cargo-wdk/tests/clean_command_test.rs | Adds integration tests for cargo wdk clean. |
| crates/cargo-wdk/tests/test_utils/mod.rs | Allows create_cargo_wdk_cmd to invoke clean. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #638 +/- ##
==========================================
+ Coverage 78.69% 79.45% +0.75%
==========================================
Files 25 26 +1
Lines 5234 5500 +266
Branches 5234 5500 +266
==========================================
+ Hits 4119 4370 +251
- Misses 995 1001 +6
- Partials 120 129 +9 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ll in clean action tests
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <copilot@github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…icrosoft#641) This pull request updates the documentation to inform users about a new build tool in development for Rust drivers. The most important change is the addition of a preview notice about the upcoming `cargo-wdk` tool. Documentation update: * Added a preview notice in `README.md` announcing the development of the `cargo-wdk` cargo-extension, which is intended to replace `cargo-make` as the recommended tool for building Rust drivers, and encouraged users to try it out and provide feedback. --------- Signed-off-by: Krishna Kumar Thokala <krishna.thokala2010@gmail.com> Co-authored-by: Gurinder Singh <frederick.the.fool@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…bilization (microsoft#643) Fixes `collapsable_if` lint failing in CI pipelines. The `assert_matches` stabilization that was expected to ship with Rust 1.95.0 was [reverted from the 1.95 beta](rust-lang/rust#154999) due to an [inconsistency in temporary scoping behavior](rust-lang/rust#154406) between `assert_matches!`/`assert_eq!` and their `debug_` variants. We gated `assert_matches` usage based on the nightly compiler warning that the feature was "stable since 1.95.0" (see microsoft#612). Since the stabilization was reverted before the actual release, this gate now fires on stable 1.95 and tries to use an unstable API, breaking CI pipelines. This bumps the gate to `1.96.0`. Beta 1.96 currently still has `assert_matches` available, though that may change if the destabilization propagates. --------- Co-authored-by: leon-xd <leondu@microsoft.com>
Adds and integrates `wdk::fmt::FormatBuffer`. ## Summary - Introduced `crates/wdk/src/fmt.rs` with a public `wdk::fmt` module containing two types: - `FormatBuffer<N>` — a fixed-size, stack-allocated formatting buffer implementing `fmt::Write` - `FlushableFormatBuffer<F, N>` — a wrapper that auto-flushes via closure on overflow and on drop - Swapped `print.rs` WDM/KMDF path to use `FlushableFormatBuffer` instead of `DbgPrintBufWriter`; removed that module and its tests. - Turns the `alloc` feature from the `wdk` crate into a no-op — it had no remaining uses after the stack-buffer migration. Avoids removal of feature to prevent a breaking change - Bumps MSRV from 1.85 to 1.91 due to use of [`str::char_floor_boundary`](https://doc.rust-lang.org/core/primitive.str.html#method.floor_char_boundary) ## Details - `FormatBuffer<N>` stores a zero-initialized `[u8; N]` and tracks `used` bytes. The last byte is reserved for a NUL terminator, so usable capacity is `N - 1`. `N` must be at least 2; smaller values will not compile (`const { assert!(N >= 2) }`). - All buffer mutations go through a single `append_bytes` helper that copies data and sets `buffer[used] = 0`, centralizing the NUL terminator invariant. - `as_str()` returns an infallible UTF-8 view — only valid UTF-8 enters via `write_str` (both `FormatBuffer::write_str` and `FlushableFormatBuffer::write_str` copy from `&str` sources). - `as_c_str()` returns a `&CStr` view up to the first NUL. Infallible in practice since the NUL invariant is always maintained. - `fmt::Write` clamps overflow writes at a UTF-8 char boundary via `floor_char_boundary` and signals truncation via `fmt::Error`. - `FlushableFormatBuffer<F, N>` wraps `FormatBuffer` and auto-flushes via a closure when the buffer fills. Remaining content is flushed on drop. This allows arbitrarily long formatted output to be processed in fixed-size chunks. - `print.rs` WDM/KMDF path now formats into `FlushableFormatBuffer<_, 512>` and calls `DbgPrint` via `%s` using the resulting `CStr`. - Removed the `alloc` feature gate from the WDM/KMDF print path — `print!`/`println!` no longer require heap allocation and work at any IRQL where `DbgPrint` is valid. - Custom `Debug` impl on `FormatBuffer` shows only the used content, not stale bytes after `clear()`. ## Testing 29 tests covering: - basic write, `as_str()`, `as_c_str()` usage - overflow, multi-write, and exact-fit scenarios - empty writes and min-sized buffers (`N = 2`) - clear-then-shorter-write regression (NUL terminator correctness) - multi-byte UTF-8 char boundary handling in both buffer types - explicit `flush()` mid-stream and flush-on-drop - interior NUL truncation via `as_c_str()` - `compile_fail` doctest for `N < 2` ```pwsh cargo test --package wdk --lib --all-features -- fmt --nocapture ``` ## Notes / Follow-ups - `_print` ignores `fmt::write` errors — partial output is acceptable for debug printing. Errors from individual `Display` impls are silently dropped. - The old `DbgPrintBufWriter` stripped interior NUL bytes and continued printing. The new WDM/KMDF path truncates each chunk at the first NUL (via `as_c_str`). UMDF still strips NULs and prints the remainder. --------- Signed-off-by: Leon Durrenberger <leon.durrenberger@gmail.com> Co-authored-by: leon-xd <leondu@microsoft.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
… build command to render compiler errors instead of the plain `json` option (microsoft#645) Fixes microsoft#613 ## Problem When `cargo wdk build` encounters a compilation error, the error output is hard to debug: 1. JSON wall — `--message-format=json` sends even the compiler diagnostics as JSON to `stdout` instead of redirecting it to `stderr`. So, compiler errors are not directly visible instead they are buried deep in the output json. This is affecting test outputs because in case of failures, the errors cannot be seen easily in the `json` output. 2. Redundant error content — `BuildTaskError::CargoBuild` wraps the full `CommandError` (containing `stdout` JSON), even though the user may have already seen the real compiler errors on `stderr` in real time. ## Fixes The following changes fix the above problems: 1. Switch to `--message-format=json-render-diagnostics` This option instructs cargo to render diagnostics from `rustc` directly to `stderr` instead of putting it in the `json` output. stdout: only machine-parseable JSON (artifacts, build-finished) — no diagnostic messages stderr: human-readable compiler errors and warnings, rendered by Cargo (visible to the user in real time since stderr is inherited) 2. Omit `stdout` from `CommandError::CommandFailed` before returning from `BuildTask`: When cargo build fails, `BuildTask::run()` now maps the error to a new instance of `CommandFailed` but with the `stdout` field set to `String::new()` to avoid printing machine-readable (`json`) output on the screen. ## Before Running `kmdf_driver_cross_compiles_with_cli_option_successfully` test after removing `aarch64-pc-windows-msvc` target: <img width="947" height="572" alt="image" src="https://github.com/user-attachments/assets/efb391d3-02e8-47fd-907e-91ffe5c1d4ba" /> _____ Compiler diagnostics not printed to `stderr`, instead it is buried in the json output when `cargo wdk build` fails: <img width="1547" height="822" alt="image" src="https://github.com/user-attachments/assets/4a0cf5c0-a9d4-4a8c-be63-c1237d6ed835" /> _____ Output seen when tests fail due to compilation errors: <img width="1936" height="1162" alt="image" src="https://github.com/user-attachments/assets/ac4a5e53-5a95-483d-898c-0e751e790c36" /> ## After Running `kmdf_driver_cross_compiles_with_cli_option_successfully` test after removing `aarch64-pc-windows-msvc` target: <img width="1344" height="824" alt="image" src="https://github.com/user-attachments/assets/f95f94a9-9076-46e3-a706-c07c7ca95b65" /> _____ Compiler diagnostics available on terminal: <img width="1028" height="576" alt="image" src="https://github.com/user-attachments/assets/39d6ba3f-5b6f-4fdb-bbb9-0b39c21874be" /> _____ Output seen when tests fail due to compilation errors: <img width="1867" height="1231" alt="image" src="https://github.com/user-attachments/assets/b282efcd-c748-4129-b2c1-4f5c6b297900" /> --------- Co-authored-by: Copilot <copilot@github.com>
### Summary This PR fixes three clippy lint failures in wdk-build that were [blocking CI](https://github.com/microsoft/windows-drivers-rs/actions/runs/25316776664/job/74241285479): 1. `useless_borrows_in_formatting` — removed redundant `&` from `panic!` arguments in `cargo_make.rs`. 2. `uninlined_format_args` — inlined the constant names directly into the `panic!` format strings. 3. `manual_assert_eq` — replaced `assert!(a == b)` with `assert_eq!(a, b)` in `utils.rs`. No functional changes; lint fixes only. ### Validation `cargo make wdk-pre-commit-flow` passes locally with the following `rustc` versions: 1. Stable - `rustc 1.95.0 (59807616e 2026-04-14)` 2. Nightly - `rustc 1.97.0-nightly (cb40c25f6 2026-05-04)` 3. Beta - `rustc 1.96.0-beta.5 (a5a9a5438 2026-05-01)` This PR fixes the issue. Co-authored-by: Copilot <copilot@github.com>
…tead of `ReadDirError` Co-authored-by: Copilot <copilot@github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| #[error("Failed to rename file from {0} to {1}")] | ||
| RenameError(PathBuf, PathBuf, #[source] io::Error), | ||
| #[error("Failed to get file type for directory entry {0:#?}")] | ||
| #[error("Failed to get file type for directory entry {0}")] |
There was a problem hiding this comment.
While adding this variant back, I noticed it was using {0:#?} whereas every other FileError variant uses plain {0}. Switched it to {0} so the PathBuf is rendered via Display instead of Debug to keep it consistent with the rest of the enum
| .unwrap_or_default(); | ||
|
|
||
| if !found_at_least_one_project { | ||
| info!("Cleaning package(s) in {}", self.working_dir.display()); |
There was a problem hiding this comment.
Nit: to make it more readable, Add a comment on top of this to clarify that this conditional is required to have one log per entire emulated workspace. it threw me off a bit if I didn't pay close attention to the argument being logged.
There was a problem hiding this comment.
Added a comment 👍
| continue; | ||
| } | ||
|
|
||
| let working_dir_path = entry.path; |
There was a problem hiding this comment.
Please change this variable name, as the working_dir variable is already used to refer to the emulated workspace itself. A better name would be cargo_package_path or rust_package_path.
More generally, we may need to standardise the terminology and refer to these as Cargo projects rather than Rust projects, since we depend on Cargo.toml. I originally introduced the term Rust projects in the build flow, assuming this tool would majorly be used by first‑time Rust adopters for driver development. On reflection, however, Cargo project is the more technically accurate term.
There was a problem hiding this comment.
"Package" is a cargo concept not a rustc one so cargo_package_path is better.
There was a problem hiding this comment.
I renamed it to cargo_package_path 👍
| } | ||
|
|
||
| let working_dir_path = dir.path(); // Avoids a short-lived temporary | ||
| let working_dir_path = entry.path; |
There was a problem hiding this comment.
This comment even applies here as we are not really switching into the directory during this loop.
https://github.com/microsoft/windows-drivers-rs/pull/638/changes#r3199700749
There was a problem hiding this comment.
Renamed to cargo_package_path 👍
Adds
cleansubcommand tocargo-wdk. The command can be used to remove artifacts produced by thebuildcommand.Closes #636
Behavior:
The command works for standalone, workspaces and emulated workspaces (with a known issue).
Standalone packages / workspace: If a
Cargo.toml(manifest) is present, runscargo cleandirectly. This cleans standalone packages and workspaces (excluding the directories that are mentioned in theexcludelist in workspace manifest)Emulated workspace: If
Cargo.tomlis not found in the current working directory, it Scans immediate subdirectories for Rust projects and cleans each one. Continues on failure and reports all errors at the end.Known Issue: Due to the current emulated workspaces detection logic, the clean command also suffers from the same issue as #477.
Summary of changes:
CleanActionadded with error types and testscleansubcommandbuild_command_test.rsthat tests the behavior for standalone packages, workspaces and emulated workspaces. Replaced vanillacargo cleanwithcargo wdk cleancargo wdk cleanin/examples:cargo wdk cleanin the samples repo:cleanandbuildcommands suffer with the sample problem in nested folders inside a workspace: