Skip to content
2 changes: 2 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github: [esden, dragonmux]
patreon: 1bitsquared
86 changes: 86 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: Build Windows

on:
push:
branches:
- 'main'
pull_request:
branches:
- 'main'
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.job }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build-windows:
name: '${{ matrix.os }} (msvc)'
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- windows-2022
- windows-2025
fail-fast: false
steps:
- name: Runtime environment
env:
WORKSPACE: ${{ github.workspace }}
run: |
echo "$env:HOMEDRIVE$env:HOMEPATH\\.local\\bin" >> $env:GITHUB_PATH
echo "$env:HOMEDRIVE$env:HOMEPATH\\.cargo\\bin" >> $env:GITHUB_PATH
echo "GITHUB_WORKSPACE=$(pwd)" >> $env:GITHUB_ENV
- name: Install WDK redist components
run: |
Invoke-WebRequest https://go.microsoft.com/fwlink/p/?LinkID=253170 -OutFile wdk-redist.msi
Start-Process -FilePath msiexec -Verb Runas -Wait -ArgumentList "/i","$PWD\wdk-redist.msi","/passive","/qn","LicenseAccepted=1"
working-directory: ${{ runner.temp }}
- name: Checkout wdi-rs
uses: actions/checkout@v5
with:
lfs: true
submodules: true
- name: Setup Rust
run: |
rustup toolchain install stable-x86_64-pc-windows-msvc
rustup toolchain install stable-aarch64-pc-windows-msvc
rustup default stable-x86_64-pc-windows-msvc
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@v2
with:
tool: cargo-llvm-cov
- name: Version tools
run: |
cargo --version
rustc --version
cargo llvm-cov --version
- name: Setup libusb0 driver dependency
shell: bash
run: |
curl -Lo libusb-win32.zip https://github.com/mcuee/libusb-win32/releases/download/snapshot_1.4.0.1/libusb-win32-bin-1.4.0.1.zip
unzip libusb-win32.zip
mv libusb-win32-bin-1.4.0.1 libusb-win32
echo "LIBUSB0_DIR=${{ runner.temp }}\\libusb-win32" >> $GITHUB_ENV
working-directory: ${{ runner.temp }}
- name: Setup libusbK driver dependency
shell: bash
run: |
curl -Lo libusbK.7z https://github.com/mcuee/libusbk/releases/download/V3.1.0.0/libusbK-3.1.0.0-bin.7z
7z x libusbK.7z
mv libusbK-3.1.0.0-bin libusbK
echo "LIBUSBK_DIR=${{ runner.temp }}\\libusbK\\bin" >> $GITHUB_ENV
working-directory: ${{ runner.temp }}
- name: Build
run: cargo b
- name: Test
run: cargo t
- name: Collect code coverage
run: cargo llvm-cov --all-features --workspace --codecov --output-path codecov.json
- name: Codecov
if: success() && github.repository == 'blackmagic-debug/wdi-rs'
uses: codecov/codecov-action@v5
with:
files: codecov.json
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
71 changes: 54 additions & 17 deletions libwdi-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,13 @@ fn get_cc_var(var_base: &str) -> Option<String>
}
}


/// Turns a [cc::Build] into a [Command] that can be used to create an executable,
/// since cc-rs doesn't directly support compiling executables.
trait CcOutputExecutable
{
fn output_executable(&self) -> Command;
}

