Skip to content

Commit

Permalink
Merge pull request imgui-rs#464 from thomcc/better-xtask
Browse files Browse the repository at this point in the history
Improvements to our `xtask`s
  • Loading branch information
thomcc authored Mar 13, 2021
2 parents 22eac76 + 0098245 commit 97d5dc8
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 92 deletions.
3 changes: 2 additions & 1 deletion xtask/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ publish = false

[dependencies]
anyhow = "1"
pico-args = "0.3"
smoljson = "0.1"
xshell = "0.1"
xflags = "0.1"
24 changes: 4 additions & 20 deletions xtask/src/bindgen.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
use crate::flags::Bindgen;
use anyhow::{anyhow, Context, Result};
use std::path::{Path, PathBuf};

pub struct GenBindings {
pub bindings_path: Option<String>,
pub output_path: Option<String>,
pub wasm_import_name: Option<String>,
}

impl GenBindings {
impl Bindgen {
pub fn run(self) -> Result<()> {
let root = crate::project_root();
let bindings = self
.bindings_path
.cimgui_path
.map(PathBuf::from)
.unwrap_or_else(|| root.join("imgui-sys/third-party"));

Expand All @@ -24,6 +19,7 @@ impl GenBindings {
.wasm_import_name
.or_else(|| std::env::var("IMGUI_RS_WASM_IMPORT_NAME").ok())
.unwrap_or_else(|| "imgui-sys-v0".to_string());

let types = get_types(&bindings.join("structs_and_enums.json"))?;
let funcs = get_definitions(&bindings.join("definitions.json"))?;
let header = bindings.join("cimgui.h");
Expand Down Expand Up @@ -147,15 +143,3 @@ fn generate_binding_file(

Ok(())
}

// impl Deref for CountingCommand {
// type Target = std::process::Command;
// fn deref(&self) -> &Self::Target {
// &self.c
// }
// }
// impl std::ops::DerefMut for CountingCommand {
// fn deref_mut(&mut self) -> &mut Self::Target {
// &mut self.c
// }
// }
88 changes: 88 additions & 0 deletions xtask/src/flags.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//! xflags is a bit jank still, but pretty nice compared to pico_args, and
//! compiles a billion times faster than clap/structopt.
//!
//! When you modify stuff in the args_parser block, you'll get compile errors.
//! to fix these:
//! 1. run `env XFLAGS_DUMP= cargo build` in the shell.
//! 2. this will error, but should spit out a block of code delimited by
//! "generated start" and "generated end" comments. (if not, you probably
//! have an error message about your usage of the macro, fix and retry)
//! 3. Copy the generated code, and replace the bottom of this file with it.
//!
//! Also, rust-analyzer says this file has a "unresolved macro call". I don't
//! know why, just ignore it — it goes away if you close this file.
#![allow(dead_code)]

xflags::args_parser! {
/// Run custom build command.
cmd xtask {
optional -v, --verbose

default cmd help {
/// Print help information.
optional -h, --help
}
/// Run lints the way we'd run it in CI
cmd lint {}
/// Run tests the way we'd run them in CI
cmd test {}

/// produce bindings using bindgen (must have bindgen installed)
cmd bindgen {
optional --cimgui-path cimgui_path: String
optional --output-path output_path: String
optional --wasm-import-name wasm_import_name: String
}
}
}

// generated start
// The following code is generated by `xflags` macro.
// Run `env XFLAGS_DUMP= cargo build` to regenerate.
#[derive(Debug)]
pub struct Xtask {
pub verbose: bool,
pub subcommand: XtaskCmd,
}

#[derive(Debug)]
pub enum XtaskCmd {
Help(Help),
Lint(Lint),
Test(Test),
Bindgen(Bindgen),
}

#[derive(Debug)]
pub struct Help {
pub help: bool,
}

#[derive(Debug)]
pub struct Lint {}

#[derive(Debug)]
pub struct Test {}

#[derive(Debug)]
pub struct Bindgen {
pub cimgui_path: Option<String>,
pub output_path: Option<String>,
pub wasm_import_name: Option<String>,
}

impl Xtask {
pub const HELP: &'static str = Self::_HELP;

pub fn from_env() -> xflags::Result<Self> {
let mut p = xflags::rt::Parser::new_from_env();
Self::_parse(&mut p)
}

pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
let mut p = xflags::rt::Parser::new(args);
Self::_parse(&mut p)
}
}
// generated end
30 changes: 0 additions & 30 deletions xtask/src/lib.rs

This file was deleted.

96 changes: 55 additions & 41 deletions xtask/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod bindgen;
mod flags;

use anyhow::Result;
use pico_args::Arguments;
use xtask::bindgen::GenBindings;
use xtask::{project_root, pushd};
use flags::XtaskCmd;
use std::path::{Path, PathBuf};

fn main() {
if let Err(e) = try_main() {
Expand All @@ -13,47 +15,59 @@ fn main() {
}
}

const HELP: &str = "\
cargo xtask
Run custom build command.
USAGE:
cargo xtask <SUBCOMMAND>
SUBCOMMANDS:
bindgen - produce bindings using bindgen \
must have bindgen installed, may require unix \
as we pass `bindgen` very many CLI args
TODO:
run - run or list examples
lint-all - run clippy as we would in CI
test-all - run the tests we'd run in CI
";

fn try_main() -> Result<()> {
let _g = pushd(project_root())?;
let root = project_root();
let _d = xshell::pushd(&root)?;
let flags = flags::Xtask::from_env()?;
if flags.verbose {
VERBOSE.store(true, std::sync::atomic::Ordering::Relaxed);
}
match flags.subcommand {
XtaskCmd::Help(_) => eprintln!("{}", flags::Xtask::HELP),
XtaskCmd::Lint(_) => lint_all()?,
XtaskCmd::Test(_) => test_all()?,
XtaskCmd::Bindgen(cmd) => cmd.run()?,
}
Ok(())
}

let mut args = Arguments::from_env();
let subcommand = args.subcommand()?.unwrap_or_default();
fn lint_all() -> Result<()> {
xshell::cmd!("cargo clippy --workspace --all-targets").run()?;
xshell::cmd!(
"cargo clippy --manifest-path imgui-winit-support/Cargo.toml --all-features --all-targets"
)
.run()?;
let winits = &["winit-19", "winit-20", "winit-22", "winit-23", "winit-24"];
for &winit in winits {
xshell::cmd!("cargo clippy --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features {winit} --all-targets").run()?;
}
xshell::cmd!("cargo fmt --all -- --check").run()?;
Ok(())
}

match subcommand.as_str() {
"bindgen" => {
// none of these are required.
let cmd = GenBindings {
// defaults to <project>/imgui-sys/third-party
bindings_path: args.opt_value_from_str("--cimgui-dir")?,
// defaults to <project>/imgui-sys/src
output_path: args.opt_value_from_str("--output-dir")?,
// defaults to "imgui-sys-v0", but can be set in
// env("IMGUI_RS_WASM_IMPORT_NAME")
wasm_import_name: args.opt_value_from_str("--wasm-import-name")?,
};
args.finish()?;
cmd.run()?;
}
_ => {
eprintln!("{}", HELP);
}
fn test_all() -> Result<()> {
xshell::cmd!("cargo test --workspace --all-targets").run()?;
xshell::cmd!("cargo test --workspace --doc").run()?;
let winits = &["winit-19", "winit-20", "winit-22", "winit-23", "winit-24"];
for &winit in winits {
xshell::cmd!("cargo test --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features {winit} --all-targets").run()?;
}
xshell::cmd!("cargo test -p imgui --release -- --ignored").run()?;
Ok(())
}

static VERBOSE: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
pub fn verbose() -> bool {
VERBOSE.load(std::sync::atomic::Ordering::Relaxed)
}

pub fn project_root() -> PathBuf {
Path::new(
&std::env::var("CARGO_MANIFEST_DIR")
.unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()),
)
.ancestors()
.nth(1)
.unwrap()
.to_path_buf()
}

0 comments on commit 97d5dc8

Please sign in to comment.