Skip to content

Go Recipes

must provides two Go recipe types: go-bin and go-test.

Quick start

Project layout:

myapp/
├── go.mod
├── go.sum
├── cmd/
│   └── myapp/
│       └── main.go
├── myapp_test.go
└── Mustfile.toml

go.mod:

module github.com/user/myapp

go 1.22

cmd/myapp/main.go:

package main

import (
    "fmt"
    "runtime"
)

var version = "dev"

func greeting(name string) string {
    return fmt.Sprintf("hello, %s!", name)
}

func main() {
    fmt.Printf("myapp %s (%s/%s)\n", version, runtime.GOOS, runtime.GOARCH)
    fmt.Println(greeting("world"))
}

myapp_test.go:

package main

import "testing"

func TestGreeting(t *testing.T) {
    cases := []struct {
        input string
        want  string
    }{
        {"world", "hello, world!"},
        {"must", "hello, must!"},
        {"", "hello, !"},
    }
    for _, tc := range cases {
        got := greeting(tc.input)
        if got != tc.want {
            t.Errorf("greeting(%q) = %q, want %q", tc.input, got, tc.want)
        }
    }
}

Mustfile.toml:

[project]
name = "myapp"
version = "0.1.0"

[recipe.build]
type    = "go-bin"
package = "./cmd/myapp"
ldflags = "-X main.version=0.1.0"

[recipe.test]
type    = "go-test"
package = "./..."
deps    = ["build"]

Build and test:

$ must build
[build] go build -ldflags -X main.version=0.1.0 ./cmd/myapp
 ok  build  1.2s

$ must test
[test] go test ./...
 ok  test  0.8s

Try it

go-bin — Build a binary

[recipe.build]
type       = "go-bin"
package    = "./cmd/server"
ldflags    = "-s -w"
build_tags = ["integration", "cgo"]

Runs: go build [-tags <t>] [-ldflags <f>] <package>

Cache key includes: go version, package name, ldflags, build tags, target, env vars.

go-test — Run tests

[recipe.test]
type    = "go-test"
package = "./..."
deps    = ["build"]

Runs: go test ./...

Cache strategy: never (test results should always be fresh).

Fields

Field Type Applies to Description
package string all Go package path
ldflags string bin Linker flags (e.g. -s -w)
build_tags string[] bin Build tags
deps string[] all Dependencies
env map all Environment variables

All recipes also support these common fields: deps, env, cache ("hash" / "mtime" / "none"), phony (always re-run).

Cross-compilation

Go cross-compiles natively via GOOS/GOARCH environment variables — no extra toolchain needed. must sets these automatically based on the target triple.

Examples

[project]
name = "my-go-service"

[recipe.server]
type       = "go-bin"
package    = "./cmd/server"
ldflags    = "-s -w"
build_tags = ["prod"]

[recipe.test]
type    = "go-test"
package = "./..."
deps    = ["server"]

See also