Filters
How to search
  • Plain words find names, texts and examples.
  • "two words" finds the exact phrase.
  • --name or -x finds an option.
  • #word looks only inside commands.
  • @grep finds lessons and labs that use grep.
  • Filters: cat:network · in:labs · in:notes · level:rhcsa · ch:8 · root:yes. Put ! before a word to leave it out. OR between words means one of them.
  • ↑ ↓ to move · Enter to open · Esc to close · / to search

make

Run the tasks of a project (build, test, lint, deploy) from one Makefile, with short names like make test.

Level
DevOps tool
Group
Build tools and languages
Needs root
No
Package
make

What it does

make reads a Makefile with targets. Each target has a list of things it depends on and the shell lines (the recipe) that build it. make runs a recipe only when a file is missing or older than the files it depends on, so a big build only does the work that changed.

In DevOps teams a Makefile is often just a task runner: make build, make test, make up, make deploy. The same short commands work on every laptop and in every CI job. Such targets are marked .PHONY because they do not make a file.

Recipe lines must start with a Tab, not spaces.

How to write it

make [OPTIONS] [TARGET ...] [VAR=value ...]

Options 13

Most used

Common options

-f FILE
Use FILE instead of Makefile.
-C DIR
Change to DIR first (run the Makefile of a sub-project).
-j N
Run N recipes at the same time (parallel build).
-n, --dry-run
Print the commands, do not run them.
-B, --always-make
Build every target again, also when it is up to date.
-k, --keep-going
Go on with other targets after an error.
-s, --silent
Do not print the commands.
-i, --ignore-errors
Ignore errors in recipes.
-p
Print all rules and variables (debug).
-q, --question
Exit 0 if the target is up to date, 1 if not; run nothing.
-e
Environment variables win over Makefile variables.
--debug=b
Explain why a target is rebuilt.
VAR=value
Set a variable on the command line (wins over the Makefile).

Examples 11

$ run as a normal user# run as root (or with sudo)

  1. 1Run the default target (the first one in the file)

    make
  2. 2A task-runner Makefile for a web service

    cat Makefile
    .PHONY: build test lint up down
    IMAGE ?= shop
    TAG   ?= $(shell git rev-parse --short HEAD)
    build:
    	docker build -t $(IMAGE):$(TAG) .
    test:
    	go test ./...
    lint:
    	golangci-lint run
    up:
    	docker compose up -d
    down:
    	docker compose down
    make build test

    Recipe lines start with a Tab. ?= sets a default that the environment or the command line can change.

  3. 3Set a variable from the command line

    make build TAG=v1.4.0
  4. 4See what would run, without running it

    make -n deploy
  5. 5Build faster with 8 jobs at once

    make -j8
  6. 6Run the Makefile of a sub-folder

    make -C services/api test
  7. 7A help target that lists all targets

    cat Makefile
    help: ## Show this help
    	@grep -E '^[a-zA-Z_-]+:.*## ' $(MAKEFILE_LIST) | awk -F':.*## ' '{printf "%-12s %s\n", $$1, $$2}'
    make help
    help         Show this help

    @ hides the command itself. $$ is a single $ for the shell.

  8. 8Rebuild everything

    make -B
  9. 9Use make in CI (GitHub Actions)

    cat .github/workflows/ci.yml
    jobs:
      test:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - run: make lint test
  10. 10Find out why a target runs again

    make --debug=b build
  11. 11Check if a target is up to date (exit code)

    make -q dist/app || echo "needs a build"

Watch out

  • "missing separator" means a recipe line starts with spaces instead of a Tab.
  • Each recipe line runs in its own shell: cd dir on one line does not change the next line. Use cd dir && cmd.
  • Mark task targets .PHONY, or a file with the same name (for example a folder called test) stops them.

Files

Makefile
The default file make reads (also makefile, GNUmakefile).

Tips to remember

  • Keep the real logic in scripts and call them from make; the Makefile stays short.
  • make help with ## comments makes a project easy for new team members.

Exit codes

0All targets done.
1-q and a target is not up to date.
2An error.