Skip to main content

Makefile 使用指南

Makefile 是配合 make 指令使用的建置自動化腳本,常用於編譯、測試、部署等重複性任務。檔名通常為 Makefilemakefile


基本語法

規則 (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 檔名

注意事項

  1. Tab 與空格:recipe 行開頭必須是 Tab,若用空格會報錯。
  2. 路徑與空格:路徑或參數有空格時要加引號,例如 "path with spaces"
  3. 跨平台:指令盡量用通用寫法,或在目標裡區分 OS(例如用 uname 或變數)。
  4. .PHONY:對不會產生檔案的目標建議都加上 .PHONY,避免未來新增同名檔案時行為改變。

小結

Makefile 適合用來:

  • 統一專案的常用指令(install、test、build、run、clean)
  • 用依賴關係自動決定要執行哪些步驟
  • 在 CI/CD 或本機用同一套 make 指令操作專案

把常用指令寫進 Makefile,團隊只要記得 make installmake test 等即可,不必背一堆參數與路徑。