From Makefiles to Taskfiles
The good old make
command has been around for ages. It helps us compile code, build projects, run tests and automate all sorts of tasks. As projects grow, Makefiles can become hard to use. The syntax, while simple, can get cryptic with complex rules and conditionals. Debugging Makefiles is no fun either. Error messages from make
can be hard to decipher, making it tough to figure out what went wrong. A single space in the wrong place can result in Makefile:42: *** commands commence before first target. Stop.
😬
Meet Taskfile - a task runner tool that aims to be simpler and easier to use than Makefile
What's Taskfile?
A Taskfile is essentially a configuration file for the Task tool. It uses a YAML-based syntax, which is both human-readable and easy to write. Instead of the somewhat cryptic syntax of Makefiles, Taskfiles are structured and clear. This makes them easier to maintain and understand, especially for new team members.
Let’s take a look at some of the key features:
- Cross-Platform Compatibility - one of the coolest things about Taskfiles is their cross-platform support. You write a Taskfile once, and it works on any system that has the Task tool installed, even Windows!
- Built-in Dependency Management - similar to Makefile, Taskfiles offer built-in support for dependencies. You can define which tasks depend on others, ensuring that tasks run in the correct order.
- Parallel Execution - you can easily specify tasks to run in parallel, which can significantly speed up your build and deployment processes
- Templating and Variable Substitution - you can define variables and templates directly in your Taskfile, making your task definitions more dynamic and reusable.
- Simplicity and Readability - YAML readability makes it easy for anyone on your team to understand and modify the Taskfile.
Let's try it
Grab the project you are currently working on and let's try Taskfile in action
First we install it and create a simple Taskfile.yml
$ brew install go-task
$ vim Taskfile.yml # or task --init
As mentioned above it uses simple Yaml schema. Let's start simple by defining a few basic tasks. Here’s an example:
version: '3'
tasks:
build:
cmds:
- go build ./...
test:
cmds:
- go test ./...
Here we basically define build and test tasks similar to how you will do in a Makefile. Next you likely would need to define some dependencies, like so