Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add driver-install packaging metadata + support for INF only drivers #246

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ exclude = [
"examples/sample-kmdf-driver",
"examples/sample-umdf-driver",
"examples/sample-wdm-driver",
"examples/sample-null-driver",
"tests/config-kmdf",
"tests/config-umdf",
"tests/config-wdm",
Expand Down Expand Up @@ -58,6 +59,7 @@ thiserror = "1.0.62"
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
windows = "0.58.0"
regex = "1.10.5"

# The following workspace.metadata.wdk sections can be uncommented to configure the workspace for a specific WDK configuration (ex. for rust-analyzer to resolve things for a specific configuration)

Expand Down
1 change: 1 addition & 0 deletions crates/wdk-build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ windows = { workspace = true, features = [
"Win32_Foundation",
"Win32_System_Registry",
] }
regex.workspace = true

[dev-dependencies]
windows = { workspace = true, features = ["Win32_UI_Shell"] }
Expand Down
110 changes: 110 additions & 0 deletions crates/wdk-build/rust-driver-makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,24 @@ args = [
private = true
Copy link
Collaborator

Choose a reason for hiding this comment

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

if wdk_build_package_matches.len() != 1 {

Previously, there was an assumption that there must be wdk-build in the workspace. This is no longer true now there can be a null driver in the workspace without any actual driver code being built (so no wdk-build in the graph).

In the wdk-build only case, we should also see if putting a workspace dep on wdk-build yields anything in the cargo metadata output.

maybe also worth putting a specific message for the case of no-wdk in workspace since that would typically be a null-driver-only workspace scenario

dependencies = ["setup-wdk-config-env-vars", "generate-driver-binary-file"]
env = { "WDK_BUILD_DRIVER_EXTENSION" = { source = "${WDK_BUILD_METADATA-DRIVER_MODEL-DRIVER_TYPE}", default_value = "UNKNOWN_EXTENSION", mapping = { "WDM" = "sys", "KMDF" = "sys", "UMDF" = "dll" } } }
condition_script_runner_args = [
"--base-path",
"${CARGO_MAKE_CURRENT_TASK_INITIAL_MAKEFILE_DIRECTORY}",
]
condition_script = '''
#!@rust

//! ```cargo
//! [dependencies]
//! wdk-build = { path = ".", version = "0.3.0" }
//! anyhow = "1"
//! ```
#![allow(unused_doc_comments)]

fn main() -> anyhow::Result<()> {
wdk_build::cargo_make::driver_model_is_not_package_condition_script()
}
'''
script_runner = "@rust"
script_runner_args = [
"--base-path",
Expand All @@ -327,6 +345,24 @@ wdk_build::cargo_make::copy_to_driver_package_folder(
[tasks.copy-pdb-to-package]
private = true
dependencies = ["build"]
condition_script_runner_args = [
"--base-path",
"${CARGO_MAKE_CURRENT_TASK_INITIAL_MAKEFILE_DIRECTORY}",
]
condition_script = '''
#!@rust

//! ```cargo
//! [dependencies]
//! wdk-build = { path = ".", version = "0.3.0" }
//! anyhow = "1"
//! ```
#![allow(unused_doc_comments)]

fn main() -> anyhow::Result<()> {
wdk_build::cargo_make::driver_model_is_not_package_condition_script()
}
'''
script_runner = "@rust"
script_runner_args = [
"--base-path",
Expand Down Expand Up @@ -373,6 +409,24 @@ wdk_build::cargo_make::copy_to_driver_package_folder(
[tasks.copy-map-to-package]
private = true
dependencies = ["build"]
condition_script_runner_args = [
"--base-path",
"${CARGO_MAKE_CURRENT_TASK_INITIAL_MAKEFILE_DIRECTORY}",
]
condition_script = '''
#!@rust

//! ```cargo
//! [dependencies]
//! wdk-build = { path = ".", version = "0.3.0" }
//! anyhow = "1"
//! ```
#![allow(unused_doc_comments)]

fn main() -> anyhow::Result<()> {
wdk_build::cargo_make::driver_model_is_not_package_condition_script()
}
'''
script_runner = "@rust"
script_runner_args = [
"--base-path",
Expand All @@ -393,6 +447,25 @@ wdk_build::cargo_make::copy_to_driver_package_folder(
)?
'''

[tasks.copy-package-files-to-package]
private = true
condition = { env_set = ["WDK_BUILD_METADATA-DRIVER_INSTALL-PACKAGE_FILES"] }
script_runner = "@rust"
script_runner_args = [
"--base-path",
"${CARGO_MAKE_CURRENT_TASK_INITIAL_MAKEFILE_DIRECTORY}",
]
script = '''
//! ```cargo
//! [dependencies]
//! wdk-build = { path = ".", version = "0.3.0" }
//! ```
#![allow(unused_doc_comments)]

wdk_build::cargo_make::copy_package_files_to_driver_package_folder()?
'''


[tasks.inf2cat]
private = true
dependencies = ["copy-driver-binary-to-package", "copy-inf-to-package"]
Expand Down Expand Up @@ -474,6 +547,24 @@ args = [
[tasks.sign-driver-binary]
private = true
dependencies = ["setup-wdk-config-env-vars", "copy-driver-binary-to-package"]
condition_script_runner_args = [
"--base-path",
"${CARGO_MAKE_CURRENT_TASK_INITIAL_MAKEFILE_DIRECTORY}",
]
condition_script = '''
#!@rust

//! ```cargo
//! [dependencies]
//! wdk-build = { path = ".", version = "0.3.0" }
//! anyhow = "1"
//! ```
#![allow(unused_doc_comments)]

fn main() -> anyhow::Result<()> {
wdk_build::cargo_make::driver_model_is_not_package_condition_script()
}
'''
env = { "WDK_BUILD_SIGNTOOL_SIGN_INPUT_FILE" = "${WDK_BUILD_OUTPUT_DIRECTORY}/${CARGO_MAKE_CRATE_FS_NAME}_package/${CARGO_MAKE_CRATE_FS_NAME}.${WDK_BUILD_DRIVER_EXTENSION}" }
run_task = "signtool-sign"

Expand All @@ -492,6 +583,24 @@ args = ["verify", "/v", "/pa", "${WDK_BUILD_SIGNTOOL_VERIFY_INPUT_FILE}"]
[tasks.verify-signature-driver-binary]
private = true
dependencies = ["setup-wdk-config-env-vars", "sign-driver-binary"]
condition_script_runner_args = [
"--base-path",
"${CARGO_MAKE_CURRENT_TASK_INITIAL_MAKEFILE_DIRECTORY}",
]
condition_script = '''
#!@rust

//! ```cargo
//! [dependencies]
//! wdk-build = { path = ".", version = "0.3.0" }
//! anyhow = "1"
//! ```
#![allow(unused_doc_comments)]

fn main() -> anyhow::Result<()> {
wdk_build::cargo_make::driver_model_is_not_package_condition_script()
}
'''
env = { "WDK_BUILD_SIGNTOOL_VERIFY_INPUT_FILE" = "${WDK_BUILD_OUTPUT_DIRECTORY}/${CARGO_MAKE_CRATE_FS_NAME}_package/${CARGO_MAKE_CRATE_FS_NAME}.${WDK_BUILD_DRIVER_EXTENSION}" }
run_task = "signtool-verify"

Expand All @@ -509,6 +618,7 @@ dependencies = [
"copy-inf-to-package",
"copy-map-to-package",
"copy-certificate-to-package",
"copy-package-files-to-package",
"sign-driver-binary",
"verify-signature-driver-binary",
"sign-cat",
Expand Down
79 changes: 79 additions & 0 deletions crates/wdk-build/src/cargo_make.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ const CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY_ENV_VAR: &str =
"CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY";
const CARGO_MAKE_CURRENT_TASK_NAME_ENV_VAR: &str = "CARGO_MAKE_CURRENT_TASK_NAME";

/// The environment variable that cargo-make uses to store driver model type
const WDK_BUILD_METADATA_DRIVER_MODEL_DRIVER_TYPE_ENV_VAR: &str =
"WDK_BUILD_METADATA-DRIVER_MODEL-DRIVER_TYPE";

/// The environment variable that cargo-make uses to store additional files to
/// be pacakaged with the driver
const WDK_BUILD_METADATA_DRIVER_INSTALL_PACKAGE_FILES_ENV_VAR: &str =
"WDK_BUILD_METADATA-DRIVER_INSTALL-PACKAGE_FILES";

/// `clap` uses an exit code of 2 for usage errors: <https://github.com/clap-rs/clap/blob/14fd853fb9c5b94e371170bbd0ca2bf28ef3abff/clap_builder/src/util/mod.rs#L30C18-L30C28>
const CLAP_USAGE_EXIT_CODE: i32 = 2;

Expand Down Expand Up @@ -725,6 +734,7 @@ pub fn copy_to_driver_package_folder<P: AsRef<Path>>(path_to_copy: P) -> Result<
std::fs::create_dir(&package_folder_path)?;
}

eprintln!("Copying {path_to_copy:?} to {package_folder_path:?}");
let destination_path = package_folder_path.join(
path_to_copy
.file_name()
Expand Down Expand Up @@ -1106,6 +1116,75 @@ pub fn driver_sample_infverif_condition_script() -> anyhow::Result<()> {
})
}

/// `cargo-make` condition script for driver flow tasks in
/// [`rust-driver-makefile.toml`](../rust-driver-makefile.toml)
///
/// # Errors
///
/// This function returns an error whenever it determines that the
/// the driver model is a package and the task should be skipped.
///
/// # Panics
///
/// Panics if `CARGO_MAKE_CURRENT_TASK_NAME` is not set in the environment
/// Panics if `WDK_BUILD_METADATA_DRIVER_MODEL_DRIVER_TYPE` is not set in the
/// environment
pub fn driver_model_is_not_package_condition_script() -> anyhow::Result<()> {
condition_script(|| {
let driver_type = env::var(WDK_BUILD_METADATA_DRIVER_MODEL_DRIVER_TYPE_ENV_VAR)
.expect("A driver type should exist in the WDK build metadata");
if driver_type == "PACKAGE" {
// cargo_make will interpret returning an error from the rust-script
// condition_script as skipping the task
return Err::<(), anyhow::Error>(anyhow::Error::msg(format!(
"Skipping {} task The driver model is a package.",
env::var(CARGO_MAKE_CURRENT_TASK_NAME_ENV_VAR)
.expect("CARGO_MAKE_CURRENT_TASK_NAME should be set by cargo-make")
)));
}
Ok(())
})
}

/// Copy the addition files specified in the wdk metadata to the Driver Package
/// folder
///
/// # Errors
///
/// This function returns an error if the package files specified in the
/// metadata are not found.
///
/// # Panics
///
/// Panics if `WDK_BUILD_METADATA_DRIVER_INSTALL_PACKAGE_FILES` is not set in
/// the environment
pub fn copy_package_files_to_driver_package_folder() -> Result<(), ConfigError> {
let package_files: Vec<String> =
env::var(WDK_BUILD_METADATA_DRIVER_INSTALL_PACKAGE_FILES_ENV_VAR)
.expect("The package files should be set by the wdk-build-init task")
.split_terminator(metadata::ser::SEQ_ELEMENT_SEPARATOR)
.map(String::from)
.collect();

let env_variable_regex = regex::Regex::new(r"\$\{(\w+)\}").unwrap();
package_files.iter().try_for_each(|package_file| {
// Evaluate environment variables in the package file path.
let package_file_evaluated = env_variable_regex
.replace_all(package_file, |captures: &regex::Captures| {
print!("Evaluating environment variable {}", &captures[1]);
env::var(&captures[1]).unwrap_or_else(|_| {
panic!("The environment variable {} should be set", &captures[1])
})
})
.to_string();

let package_file_path = Path::new(&package_file_evaluated);
copy_to_driver_package_folder(package_file_path)
})?;

Ok(())
}

#[cfg(test)]
mod tests {
use crate::ConfigError;
Expand Down
Loading