make can't find (or infer) a rule to build a requested target. Read it literally: the named file is missing AND no rule can produce it. Fix the name, the prerequisite, or generate the missing source.
A missing source file, an un-generated artifact (configure, protobuf output), or a path wrong relative to the makefile's directory. make tells you exactly which prerequisite it wanted ('needed by').
make target names are case-sensitive and live in the Makefile's directory: make build in a tree with no build target = literal no rule. The bare 'No rule to make target X' (without needed-by) means make never found target X at all.
# with 'needed by': a PREREQUISITE is missing. Without: the TARGET name you typed doesn't exist in this Makefile.
make -pn 2>/dev/null | grep -E '^[a-zA-Z0-9_.-]+:' | cut -d: -f1 | sort -u | head -30
ls <dir>; find . -name '<missing-file>' 2>/dev/null # fresh clones: run ./configure, protoc, codegen targets first
# the common order: ./autogen.sh || ./configure, make — a README/configure step usually produces the file make wants
The 'works on my machine' variant: your tree had the generated file from an earlier build; fresh clones don't. Deleting your build dir and cloning fresh is the honest CI-parity test. make -n <target> (dry run) prints the plan it WOULD execute — useful to verify the rule exists and its prerequisites resolve before running anything.
CI clones fresh and makes your tree's generated files visible by their absence: run the codegen/configure step in CI before make, or add a rule that generates the missing file from its source.
make -pn dumps every rule and variable; or just read the Makefile's top-level phony targets (usually .PHONY or the first block). Tab-completion doesn't exist for make — those two are the tooling.
Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.
Browse the template store →One-time. Yours to modify. Instant download from the NinjaOps template store.