diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 000000000..35049cbcb --- /dev/null +++ b/.cargo/config @@ -0,0 +1,2 @@ +[alias] +xtask = "run --package xtask --" diff --git a/Cargo.lock b/Cargo.lock index ca9160c27..3bdb7dc0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3035,12 +3035,9 @@ name = "taskchampion-lib" version = "0.1.0" dependencies = [ "anyhow", - "cbindgen", "chrono", "libc", - "pretty_assertions", "taskchampion", - "uuid", ] [[package]] @@ -3797,6 +3794,14 @@ dependencies = [ "time 0.1.43", ] +[[package]] +name = "xtask" +version = "0.1.0" +dependencies = [ + "anyhow", + "cbindgen", +] + [[package]] name = "zeroize" version = "1.3.0" diff --git a/Cargo.toml b/Cargo.toml index 18399678b..701f3839e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,5 @@ members = [ "sync-server", "lib", "integration-tests", + "xtask", ] diff --git a/README.md b/README.md index 10e119460..6bf44be76 100644 --- a/README.md +++ b/README.md @@ -17,12 +17,18 @@ But, if you just want to get some practice with Rust, we'd be happy to have you. ## Structure -There are four crates here: +There are five crates here: * [taskchampion](./taskchampion) - the core of the tool * [taskchampion-cli](./cli) - the command-line binary * [taskchampion-sync-server](./sync-server) - the server against which `task sync` operates - * [replica-server-tests](./replica-server-tests) - integration tests covering both _taskchampion-cli_ and _taskchampion-sync-server_ + * [taskchampion-lib](./lib) - glue code to use _taskchampion_ from C + * [integration-tests](./integration-tests) - integration tests covering _taskchampion-cli_, _taskchampion-sync-server_, and _taskchampion-lib_. + +## Code Generation + +The _taskchampion_lib_ crate uses a bit of code generation to create the `lib/taskchampion.h` header file. +To regenerate this file, run `cargo xtask codegen`. ## Documentation Generation diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 86a2ec735..564f28590 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -2,7 +2,6 @@ name = "taskchampion-lib" version = "0.1.0" edition = "2018" -build = "build.rs" [lib] name = "taskchampion" @@ -17,6 +16,3 @@ anyhow = "1.0" [dev-dependencies] pretty_assertions = "1" - -[build-dependencies] -cbindgen = "0.20.0" diff --git a/lib/build.rs b/lib/build.rs deleted file mode 100644 index f8f75d3b5..000000000 --- a/lib/build.rs +++ /dev/null @@ -1,26 +0,0 @@ -use cbindgen::*; - -use std::env; - -fn main() { - let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); - - Builder::new() - .with_crate(crate_dir) - .with_config(Config { - language: Language::C, - cpp_compat: true, - sys_includes: vec!["stdbool.h".into(), "stdint.h".into(), "time.h".into()], - usize_is_size_t: true, - no_includes: true, - enumeration: EnumConfig { - // this appears to still default to true for C - enum_class: false, - ..Default::default() - }, - ..Default::default() - }) - .generate() - .expect("Unable to generate bindings") - .write_to_file("taskchampion.h"); -} diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml new file mode 100644 index 000000000..fe6c3dda6 --- /dev/null +++ b/xtask/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "xtask" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0" +cbindgen = "0.20.0" diff --git a/xtask/src/main.rs b/xtask/src/main.rs new file mode 100644 index 000000000..036802e9a --- /dev/null +++ b/xtask/src/main.rs @@ -0,0 +1,47 @@ +//! This executable defines the `cargo xtask` subcommands. +//! +//! At the moment it is very simple, but if this grows more subcommands then +//! it will be sensible to use `clap` or another similar library. + +use cbindgen::*; +use std::env; +use std::path::PathBuf; + +pub fn main() -> anyhow::Result<()> { + let arg = env::args().nth(1); + match arg.as_ref().map(|arg| arg.as_str()) { + Some("codegen") => codegen(), + Some(arg) => anyhow::bail!("unknown xtask {}", arg), + _ => anyhow::bail!("unknown xtask"), + } +} + +/// `cargo xtask codegen` +/// +/// This uses cbindgen to generate `lib/taskchampion.h`. +fn codegen() -> anyhow::Result<()> { + let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + let workspace_dir = manifest_dir.parent().unwrap(); + let lib_crate_dir = workspace_dir.join("lib"); + + Builder::new() + .with_crate(&lib_crate_dir) + .with_config(Config { + language: Language::C, + cpp_compat: true, + sys_includes: vec!["stdbool.h".into(), "stdint.h".into(), "time.h".into()], + usize_is_size_t: true, + no_includes: true, + enumeration: EnumConfig { + // this appears to still default to true for C + enum_class: false, + ..Default::default() + }, + ..Default::default() + }) + .generate() + .expect("Unable to generate bindings") + .write_to_file(lib_crate_dir.join("taskchampion.h")); + + Ok(()) +}