Rust task runners

Hi,

I am interested in Rust task runners. While make is fine for basic projects of various programming languages, there is a level of rigor and portability in using primarily Rust code as opposed to shell commands. I want my build system declared in the very same language as the main application/library.

There is a trend for exactly that:

  • Go has mage.
  • Haskell has Shake.
  • NPM can do this with the booty pattern.
  • C/C++ can do this with rez (deprecated).
  • D can do this with dale (deprecated).
  • Groovy can probably do this with Gradle.
  • Clojure can probably do this with Leiningen.
  • Scala can probably do this with sbt.
  • Rust can do this with tinyrick.

cargo build scripts can nearly do this. However, it is missing several essential features present in conventional task runners:

  • cargo build scripts are tightly coupled to the overall compilation step, meaning non-contributors would be forced to install extra libraries and/or tools for non-compilation needs. Linters, Remote deployment tools, VM's, integration tests... Such tools belong in dev environments strictly for people actively modifying a Rust project's code, not downstream users. It's one thing to require a C++ compiler for FFI projects, or Thrift, or other code generation systems. Another thing entirely to require Python, or whatever kitchen sink suite that projects inevitably end up consuming.
  • cargo build scripts have no way to invoke the scripts other than performing a cargo compilation command. There's no make <your-task-here>.
  • There's no built-in mechanism for declaring logical task dependencies on other tasks, to prevent redundant tasks from being called twice.

A million and one task runners also exist, using INI/JSON/YAML/TOML to declare tasks, in a way that is even more baroque than make. Super not a fan of those. There's no way to directly trigger programming language functions. Thus incurring portability, safety, and performance costs. Embedding shell commands in non-shell files breaks SAST scans, so those should be kept to a minimum.

That's why I wrote tinyrick. It lets us declare tasks for linting, fuzzing, and other non-build steps out of band of the cargo compilation system. So that we can extend development and CI/CD processes, without breaking conventional build commands.

The task dependency relationship and caching system consists of a simple hashmap. Either the task has been called yet, or it hasn't. No need for fancy graph traversal.

All tasks are effectively .PHONY: by default, with no default tasks. As opposed to make's deep C, lex, and yacc logic.

tinyrick (and tinyrick_extras) provide practical functions and macros for invoking shell commands. Though the emphasis is on calling your custom Rust code for dev tasks, whenever possible.

I am a Zenful programmer: My absolute favorite thing to do in programming is delete lines of code. I would very much like to deprecate tinyrick entirely, in favor of some sufficiently clean, community maintained equivalent, should one exist.

What are some currently maintained, 0 CVE Rust equivalents to Go's mage?

I'm not sure if there is a question in your post or if this is an announcement for your tinyrick project. Either way, have you seen the cargo xtask pattern? Might be of interest to you.

Both an announcement and a request for alternatives.

Thank you for citing xtask. I will try that. The README is disorganized. It's not really clear how to use the tool. But if it does work, then that's an easy enough file to polish over time.

Unless I’m mistaken, it’s not a single tool, just a design pattern.

Yeah, like booty.

The CLI calling convention for such tends to require extra terms. <base tool> <plugin> [<tasks>].

Easy enough to write a CLI utility for convenience.