Formatting Terraform code, rebuilding documentation, and running checks can leave a team with too many commands to remember. A makefile records those commands as reusable project tasks. Create a text file named `makefile` in the project root, define a target for each task, and run it with `make` followed by the target name, such as `make chores`. section 7.2.2 section 7.6
Listing 7.5 Using the makefile
.PHONY: chores chores: format document #1 .PHONY: format format: terraform fmt #2 .PHONY: document document: terraform-docs -c .terraform-docs.yml . #3
The `chores` target depends on `format` and `document`, so one command invokes both tasks. `.PHONY` marks these names as tasks rather than files Make should produce. Recipe commands require tabs, not spaces. section 7.2.2
A target can also represent a real file or directory. Unlike a phony task, Make skips its command when that target already exists. For validation, a `.terraform` target runs initialization with the backend disabled; `test_validation` depends on it before running `validate`. This avoids repeating initialization when the directory exists. The backend-disabled command also leaves a previously configured developer backend in place. section 7.3.1
Listing 7.15 terraform validate makefile
.terraform: #1
$(TF_BINARY) init -backend=false #2
.PHONY: test_validation
test_validation: .terraform #3
$(TF_BINARY) validate
The `.terraform` directory is the non-phony initialization target; `test_validation` is phony because it is a check to run, not a file to generate. section 7.3.1
Variables make the same targets adaptable. A `TF_ENGINE` setting can select Terraform or OpenTofu, with a command-line override such as `make format TF_ENGINE=opentofu`. Installation targets can select Homebrew or Chocolatey and keep package lists in variables. Version-selection logic can likewise support local testing while skipping a local `tenv use` command in CI. Keep shared setup in the makefile, but check platform-specific installers and avoid defining a target twice. section 7.2.4 section 7.2.3 section 9.4.5 section 7.6

