Skip to content

fix: prevent RUSTFLAGS from leaking into downstream cargo-make rust-script builds#629

Draft
wmmc88 wants to merge 2 commits intomicrosoft:mainfrom
wmmc88:fix/cargo-make-rustflags-leak
Draft

fix: prevent RUSTFLAGS from leaking into downstream cargo-make rust-script builds#629
wmmc88 wants to merge 2 commits intomicrosoft:mainfrom
wmmc88:fix/cargo-make-rustflags-leak

Conversation

@wmmc88
Copy link
Copy Markdown
Collaborator

@wmmc88 wmmc88 commented Mar 7, 2026

Problem

When downstream consumers of wdk-build (e.g. microsoft/Windows-rust-driver-samples) run cargo make, RUSTFLAGS=-D warnings leaks into rust-script compilation of the inline build scripts. This causes warnings in the published wdk-build crate to become hard errors, breaking downstream CI.

Example failure (from Windows-rust-driver-samples Build CI):

error: the feature `assert_matches` has been stable since 1.95.0-nightly
  --> wdk-build-0.5.1/src/lib.rs:13:40
   = note: `-D stable-features` implied by `-D warnings`

Root Cause

The rust-script tasks in rust-driver-makefile.toml specify wdk-build = { path = ".", version = "0.5.1" }. Cargo always uses path when both are specified, ignoring version. When load_rust_driver_makefile() symlinks the makefile from the registry cache, path = "." resolves to the registry source via --base-path, making wdk-build a path dependency. Cargo does not apply --cap-lints allow to path dependencies, so RUSTFLAGS=-D warnings applies directly to the published crate.

Normal cargo build is unaffected because wdk-build is resolved as a registry dependency there.

Fix

  1. load_wdk_build_makefile() now checks package.source from cargo_metadata:

    • Registry dep (source.is_some()): Copies the makefile and rewrites wdk-build = { path = "." } to wdk-build = "X.Y.Z" (version from metadata). This ensures cargo treats it as a registry dep and applies --cap-lints allow.
    • Path/workspace dep (source.is_none()): Preserves existing symlink behavior so local development works correctly.
  2. Removed unused version field from all 14 rust-script dep specs in rust-driver-makefile.toml and rust-driver-sample-makefile.toml, since path always takes precedence. Added a comment explaining the automatic rewrite by load_rust_driver_makefile().

Scenarios

Scenario package.source Behavior
Upstream WDR dev N/A (uses extend, not load_*) Unchanged
Downstream registry dep Some(registry+...) Copy + rewrite -> registry dep -> --cap-lints
Downstream path dep None Symlink preserved -> path dep (intentional)

Copilot AI review requested due to automatic review settings March 7, 2026 22:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 prevents downstream cargo make consumers of wdk-build from inheriting caller RUSTFLAGS (e.g. -D warnings) into rust-script compilation of embedded scripts by ensuring wdk-build is treated as a non-path dependency when loaded from the registry.

Changes:

  • Update load_wdk_build_makefile() to copy+rewrite embedded rust-script manifests from wdk-build = { path = "." } to wdk-build = "X.Y.Z" when wdk-build is resolved from a non-path source.
  • Preserve existing symlink behavior when wdk-build is a workspace/path dependency to keep local dev flows intact.
  • Remove redundant version = "...“ fields from rust-script embedded dependency specs and add an explanatory note in the main makefile.

Reviewed changes

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

File Description
crates/wdk-build/src/cargo_make.rs Implements registry-vs-path behavior (copy+rewrite vs symlink) when materializing makefiles into target/.
crates/wdk-build/rust-driver-makefile.toml Removes redundant embedded dependency versions and documents the downstream rewrite behavior.
crates/wdk-build/rust-driver-sample-makefile.toml Removes redundant embedded dependency versions from sample tasks.
Comments suppressed due to low confidence (2)

crates/wdk-build/src/cargo_make.rs:934

  • The rewrite uses a simple replace without validating that any occurrences were actually patched. If the makefile format changes (spacing/comments/features), this will silently leave the path = "." dependency intact and the original lint-leak issue will persist. Consider checking whether patched_content differs from makefile_content and returning a ConfigError (or at least logging) when no replacement occurred.
        let version = &wdk_build_package.version;
        let patched_content = makefile_content.replace(
            r#"wdk-build = { path = "." }"#,
            &format!("wdk-build = \"{version}\""),
        );

