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