Getting Started
Install GoMake and run your first target in five minutes.
Installation
Install with a single command (requires Go 1.26+):
curl -fsSL https://raw.githubusercontent.com/ctx42/gomake/master/install.sh | sh
Or directly with go run:
go run github.com/ctx42/gomake/cmd/install@latest
After installation, verify it works:
gomake --version
# gomake v0.12.1, hash: abc1234, ...
Embedding a CI/CD tag
Set GOMAKE_CCID to embed a build identifier in the version string:
GOMAKE_CCID=build-42 go run github.com/ctx42/gomake/cmd/install@latest
With custom built-in targets
Pass a targets.yaml to compile external target packages permanently into the
binary at install time:
go run github.com/ctx42/gomake/cmd/install@latest --targets=./targets.yaml
Or forward --targets through the install script with sh -s --:
curl -fsSL https://raw.githubusercontent.com/ctx42/gomake/master/install.sh | sh -s -- --targets=./targets.yaml
See Builtin targets for details.
Installing from a local clone
To build from a checked-out copy of the source instead of a published
release — for instance to install unreleased changes on master — run the
installer from the clone. It builds whatever is in your working tree; no tag,
release, or module proxy is involved:
go run -buildvcs=true ./cmd/install
--targets works the same way:
go run -buildvcs=true ./cmd/install --targets=./targets.yaml
Pass -buildvcs=true: under the default -buildvcs=auto, go run skips
version-control stamping, so the binary reports <not set> for its revision,
hash, and clean/dirty state; forcing it on records them from the checked-out
commit. Use the package path ./cmd/install, not a file path like
cmd/install/install.go — building from an explicit file leaves the build
metadata empty, and the installer then mistakes the run for a published
install and fails.
Your first makefile
Create makefile.go in your project root. Your targets live in
makefile.go; the only other files GoMake loads are OS/arch variants such as
makefile_linux.go (see Writing targets):
//go:build gomake
package main
import (
"context"
"fmt"
"github.com/ctx42/ring/pkg/ring"
)
// Hello prints a greeting.
func Hello(ctx context.Context, rng *ring.Ring) error {
fmt.Fprintln(rng.Stdout(), "Hello from GoMake!")
return nil
}
Run it:
gomake hello
# Hello from GoMake!
List targets:
gomake --list
# hello prints a greeting
Get help:
gomake --help hello
What happens on first run
- GoMake finds
makefile.goin the current directory. - It creates a temporary build directory and copies your makefile sources.
- It generates a thin
mainpackage that wires your targets to the runner. - It compiles the package with
go build. - It caches the binary under
~/.cache/gomake/bin/. - It runs the binary with the target name and any extra arguments.
On subsequent runs with unchanged sources, steps 1–5 are skipped. The cached binary is used directly.
Next steps
- Writing targets — full target syntax
- Namespaces — group targets into hierarchies
- Importing targets — share targets across projects
- CLI reference — all flags and options