RaySin on GitHub

Makefile 完全指南

2026-03-27

自動化 Go 專案開發流程 -> Makefile 完全指南

基礎

由一系列的「規則」組成:

<target>: <prerequisites>
<TAB><command>
  • target:規則的名稱,一個目標,例如 build。
  • prerequisites:前置條件,即在執行此規則前,必須先完成的其他目標。
  • command:要執行的 shell 指令。
極其重要
command 行的開頭必須是一個 Tab 字元,而不是四個或八個空格。這是 Makefile 最容易出錯的地方。

確認 make 是否安裝

make --version

步驟

第一步:建立 Makefile

在你的專案根目錄下,建立一個名為 Makefile 的檔案。

第二步:定義變數

為了讓 Makefile 更易於維護,我們會先定義一些變數。

這裡我們會讀取 .env 檔案中的變數,並在 Makefile 中使用。 這樣就不用重複定義相同的變數,確保一致性。

# 讀取 .env 檔案
include .env

# 定義變數
# ===================================================================================
# Variables
# ===================================================================================

pes_parent_dir:=$(shell pwd)/$(lastword $(MAKEFILE_LIST))
pes_parent_dir:=$(shell dirname $(pes_parent_dir))

DockerImageNameMigrate='migrate/migrate:v4.19.0'
MigrationFilePath=$(pes_parent_dir)/deployments/migrations
LocalDatabase='mysql://$(MYSQL_USER):$(MYSQL_PASSWORD)@tcp($(MYSQL_HOST):$(MYSQL_PORT))/$(MYSQL_DATABASE)'

第三步:撰寫核心指令

會撰寫一些常用的指令,例如 run 等等。

# ==============================================================================
# Development
# ==============================================================================

.PHONY: run
run: ## Run the application
  @go run ./cmd/api/main.go

JWT (JSON Web Token) 的生成與解析

# ==============================================================================
# JWT Secret
# ==============================================================================

.PHONY: genJWTSecretToEnv
genJWTSecretToEnv: ## Generate a new JWT secret key and append it to the .env file
	@openssl ecparam -genkey -name secp521r1 -noout | tee -a | awk '{printf "%s""\\n",$$0}' | rev | cut -c3- | rev | awk '{printf "\nTOKEN_SECRET=\"%s\"\n",$$0}' >> .env  

資料庫遷移 (Migration)

# ==============================================================================
# Database
# ==============================================================================

.PHONY: databaseMigrateCreate databaseMigrateUp databaseMigrateRollback
databaseMigrateCreate: ## Create a new database migration file. Usage: make databaseMigrateCreate name="migration_name"
ifndef name
	$(error name is undefined. Usage: make databaseMigrateCreate name="migration_name")
endif
	@mkdir -p $(MigrationFilePath)
	@docker run --rm -v $(MigrationFilePath):/migrations --network host $(DockerImageNameMigrate) create -seq -ext sql -dir /migrations $(name)

databaseMigrateUp: ## Migrate database to the latest version
	@docker run --rm -v $(MigrationFilePath):/migrations --network host $(DockerImageNameMigrate) -path=/migrations/ -database $(LocalDatabase) up

databaseMigrateRollback: ## Rollback database by one version
	@docker run --rm -v $(MigrationFilePath):/migrations --network host $(DockerImageNameMigrate) -path=/migrations/ -database $(LocalDatabase) down 1
  • @ 符號:加在指令前,表示在執行時不要將該行指令本身印出來,讓輸出更乾淨。
  • .PHONY:宣告這些目標不是實際的檔案名稱,避免與檔案名稱衝突。

第四步:一個自解釋的 help 指令

一個優秀的 Makefile 應該是自解釋的。我們可以寫一個 help target,它會自動掃描 Makefile 中所有包含 ## 註解的行,並將它們格式化輸出

# ==============================================================================
# Help
# ==============================================================================

.PHONY:  help

help: ## Show this help message
	@echo "Usage: make <target>"
	@echo ""
	@echo "Targets:"
	@awk 'BEGIN {FS = ":.*?## " } /^[a-zA-Z_-]+:.*?## / {printf "	\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)

第五步:指定 Makefile 的預設目標

Makefile 中,我們可以指定一個預設目標,當使用者執行 make 而不帶任何參數時,將會執行這個目標。通常,我們會將 help 目標設為預設目標,這樣使用者可以快速查看所有可用的指令。


Similar Posts

Comments

Translator
Google AdSense
BloggerAds