impl CcOutputExecutable for cc::Build
{
fn output_executable(&self) -> Command
Expand Down Expand Up @@ -458,15 +458,29 @@ impl LibwdiBuild

// Allow the user to specify WDK_DIR environment variable to override the default WDK
// directory. This becomes necessary when cross compiling.
if let Ok(val) = env::var("WDK_DIR") {
embedder.define("WDK_DIR", Some(format!(r#""{}""#, val).as_str()));
if let Ok(path) = env::var("WDK_DIR") {
// Handle Windows path separators - all single \ need to become \\ for the C(++)
// compiler to not eat itself for breakfast, lunch and dinner with escape sequences
let path = path
.split("\\")
.map(String::from)
.reduce(|base, piece| format!("{}\\\\{}", base, piece))
.unwrap();
embedder.define("WDK_DIR", Some(format!(r#""{}""#, path).as_str()));
}
println!("cargo:rerun-if-env-changed=WDK_DIR");

// If we're compiling with libusb0, let the embedder know where it is.
if cfg!(feature = "libusb0") {
if let Ok(val) = env::var("LIBUSB0_DIR") {
embedder.define("LIBUSB0_DIR", Some(format!(r#""{}""#, val).as_str()));
if let Ok(path) = env::var("LIBUSB0_DIR") {
// Handle Windows path separators - all single \ need to become \\ for the C(++)
// compiler to not eat itself for breakfast, lunch and dinner with escape sequences
let path = path
.split("\\")
.map(String::from)
.reduce(|base, piece| format!("{}\\\\{}", base, piece))
.unwrap();
embedder.define("LIBUSB0_DIR", Some(format!(r#""{}""#, path).as_str()));
} else {
error!("LIBUSB0_DIR environment variable required when compiling with libusb0");
panic!("LIBUSB0_DIR environment variable required when compiling with libusb0");
Expand All @@ -475,8 +489,15 @@ impl LibwdiBuild
}
// Ditto for libusbk
if cfg!(feature = "libusbk") {
if let Ok(val) = env::var("LIBUSBK_DIR") {
embedder.define("LIBUSBK_DIR", Some(format!(r#""{}""#, val).as_str()));
if let Ok(path) = env::var("LIBUSBK_DIR") {
// Handle Windows path separators - all single \ need to become \\ for the C(++)
// compiler to not eat itself for breakfast, lunch and dinner with escape sequences
let path = path
.split("\\")
.map(String::from)
.reduce(|base, piece| format!("{}\\\\{}", base, piece))
.unwrap();
embedder.define("LIBUSBK_DIR", Some(format!(r#""{}""#, path).as_str()));
} else {
error!("LIBUSBK_DIR environment variable required when compiling with libusbk");
panic!("LIBUSBK_DIR environment variable required when compiling with libusbk");
Expand Down Expand Up @@ -697,22 +718,38 @@ impl LibwdiBuild
// If we're compiling with libusb0, provide the header,
// so the library recognizes its existence.
if cfg!(feature = "libusb0") {
if let Ok(val) = env::var("LIBUSB0_DIR") {
lib.define("LIBUSB0_DIR", Some(format!(r#""{}""#, val).as_str()));
}
if let Ok(path) = env::var("LIBUSB0_DIR") {
// Handle Windows path separators - all single \ need to become \\ for the C(++)
// compiler to not eat itself for breakfast, lunch and dinner with escape sequences
let path = path
.split("\\")
.map(String::from)
.reduce(|base, piece| format!("{}\\\\{}", base, piece))
.unwrap();
lib.define("LIBUSB0_DIR", Some(format!(r#""{}""#, path).as_str()));
}
// Everything else is handled by make_embedder
}
// Ditto for libusbk
if cfg!(feature = "libusbk") {
if let Ok(val) = env::var("LIBUSBK_DIR") {
lib.define("LIBUSBK_DIR", Some(format!(r#""{}""#, val).as_str()));
}
if let Ok(path) = env::var("LIBUSBK_DIR") {
// Handle Windows path separators - all single \ need to become \\ for the C(++)
// compiler to not eat itself for breakfast, lunch and dinner with escape sequences
let path = path
.split("\\")
.map(String::from)
.reduce(|base, piece| format!("{}\\\\{}", base, piece))
.unwrap();
lib.define("LIBUSBK_DIR", Some(format!(r#""{}""#, path).as_str()));
}
// Everything else is handled by make_embedder
}

lib
.files(&lib_srcs)
.compile("wdi");
// Tell the builder about all the input files that are needed
lib.files(&lib_srcs);
// Display a diagnostic on what we're about to do and run the build
info!("{:?}", lib.output_executable().args(&lib_srcs));
lib.compile("wdi");

println!("cargo:include={}", self.libwdi_src.join("libwdi").to_str().unwrap());
println!("cargo:rustc-link-lib=shell32");
Expand Down Expand Up @@ -744,7 +781,7 @@ impl LibwdiBuild
let bindings = bindgen::Builder::default()
.header("wrapper.h")
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
//.clang_arg("-Ilibwdi/libwdi")
.clang_arg(format!("-I{}", self.libwdi_src.join("libwdi").to_str().unwrap()))
.allowlist_function("wdi_.*")
.allowlist_var("wdi_.*")
.allowlist_type("wdi_.*")
Expand Down