Makefile 使用指南
Makefile 是配合 make 指令使用的建置自動化腳本,常用於編譯、測試、部署等重複性任務。檔名通常為 Makefile 或 makefile。
基本語法
規則 (Rule) 結構
target: prerequisites
recipe
- target:要產生的目標(檔名或虛擬目標)
- prerequisites:依賴項,任一個比 target 新時會重新執行
- recipe:要執行的指令,必須以 Tab 開頭(不可用空格)
簡單範例
# 執行 make 或 make hello 會印出 Hello
hello:
echo "Hello, World!"
# 多個指令
build:
go build -o app .
chmod +x app
常用概念
虛擬目標 (Phony Target)
不對應實際檔案的目標,用來當成「指令名稱」使用。建議用 .PHONY 宣告,避免與同名檔案衝突:
.PHONY: run test clean install
run:
python main.py
test:
pytest tests/
clean:
rm -rf __pycache__ *.pyc dist/
install:
pip install -r requirements.txt
變數
# 簡單賦值(延遲展開,用到時才求值)
CC = gcc
CFLAGS = -Wall -O2
# 即時賦值(定義當下就展開)
OUT := build/app
# 使用變數
build:
$(CC) $(CFLAGS) -o $(OUT) main.c
自動變數
| 變數 | 說明 |
|---|---|
$@ | 目前目標的名稱 |
$< | 第一個 prerequisite |
$^ | 所有 prerequisites |
$? | 比目標新的 prerequisites |
app: main.o utils.o
$(CC) -o $@ $^ # 等同 gcc -o app main.o utils.o
實用範例
Python 專案
.PHONY: install run test lint clean
VENV = .venv
PY = $(VENV)/bin/python
PIP = $(VENV)/bin/pip
install:
python -m venv $(VENV)
$(PIP) install -r requirements.txt
run:
$(PY) main.py
test:
$(PY) -m pytest tests/ -v
lint:
$(PY) -m ruff check .
$(PY) -m mypy .
clean:
rm -rf $(VENV) __pycache__ .pytest_cache .mypy_cache
Go 專案
.PHONY: build run test clean
BINARY = app
MAIN = ./cmd/server
build:
go build -o $(BINARY) $(MAIN)
run: build
./$(BINARY)
test:
go test -v ./...
clean:
rm -f $(BINARY)
前端 (npm / Vue)
.PHONY: install dev build lint
install:
npm ci
dev:
npm run dev
build:
npm run build
lint:
npm run lint
多環境(dev / prod)
.PHONY: dev prod
dev:
export ENV=development && python main.py
prod:
export ENV=production && gunicorn -w 4 main:app
進階技巧
條件與預設目標
# 第一個出現的目標是預設目標(只打 make 時會執行)
.DEFAULT_GOAL := help
help:
@echo "用法: make [target]"
@echo " install - 安裝依賴"
@echo " test - 執行測試"
@echo " clean - 清理產物"
- 指令前加
@不會印出該行指令本身,只印出輸出。
依賴其他目標
run: build
./app
build:
go build -o app .
執行 make run 會先執行 build,再執行 run 的 recipe。
傳入參數
# make run PORT=8080
run:
python main.py --port $(PORT)
若不想必填,可設預設值:
PORT ?= 3000
run:
python main.py --port $(PORT)
在 recipe 中寫多行(同一 shell)
預設每一行 recipe 都在新的 shell 執行,若要同一 shell 多行,用 \ 接行並用 ; 或 &&:
setup:
cd /tmp && \
mkdir -p myapp && \
cd myapp && pwd
常用指令
| 指令 | 說明 |
|---|---|
make | 執行預設目標(通常是第一個目標) |
make target | 執行指定目標 |
make -n target | 乾跑,只顯示會執行的指令不真的跑 |
make -j4 | 並行執行多個目標(數字為 job 數) |
make -f other.mk | 使用指定的 Makefile 檔名 |
注意事項
- Tab 與空格:recipe 行開頭必須是 Tab,若用空格會報錯。
- 路徑與空格:路徑或參數有空格時要加引號,例如
"path with spaces"。 - 跨平台:指令盡量用通用寫法,或在目標裡區分 OS(例如用
uname或變數)。 - .PHONY:對不會產生檔案的目標建議都加上
.PHONY,避免未來新增同名檔案時行為改變。
小結
Makefile 適合用來:
- 統一專案的常用指令(install、test、build、run、clean)
- 用依賴關係自動決定要執行哪些步驟
- 在 CI/CD 或本機用同一套
make指令操作專案
把常用指令寫進 Makefile,團隊只要記得 make install、make test 等即可,不必背一堆參數與路徑。