使用 Makefile 構建指令集

使用 Makefile 構建指令集

make 是一個歷史悠久的構建工具,經過配置 Makefile 文件就能夠很方便的使用你本身自定義的各類指令集,且與具體的編程語言無關。 例如配置以下的 Makefile :html

run dev:
	NODE_ENV=development nodemon server.js
複製代碼

這樣當你在命令行執行 make run dev 時其實就會執行 NODE_ENV=development nodemon server.js 指令。node

使用 Makefile 構建指令集能夠很大的提高工做效率。shell

Makefile 基本語法

<target>: <prerequisites>
    <commands>
複製代碼

target 其實就是執行的目標,prerequisites 是執行這條指令的前置條件,commands 就是具體的指令內容。編程

示例:bash

build: clean
	go build -o myapp main.go

clean:
	rm -rf myapp
複製代碼

這裏的 build 有一個前置條件 clean ,意思就是當你執行 make build 時,會先執行 clean 的指令內容 rm -rf myapp ,而後再執行 build 的內容 go build -o myapp main.goapp

變量

自定義變量,示例:編程語言

APP=myapp

build: clean
	go build -o ${APP} main.go

clean:
	rm -rf ${APP}
複製代碼

PHONY

上例中的定義了 target 目標有 buildclean ,若是當前目錄中正好有一個文件叫作 buildclean,那麼其指令內容不會執行,這是由於 make 會把 target 視爲文件,只有當文件不存在或發生改變時纔會去執行命令。工具

爲了解決這個問題,咱們須要使用 PHONY 聲明 target 實際上是僞目標:ui

APP=myapp

.PHONY: build
build: clean
	go build -o ${APP} main.go

.PHONY: clean
clean:
	rm -rf ${APP}
複製代碼

多個 PHONY 也能夠統一聲明在一行中:this

.PHONY: build clean
複製代碼

遞歸的目標

假設咱們的工程目錄結構以下:

~/project

├── main.go
├── Makefile
└── mymodule/
      ├── main.go
      └── Makefile
複製代碼

文件根目錄下還有一個文件夾 mymodule,它多是一個單獨的模塊,也須要打包構建,而且定義有本身的 Makefile :

# ~/project/mymodule/Makefile

APP=module

build:
	go build -o ${APP} main.go
複製代碼

如今當你處於項目的根目錄時,如何去執行 mymodule 子目錄下定義的 Makefile 呢?

使用 cd 命令也能夠,不過咱們有其它的方式去解決這個問題:使用 -C 標誌和特定的 ${MAKE} 變量。

修改項目根目錄中的 Makefile 爲:

APP=myapp

.PHONY: build
build: clean
	go build -o ${APP} main.go

.PHONY: clean
clean:
	rm -rf ${APP}


.PHONY: build-mymodule
build-mymodule:
	${MAKE} -C mymodule build
複製代碼

這樣,當你執行 make build-mymodule 時,其將會自動切換到 mymodule 目錄,而且執行 mymodule 目錄下的 Makefile 中定義的 build 指令。

shell 輸出做爲變量

咱們能夠把 shell 中執行的指令的輸出做爲變量:

V=$(shell go version)

gv:
	echo ${V}
複製代碼

這裏執行 make gv 就會先執行 go version 指令而後把輸出的內容賦值給變量 V 。

判斷語句

假設咱們的指令依賴於環境變量 ENV ,咱們可使用一個前置條件去檢查是否忘了輸入 ENV

.PHONY: run
run: check-env
	echo ${ENV}

check-env:
ifndef ENV
    $(error ENV not set, allowed values - `staging` or `production`)
endif
複製代碼

這裏當咱們執行 make run 時,由於有前置條件 check-env 會先執行前置條件中的內容,指令內容是一個判斷語句,判斷 ENV 是否未定義,若是未定義,則會拋出一個錯誤,錯誤提示就是 error 後面的內容。

幫助提示

添加 help 幫助提示:

.PHONY: build
## build: build the application
build: clean
    @echo "Building..."
    @go build -o ${APP} main.go

.PHONY: run
## run: runs go run main.go
run:
	go run -race main.go

.PHONY: clean
## clean: cleans the binary
clean:
    @echo "Cleaning"
    @rm -rf ${APP}

.PHONY: setup
## setup: setup go modules
setup:
	@go mod init \
		&& go mod tidy \
		&& go mod vendor

.PHONY: help
## help: prints this help message
help:
	@echo "Usage: \n"
	@sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' |  sed -e 's/^/ /'
複製代碼

這樣當你執行 make help 時,就是打印以下的提示內容:

Usage:

  build   build the application
  run     runs go run main.go
  clean   cleans the binary
  setup   setup go modules
  help    prints this help message
複製代碼

參考資料

相關文章
相關標籤/搜索