crates/wdk-build/src/cargo_make.rs:927

  • load_wdk_build_makefile now sometimes writes a patched copy into target/ instead of always creating/updating a symlink. The rustdoc/comments above this function (and the public load_*_makefile wrappers) still describe the behavior as always symlinking; they should be updated to reflect the new copy+rewrite path for registry dependencies.
    if wdk_build_package.source.is_some() {
        // wdk-build is a registry (or git) dependency. Rewrite path dependencies in
        // the makefile's rust-script embedded manifests to version-only dependencies so
        // that cargo treats wdk-build as a registry dep and applies --cap-lints. This
        // prevents the caller's RUSTFLAGS (e.g. -D warnings) from leaking into the
        // published wdk-build crate's compilation.
        let makefile_content = std::fs::read_to_string(&rust_driver_makefile_toml_path)

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

Comment on lines +921 to +954
if wdk_build_package.source.is_some() {
// wdk-build is a registry (or git) dependency. Rewrite path dependencies in
// the makefile's rust-script embedded manifests to version-only dependencies so
// that cargo treats wdk-build as a registry dep and applies --cap-lints. This
// prevents the caller's RUSTFLAGS (e.g. -D warnings) from leaking into the
// published wdk-build crate's compilation.
let makefile_content = std::fs::read_to_string(&rust_driver_makefile_toml_path)
.map_err(|source| IoError::with_path(&rust_driver_makefile_toml_path, source))?;

let version = &wdk_build_package.version;
let patched_content = makefile_content.replace(
r#"wdk-build = { path = "." }"#,
&format!("wdk-build = \"{version}\""),
);

// Only write if content changed or file doesn't exist, to avoid unnecessary
// rebuilds from rust-script cache invalidation
let should_write = if destination_path.exists() {
let existing_content = std::fs::read_to_string(&destination_path)
.map_err(|source| IoError::with_path(&destination_path, source))?;
existing_content != patched_content
} else {
true
};

if should_write {
if destination_path.exists() {
std::fs::remove_file(&destination_path)
.map_err(|source| IoError::with_path(&destination_path, source))?;
}
std::fs::write(&destination_path, patched_content)
.map_err(|source| IoError::with_path(&destination_path, source))?;
}
} else {
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

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

This change introduces new behavior (copying and patching the makefile based on cargo_metadata source) but there are no tests covering the rewrite decision or the resulting file content. Since this module already has unit tests, consider adding tests (e.g., using temp dirs + a small fixture makefile, and injecting/stubbing metadata) to lock in registry-vs-path behavior and ensure the wdk-build dep is rewritten as intended.

This issue also appears on line 930 of the same file.

Copilot uses AI. Check for mistakes.
Comment on lines +921 to +934
if wdk_build_package.source.is_some() {
// wdk-build is a registry (or git) dependency. Rewrite path dependencies in
// the makefile's rust-script embedded manifests to version-only dependencies so
// that cargo treats wdk-build as a registry dep and applies --cap-lints. This
// prevents the caller's RUSTFLAGS (e.g. -D warnings) from leaking into the
// published wdk-build crate's compilation.
let makefile_content = std::fs::read_to_string(&rust_driver_makefile_toml_path)
.map_err(|source| IoError::with_path(&rust_driver_makefile_toml_path, source))?;

let version = &wdk_build_package.version;
let patched_content = makefile_content.replace(
r#"wdk-build = { path = "." }"#,
&format!("wdk-build = \"{version}\""),
);
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

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

wdk_build_package.source.is_some() groups registry and git dependencies together, but rewriting to wdk-build = "{version}" will break consumers using a git dependency (Cargo will try to resolve that version from the registry). Consider detecting source kind (e.g., registry+... vs git+...) and only performing the version-only rewrite for registry sources; for git sources, either preserve the symlink behavior or rewrite to a git dependency in the embedded manifests.

This issue also appears on line 921 of the same file.

Copilot uses AI. Check for mistakes.
Comment on lines +126 to +129
//! # `load_rust_driver_makefile()`, this path dependency is automatically
//! # rewritten to a version-only registry dependency. This ensures cargo
//! # applies `--cap-lints allow` to wdk-build, preventing the caller's
//! # RUSTFLAGS from leaking into the published crate's compilation.
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

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

The NOTE says the path = "." dependency is rewritten when loaded by downstream consumers, but the implementation only rewrites when wdk-build is resolved from a non-path source (registry/git). Downstream users can also depend on wdk-build via a local path, in which case the rewrite intentionally does not happen. Consider clarifying the note to mention it only applies when wdk-build is a registry dependency.

Suggested change
//! # `load_rust_driver_makefile()`, this path dependency is automatically
//! # rewritten to a version-only registry dependency. This ensures cargo
//! # applies `--cap-lints allow` to wdk-build, preventing the caller's
//! # RUSTFLAGS from leaking into the published crate's compilation.
//! # `load_rust_driver_makefile()`, and `wdk-build` is resolved from a
//! # non-path source (e.g., registry or git), this path dependency is
//! # automatically rewritten to a version-only registry dependency. This
//! # ensures cargo applies `--cap-lints allow` to wdk-build, preventing the
//! # caller's RUSTFLAGS from leaking into the published crate's compilation.

Copilot uses AI. Check for mistakes.
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 7, 2026

Codecov Report

❌ Patch coverage is 93.21429% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.63%. Comparing base (666875a) to head (bcdf058).

Files with missing lines Patch % Lines
crates/wdk-build/src/cargo_make.rs 93.21% 19 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #629      +/-   ##
==========================================
+ Coverage   77.42%   78.63%   +1.21%     
==========================================
  Files          24       24              
  Lines        4851     5117     +266     
  Branches     4851     5117     +266     
==========================================
+ Hits         3756     4024     +268     
+ Misses        978      976       -2     
  Partials      117      117              

☔ View full report in Codecov by Sentry.
📢 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.

@wmmc88 wmmc88 marked this pull request as draft March 8, 2026 00:26
@wmmc88 wmmc88 force-pushed the fix/cargo-make-rustflags-leak branch from 4df0dc5 to 9a89265 Compare March 8, 2026 00:33
wmmc88 added a commit to wmmc88/Windows-rust-driver-samples that referenced this pull request Mar 8, 2026
…t builds

Unset RUSTFLAGS for cargo-make and cargo-wdk steps in build.yaml to prevent
-D warnings from leaking into rust-script compilation of wdk-build.

This is a temporary workaround. The proper fix is in
microsoft/windows-drivers-rs#629 which rewrites path deps to version-only
deps in load_wdk_build_makefile() for registry consumers.

Root cause: wdk-build = { path = '.' } in rust-driver-makefile.toml makes
wdk-build a path dependency even when loaded from the registry cache via
symlink. Cargo does not apply --cap-lints allow to path deps, so RUSTFLAGS
leaks through.

Tracked in ADO Bug #5396440.
@wmmc88 wmmc88 force-pushed the fix/cargo-make-rustflags-leak branch from 9a89265 to 3522897 Compare March 8, 2026 00:56
Copilot AI review requested due to automatic review settings March 8, 2026 00:56
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 2 comments.


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

let version = &wdk_build_package.version;
let patched_content = makefile_content.replace(
r#"wdk-build = { path = "." }"#,
&format!("wdk-build = \"{version}\""),
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

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

The rewritten dependency uses wdk-build = "{version}", which is a caret requirement and may allow rust-script to resolve a newer compatible 0.5.x than the wdk-build version that provided this makefile. To keep the embedded scripts and the loaded makefile in lockstep (and make downstream behavior deterministic/offline-friendly), consider rewriting to an exact requirement like wdk-build = "={version}" instead.

Suggested change
&format!("wdk-build = \"{version}\""),
&format!("wdk-build = \"={version}\""),

Copilot uses AI. Check for mistakes.
Comment on lines +929 to +974
let is_registry_source = wdk_build_package
.source
.as_ref()
.is_some_and(|s| s.repr.starts_with("registry+") || s.repr.starts_with("sparse+"));

if is_registry_source {
// wdk-build is a registry dependency. Rewrite path dependencies in the
// makefile's rust-script embedded manifests to version-only dependencies
// so that cargo treats wdk-build as a registry dep and applies
// --cap-lints. This prevents the caller's RUSTFLAGS (e.g. -D warnings)
// from leaking into the published wdk-build crate's compilation.
let makefile_content = std::fs::read_to_string(&rust_driver_makefile_toml_path)
.map_err(|source| IoError::with_path(&rust_driver_makefile_toml_path, source))?;

let version = &wdk_build_package.version;
let patched_content = makefile_content.replace(
r#"wdk-build = { path = "." }"#,
&format!("wdk-build = \"{version}\""),
);

if patched_content == makefile_content {
warn!(
"No wdk-build path dependency found to rewrite in {makefile_name:?}. The makefile \
format may have changed."
);
}

// Only write if content changed or file doesn't exist, to avoid
// unnecessary rebuilds from rust-script cache invalidation
let should_write = if destination_path.exists() {
let existing_content = std::fs::read_to_string(&destination_path)
.map_err(|source| IoError::with_path(&destination_path, source))?;
existing_content != patched_content
} else {
true
};

if should_write {
if destination_path.exists() {
std::fs::remove_file(&destination_path)
.map_err(|source| IoError::with_path(&destination_path, source))?;
}
std::fs::write(&destination_path, patched_content)
.map_err(|source| IoError::with_path(&destination_path, source))?;
}
} else {
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

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

This new registry-vs-non-registry behavior (copy+rewrite vs symlink) is not covered by tests, but this module already has unit tests for other helpers. Consider extracting the rewrite decision/content patching into a small pure helper and adding tests that (a) registry sources produce rewritten content and (b) non-registry sources preserve the symlink/update behavior.

Copilot uses AI. Check for mistakes.
@wmmc88 wmmc88 force-pushed the fix/cargo-make-rustflags-leak branch from 3522897 to a28a18b Compare March 8, 2026 01:18
wmmc88 added a commit to wmmc88/Windows-rust-driver-samples that referenced this pull request Mar 8, 2026
…t builds

Unset RUSTFLAGS for cargo-make and cargo-wdk steps in build.yaml to prevent
-D warnings from leaking into rust-script compilation of wdk-build.

Temporary workaround until microsoft/windows-drivers-rs#629 is merged and
a new wdk-build is published.

Tracked in ADO Bug #5396440.
wmmc88 added a commit to wmmc88/Windows-rust-driver-samples that referenced this pull request Mar 9, 2026
Unset RUSTFLAGS for the cargo-make step in build.yaml to prevent -D warnings
from leaking into rust-script compilation of wdk-build. Only cargo-make is
affected since it uses rust-script to compile inline build scripts where
wdk-build is a path dependency (via symlink), bypassing cargo's --cap-lints.
cargo-wdk and cargo install are normal cargo operations with proper
--cap-lints handling and do not need this workaround.

Temporary workaround until microsoft/windows-drivers-rs#629 is merged and
a new wdk-build is published.

Tracked in ADO Bug #5396440.
wmmc88 added a commit to microsoft/Windows-rust-driver-samples that referenced this pull request Mar 21, 2026
## Changes

### 1. Fix nightly clippy + rustfmt failures

Edits to pass new nightly `clippy::unnecessary_trailing_comma`
[lint](https://rust-lang.github.io/rust-clippy/master/index.html?search=clippy%3A%3Aunnecessary_trailing_comma#unnecessary_trailing_comma)
and nightly rustfmt import reordering.

- Remove 4 unnecessary trailing commas in `format!`/`println!` macros
(`general/echo/kmdf/exe/src/main.rs`)
- Reorder underscore-prefixed imports to match nightly rustfmt sorting
(`device.rs`, `queue.rs`, `driver.rs`)

**Failed CI run:**
https://github.com/microsoft/Windows-rust-driver-samples/actions/runs/22519532366

### 2. Workaround RUSTFLAGS leaking into cargo-make/cargo-wdk builds

Unset `RUSTFLAGS` for `cargo make`, `cargo wdk install`, and `cargo wdk
build` steps in `build.yaml`. This prevents `-D warnings` from leaking
into `rust-script` compilation of `wdk-build` (which is treated as a
path dependency via symlink, bypassing cargo's `--cap-lints allow`).

Temporary workaround until microsoft/windows-drivers-rs#629 is merged
and a new `wdk-build` is published.
wmmc88 added 2 commits March 27, 2026 16:45
…cript builds

When downstream consumers (e.g. Windows-rust-driver-samples) run cargo make,
RUSTFLAGS=-D warnings leaks into rust-script compilation of wdk-build because
the makefile dep specs use path = '.' which makes wdk-build a path dependency.
Cargo does not apply --cap-lints to path dependencies, so -D warnings applies
directly to the published crate, causing upstream lint issues to break
downstream builds.

Fix: load_wdk_build_makefile() now detects whether wdk-build is a registry
dependency (via package.source from cargo_metadata). When it is, the makefile
is copied with path deps rewritten to version-only deps, ensuring cargo
applies --cap-lints allow. When wdk-build is a local path dep, the existing
symlink behavior is preserved.

Also removes the unused version field from all 14 rust-script dep specs in
the makefiles, since path always takes precedence when both are specified.
Copilot AI review requested due to automatic review settings March 27, 2026 23:45
@wmmc88 wmmc88 force-pushed the fix/cargo-make-rustflags-leak branch from a28a18b to bcdf058 Compare March 27, 2026 23:45
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 2 comments.


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

Comment on lines +885 to +890
/// The version of `wdk-build` from which the file comes is determined by the
/// working directory of the process that invokes this function. For example,
/// if this function is ultimately executing in a `cargo_make` `load_script`,
/// the files will come from the `wdk-build` version that is in the
/// `Cargo.lock` file, and not the `wdk-build` version specified in the
/// `load_script`.
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

The updated doc comment explains the new copy+rewrite behavior, but the # Errors list for this function (below) still describes only symlink-related IO errors and doesn’t mention that NoWdkBuildCrateDetected can be returned. Please align the error docs with the current behavior (read/write/symlink + missing wdk-build).

Copilot uses AI. Check for mistakes.
Comment on lines +934 to 938
let wdk_build_package = &wdk_build_package_matches[0];

let rust_driver_makefile_toml_path = wdk_build_package
.manifest_path
.parent()
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

rust_driver_makefile_toml_path is used for both rust-driver and rust-driver-sample makefiles (it’s derived from the generic makefile_name). Renaming it to something neutral like makefile_path/source_makefile_path would avoid confusion as this function grows.

Copilot uses AI. Check for mistakes.
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.

3 participants