Skip to content

Commit

Permalink
Simple Check Feature Task xtask (#7041)
Browse files Browse the repository at this point in the history
  • Loading branch information
cwfitzgerald authored Jan 31, 2025
1 parent 7cde470 commit ad194a8
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 21 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -780,3 +780,22 @@ jobs:
command: check bans licenses sources
arguments: --all-features --workspace
rust-version: ${{ env.REPO_MSRV }}

check-feature-dependencies:
# runtime is normally 1 minute
timeout-minutes: 5

name: "Feature Dependencies"
runs-on: ubuntu-latest
steps:
- name: checkout repo
uses: actions/checkout@v4

- name: Install Repo MSRV toolchain
run: |
rustup toolchain install ${{ env.REPO_MSRV }} --no-self-update --profile=minimal
rustup override set ${{ env.REPO_MSRV }}
cargo -V
- name: Run `cargo feature-dependencies`
run: cargo xtask check-feature-dependencies
114 changes: 114 additions & 0 deletions xtask/src/check_feature_dependencies.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use pico_args::Arguments;
use xshell::Shell;

#[derive(Debug)]
enum Search<'a> {
#[expect(dead_code)]
Positive(&'a str),
Negative(&'a str),
}

#[derive(Debug)]
struct Requirement<'a> {
human_readable_name: &'a str,
target: &'a str,
packages: &'a [&'a str],
features: &'a [&'a str],
default_features: bool,
search_terms: &'a [Search<'a>],
}

const ALL_WGPU_FEATURES: &[&str] = &[
"dx12",
"metal",
"webgpu",
"angle",
"vulkan-portability",
"webgl",
"spirv",
"glsl",
"wgsl",
"naga-ir",
"serde",
"replay",
"counters",
"fragile-send-sync-non-atomic-wasm",
"static-dxc",
];

pub fn check_feature_dependencies(shell: Shell, arguments: Arguments) -> anyhow::Result<()> {
let mut _args = arguments.finish();

let features_no_webgl: Vec<&str> = ALL_WGPU_FEATURES
.iter()
.copied()
.filter(|feature| *feature != "webgl")
.collect();

let requirements = [
Requirement {
human_readable_name: "wasm32 without `webgl` feature does not depend on `wgpu-core`",
target: "wasm32-unknown-unknown",
packages: &["wgpu"],
features: &features_no_webgl,
default_features: false,
search_terms: &[Search::Negative("wgpu-core")],
},
Requirement {
human_readable_name:
"wasm32 with `webgpu` and `wgsl` feature does not depend on `naga`",
target: "wasm32-unknown-unknown",
packages: &["wgpu"],
features: &["webgpu", "wgsl"],
default_features: false,
search_terms: &[Search::Negative("naga")],
},
];

let mut any_failures = false;
for requirement in requirements {
let mut cmd = shell
.cmd("cargo")
.args(["tree", "--target", requirement.target]);

for package in requirement.packages {
cmd = cmd.arg("--package").arg(package);
}

if !requirement.default_features {
cmd = cmd.arg("--no-default-features");
}

if !requirement.features.is_empty() {
cmd = cmd.arg("--features").arg(requirement.features.join(","));
}

log::info!("Checking Requirement: {}", requirement.human_readable_name);
log::debug!("{:#?}", requirement);
log::debug!("$ {cmd}");

let output = cmd.read()?;

log::debug!("{output}");

for search_term in requirement.search_terms {
let found = match search_term {
Search::Positive(search_term) => output.contains(search_term),
Search::Negative(search_term) => !output.contains(search_term),
};

if found {
log::info!("✅ Passed!");
} else {
log::info!("❌ Failed");
any_failures = true;
}
}
}

if any_failures {
anyhow::bail!("Some feature dependencies are not met");
}

Ok(())
}
7 changes: 7 additions & 0 deletions xtask/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::process::ExitCode;
use anyhow::Context;
use pico_args::Arguments;

mod check_feature_dependencies;
mod run_wasm;
mod test;
mod util;
Expand All @@ -12,6 +13,9 @@ const HELP: &str = "\
Usage: xtask <COMMAND>
Commands:
check-feature-dependencies
Check certain dependency invariants are upheld.
run-wasm
Build and run web examples
Expand Down Expand Up @@ -71,6 +75,9 @@ fn main() -> anyhow::Result<ExitCode> {
shell.change_dir(String::from(env!("CARGO_MANIFEST_DIR")) + "/..");

match subcommand.as_deref() {
Some("check-feature-dependencies") => {
check_feature_dependencies::check_feature_dependencies(shell, args)?
}
Some("run-wasm") => run_wasm::run_wasm(shell, args)?,
Some("test") => test::run_tests(shell, args)?,
Some("vendor-web-sys") => vendor_web_sys::run_vendor_web_sys(shell, args)?,
Expand Down
36 changes: 15 additions & 21 deletions xtask/src/run_wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,22 @@ use xshell::Shell;
use crate::util::{check_all_programs, Program};

pub(crate) fn run_wasm(shell: Shell, mut args: Arguments) -> anyhow::Result<()> {
let no_serve = args.contains("--no-serve");
let should_serve = !args.contains("--no-serve");
let release = args.contains("--release");

let programs_needed: &[_] = if no_serve {
&[Program {
crate_name: "wasm-bindgen-cli",
binary_name: "wasm-bindgen",
}]
} else {
&[
Program {
crate_name: "wasm-bindgen-cli",
binary_name: "wasm-bindgen",
},
Program {
crate_name: "simple-http-server",
binary_name: "simple-http-server",
},
]
};

check_all_programs(programs_needed)?;
let mut programs_needed = vec![Program {
crate_name: "wasm-bindgen-cli",
binary_name: "wasm-bindgen",
}];

if should_serve {
programs_needed.push(Program {
crate_name: "simple-http-server",
binary_name: "simple-http-server",
});
}

check_all_programs(&programs_needed)?;

let release_flag: &[_] = if release { &["--release"] } else { &[] };
let output_dir = if release { "release" } else { "debug" };
Expand Down Expand Up @@ -91,7 +85,7 @@ pub(crate) fn run_wasm(shell: Shell, mut args: Arguments) -> anyhow::Result<()>
.with_context(|| format!("Failed to copy static file \"{}\"", file.display()))?;
}

if !no_serve {
if should_serve {
log::info!("serving on port 8000");

// Explicitly specify the IP address to 127.0.0.1 since otherwise simple-http-server will
Expand Down

0 comments on commit ad194a8

Please sign in to comment.