make
是一個歷史悠久的構建工具,經過配置 Makefile
文件就能夠很方便的使用你本身自定義的各類指令集,且與具體的編程語言無關。
例如配置以下的 Makefile
:html
run dev: NODE_ENV=development nodemon server.js
這樣當你在命令行執行 make run dev
時其實就會執行 NODE_ENV=development nodemon server.js
指令。node
使用 Makefile
構建指令集能夠很大的提高工做效率。shell
<target>: <prerequisites> <commands>
target
其實就是執行的目標,prerequisites
是執行這條指令的前置條件,commands
就是具體的指令內容。編程
示例:app
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.go
。編程語言
自定義變量,示例:工具
APP=myapp build: clean go build -o ${APP} main.go clean: rm -rf ${APP}
上例中的定義了 target
目標有 build
和 clean
,若是當前目錄中正好有一個文件叫作 build
或 clean
,那麼其指令內容不會執行,這是由於 make 會把 target
視爲文件,只有當文件不存在或發生改變時纔會去執行命令。ui
爲了解決這個問題,咱們須要使用 PHONY
聲明 target
實際上是僞目標:this
APP=myapp .PHONY: build build: clean go build -o ${APP} main.go .PHONY: clean clean: rm -rf ${APP}
多個 PHONY 也能夠統一聲明在一行中:spa
.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 中執行的指令的輸出做爲變量:
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