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
就是具體的指令內容。編程
示例: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.go
。app
自定義變量,示例:編程語言
APP=myapp
build: clean
go build -o ${APP} main.go
clean:
rm -rf ${APP}
複製代碼
上例中的定義了 target
目標有 build
和 clean
,若是當前目錄中正好有一個文件叫作 build
或 clean
,那麼其指令內容不會執行,這是由於 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 中執行的指令的輸出做爲變量:
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
複製代碼