Skip to content

Commit

Permalink
feat: automatically determine whether driver packaging steps make sen…
Browse files Browse the repository at this point in the history
…se to run on Cargo package
  • Loading branch information
wmmc88 committed Jan 24, 2024
1 parent 413ad35 commit 78f1b7f
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 24 deletions.
26 changes: 17 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,13 @@ The crates in this repository are available from [`crates.io`](https://crates.io
crate-type = ["cdylib"]
```

4. Set crate panic strategy to `abort` in `Cargo.toml`:
4. Mark the crate as a driver with a wdk metadata section. This lets the cargo-make tasks know that the package is a driver and that the driver packaging steps need to run.

```toml
[package.metadata.wdk]
```

5. Set crate panic strategy to `abort` in `Cargo.toml`:

```toml
[profile.dev]
Expand All @@ -66,7 +72,7 @@ The crates in this repository are available from [`crates.io`](https://crates.io
lto = true # optional setting to enable Link Time Optimizations
```

5. Create a `build.rs` and add the following snippet:
6. Create a `build.rs` and add the following snippet:

```rust
fn main() -> Result<(), wdk_build::ConfigError> {
Expand All @@ -75,21 +81,21 @@ The crates in this repository are available from [`crates.io`](https://crates.io
}
```

6. Mark your driver as `no_std` in `lib.rs`:
7. Mark your driver crate as `no_std` in `lib.rs`:

```rust
#![no_std]
```

7. Add a panic handler in `lib.rs`:
8. Add a panic handler in `lib.rs`:

```rust
#[cfg(not(test))]
extern crate wdk_panic;

```

8. Add a global allocator in `lib.rs`:
9. Optional: Add a global allocator in `lib.rs`:

```rust
#[cfg(not(test))]
Expand All @@ -100,7 +106,9 @@ The crates in this repository are available from [`crates.io`](https://crates.io
static GLOBAL_ALLOCATOR: WDKAllocator = WDKAllocator;
```

9. Add a DriverEntry in `lib.rs`:
This is only required if you want to be able to use the [`alloc` modules](https://doc.rust-lang.org/alloc/) in the rust standard library. You are also free to use your own implementations of global allocators.

10. Add a DriverEntry in `lib.rs`:

```rust
use wdk_sys::{
Expand All @@ -118,7 +126,7 @@ The crates in this repository are available from [`crates.io`](https://crates.io
}
```

10. Add a `Makefile.toml`:
11. Add a `Makefile.toml`:

```toml
extend = ".cargo-make-loadscripts/rust-driver-makefile.toml"
Expand All @@ -137,9 +145,9 @@ The crates in this repository are available from [`crates.io`](https://crates.io
"""
```

11. Add an inx file that matches the name of your `cdylib` crate.
12. Add an inx file that matches the name of your `cdylib` crate.

12. Build the driver:
13. Build the driver:

```pwsh
cargo make
Expand Down
2 changes: 2 additions & 0 deletions crates/sample-kmdf-driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ keywords = ["windows", "driver", "sample", "example", "wdf"]
categories = ["hardware-support"]
publish = false

[package.metadata.wdk]

[lib]
crate-type = ["cdylib"]
# Tests from root driver crates must be excluded since there's no way to prevent linker args from being passed to their unit tests: https://github.com/rust-lang/cargo/issues/12663
Expand Down
82 changes: 67 additions & 15 deletions rust-driver-makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

# FIXME: this flow is based on the signing process of a KMDF PNP driver. There should be different flows availabe for different types of drivers as outlined in https://learn.microsoft.com/en-us/windows-hardware/drivers/install/test-signing-driver-packages
[config]
min_version = "0.37.3"
min_version = "0.37.8"
init_task = "wdk-build-init"
reduce_output = false

[env]
# This allows all workspace members to access this makefile
Expand Down Expand Up @@ -106,6 +107,7 @@ std::fs::copy(&source_file, &destination_file).expect(&format!("copy of '{source
'''

[tasks.generate-sys-file]
private = true
dependencies = ["build"]
script_runner = "@rust"
script = '''
Expand All @@ -118,6 +120,7 @@ std::fs::copy(&source_file, &destination_file).expect(&format!("copy of '{source
'''

[tasks.stampinf]
private = true
dependencies = ["copy-inx-to-output"]
command = "stampinf"
args = [
Expand All @@ -136,6 +139,7 @@ args = [
]

[tasks.infverif]
private = true
dependencies = ["stampinf"]
command = "infverif"
args = [
Expand Down Expand Up @@ -165,6 +169,7 @@ std::fs::copy(&source_file, &destination_file).expect(&format!("copy of '{source
'''

[tasks.copy-pdb-to-package]
private = true
dependencies = ["build"]
script_runner = "@rust"
script = '''
Expand All @@ -184,6 +189,7 @@ std::fs::copy(&source_file, &destination_file).expect(&format!("copy of '{source
'''

[tasks.copy-inf-to-package]
private = true
dependencies = ["stampinf"]
script_runner = "@rust"
script = '''
Expand All @@ -203,6 +209,7 @@ std::fs::copy(&source_file, &destination_file).expect(&format!("copy of '{source
'''

[tasks.copy-map-to-package]
private = true
dependencies = ["build"]
script_runner = "@rust"
script = '''
Expand All @@ -222,6 +229,7 @@ std::fs::copy(&source_file, &destination_file).expect(&format!("copy of '{source
'''

[tasks.inf2cat]
private = true
dependencies = ["copy-sys-to-package", "copy-inf-to-package"]
command = "inf2cat"
args = [
Expand All @@ -230,19 +238,20 @@ args = [
"/uselocaltime",
]

[tasks.generate-certificate-if-needed]
# This script can't be in a `condition_script` block because of https://github.com/sagiegurari/cargo-make/issues/987
script_runner = "@duckscript"
script = '''
[tasks.generate-certificate]
private = true
condition_script = '''
#!@duckscript
out = exec certmgr.exe -put -s WDRTestCertStore -c -n WDRLocalTestCert ${WDK_BUILD_OUTPUT_DIRECTORY}/WDRLocalTestCert.cer
if not eq ${out.code} 0
if eq ${out.code} 0
echo WDRLocalTestCert found in WDRTestCertStore. Skipping certificate generation.
exit 1
else
echo WDRLocalTestCert not found in WDRTestCertStore. Generating new certificate.
cm_run_task generate-certificate
exit 0
end
'''

[tasks.generate-certificate]
private = true
command = "makecert"
args = [
"-r",
Expand All @@ -259,7 +268,8 @@ args = [
]

[tasks.copy-certificate-to-package]
dependencies = ["generate-certificate-if-needed"]
private = true
dependencies = ["generate-certificate"]
script_runner = "@rust"
script = '''
use std::path::PathBuf;
Expand All @@ -277,7 +287,8 @@ std::fs::copy(&source_file, &destination_file).expect(&format!("copy of '{source
'''

[tasks.signtool]
dependencies = ["inf2cat", "generate-certificate-if-needed"]
private = true
dependencies = ["inf2cat", "generate-certificate"]
command = "signtool"
args = [
"sign",
Expand All @@ -294,6 +305,7 @@ args = [
]

[tasks.package-driver]
private = true
dependencies = [
"copy-sys-to-package",
"copy-pdb-to-package",
Expand All @@ -304,7 +316,47 @@ dependencies = [
"infverif",
]

[tasks.default]
alias = "package-driver"
[tasks.package-driver-flow]
# Only run flow if the current package is marked as a driver
condition_script = '''
#!@duckscript
# Execute Cargo Metadata to get Package information
out = exec --fail-on-error cargo metadata --no-deps --format-version 1 --manifest-path ${CARGO_MAKE_WORKING_DIRECTORY}/Cargo.toml
assert_eq ${out.code} 0 "cargo metadata failed with exit code: ${out.code}\nstdout:\n${out.stdout}\nstderr:\n${out.stderr}"
manifest_metadata = json_parse --collection ${out.stdout}
packages = map_get ${manifest_metadata} packages
contains_wdk_metadata = set false
for package in ${packages}
package_name = map_get ${package} name
# Find metadata for the current package
if eq ${package_name} ${CARGO_MAKE_CRATE_NAME}
package_metadata = map_get ${package} metadata
# Check if the package contains a metadata section
if is_map ${package_metadata}
# Check if the package contains a package.metadata.wdk section
contains_wdk_metadata = map_contains_key ${package_metadata} wdk
end
end
end
release --recursive ${manifest_metadata}
# Run driver package-driver task if the package contains a package.metadata.wdk section
if ${contains_wdk_metadata}
echo Building and packaging driver: ${CARGO_MAKE_CRATE_NAME}...
exit 0
else
echo ${CARGO_MAKE_CRATE_NAME} does not contain a package.metadata.wdk section in its manifest. Skipping package-driver task.
exit 1
end
'''
run_task = "package-driver"

# TODO: mark drivers
[tasks.default]
alias = "package-driver-flow"

0 comments on commit 78f1b7f

Please sign in to comment.