Skip to main content

MEMO-049: Task Build System Migration

Overview

Migration from GNU Make to Task completed in October 2024. This memo documents the rationale, migration process, and provides guidance for developers transitioning from Make to Task.

Status

Completed: October 2024 Migration File: Originally TASK_MIGRATION.md (archived to this memo) Current Build System: Task (Taskfile.yml) Legacy Build System: Make (Makefile.legacy, no longer maintained)

Why Task?

Problems with Make

  1. Manual dependency tracking: Make requires explicitly listing source files, which is error-prone
  2. Slow with binary targets: Make checks timestamps, but rebuilds are slow or skipped incorrectly
  3. Complex glob patterns: Using find in Make is awkward and evaluated at parse-time
  4. Poor multi-language support: Make was designed for C, not Go/Rust/Python polyglots

Benefits of Task

  1. Automatic change detection: Uses checksum-based detection via sources and generates
  2. Parallel by default: Tasks run concurrently when possible
  3. Cleaner syntax: YAML instead of Make's arcane syntax
  4. Multi-language friendly: Designed for modern polyglot projects
  5. Built-in file watching: No need for external tools
  6. Cross-platform: Works identically on macOS, Linux, and Windows

Installation

macOS (Homebrew)

brew install go-task

Linux/macOS (install script)

sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d

Alternative: Go install

go install github.com/go-task/task/v3/cmd/task@latest

Verify installation

task --version

Command Mapping

All make commands have been converted to task commands:

Make CommandTask CommandNotes
maketaskDefault target (build all)
make helptask --listShow available tasks
make buildtask buildBuild all components
make proxytask proxyBuild Rust proxy
make prismctltask prismctlBuild prismctl
make testtask testRun all tests
make test-paralleltask test-parallelRun tests in parallel
make linttask lintLint all code
make lint-paralleltask lint-parallelLint in parallel
make fmttask fmtFormat all code
make cleantask cleanClean build artifacts
make prototask protoGenerate protobuf
make coveragetask coverageGenerate coverage
make docstask docsBuild documentation
make citask ciRun CI pipeline

Key Differences

1. Automatic Dependency Tracking

Make (manual):

$(BINARIES_DIR)/prismctl: cmd/prismctl/go.mod
cd cmd/prismctl && go build -o $(BINARIES_DIR)/prismctl .

Task (automatic):

prismctl:
desc: Build prismctl CLI tool
sources:
- cmd/prismctl/**/*.go
- cmd/prismctl/go.mod
- cmd/prismctl/go.sum
generates:
- '{{.BINARIES_DIR}}/prismctl'
cmds:
- cd cmd/prismctl && go build -o {{.BINARIES_DIR}}/prismctl .

Task automatically:

  • Checksums all source files
  • Only rebuilds if sources changed
  • No manual glob patterns needed

2. Parallel Execution

Make: Sequential by default, use make -j4 for parallelism Task: Parallel by default when using deps:

build:
desc: Build all components
deps: [proxy, build-cmds, patterns] # Runs in parallel!

3. Variables

Make: Environment variables and shell expansion Task: Built-in variable system with templates

vars:
BUILD_DIR: '{{.ROOT_DIR}}/build'
BINARIES_DIR: '{{.BUILD_DIR}}/binaries'

tasks:
proxy:
cmds:
- cp target/release/prism-proxy {{.BINARIES_DIR}}/

4. No More .PHONY

Task doesn't use file targets by default, so no need for .PHONY declarations.

Quick Start

  1. Install Task (see Installation above)

  2. List available tasks:

    task --list
  3. Run default build:

    task
  4. Run specific task:

    task prismctl
  5. Run with variables:

    task test-acceptance-parallel-backends BACKENDS=MemStore,Redis
  6. Watch and rebuild (built-in):

    task --watch proxy

Advanced Features

Incremental Builds

Task only rebuilds when sources change:

$ task proxy
task: Task "proxy" is up to date

$ touch prism-proxy/src/main.rs
$ task proxy
Building Rust proxy...
✓ Proxy built

Parallel Testing

# Run all tests in parallel (automatic with deps)
task test-parallel

# Explicit parallel execution
task --parallel lint-rust lint-python lint-go

Dry Run

# See what would run without executing
task --dry proxy

Summary View

# Show task descriptions
task --list-all

CI/CD Integration

GitHub Actions workflows have been updated to install and use Task:

- name: Install Task
run: |
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin

- name: Build
run: task build

Troubleshooting

Task not found after install

# Ensure Task is in your PATH
export PATH="$HOME/.local/bin:$PATH"

# Or use full path
~/.local/bin/task --list

Task always rebuilds

  • Check that sources and generates are correctly specified
  • Use task --status <taskname> to debug
  • Ensure generated files match exactly

Need old Makefile?

The original Makefile has been archived as Makefile.legacy for reference.

Resources

Feedback

If you encounter issues with the Task migration, please:

  1. Check this migration guide
  2. Review the Taskfile.yml
  3. Open an issue with details about the problem

Legacy Support

The original Makefile has been preserved as Makefile.legacy for reference but is no longer maintained. All development should use Task going forward.

Impact

Developer Experience: Improved build times with automatic dependency detection and parallel execution CI/CD: Simplified workflows with consistent cross-platform behavior Maintenance: Easier to understand and modify YAML syntax vs Make's syntax