ITPub博客

首页 > 数据库 > 数据库开发技术 > 使用 Makefile 构建指令集

使用 Makefile 构建指令集

原创 数据库开发技术 作者:凌虚 时间:2019-12-15 16:29:05 0 删除 编辑

使用 Makefile 构建指令集

make 是一个历史悠久的构建工具,通过配置 Makefile 文件就可以很方便的使用你自己自定义的各种指令集,且与具体的编程语言无关。例如配置如下的 Makefile :

  1. run dev:

  2. NODE_ENV=development nodemon server.js

这样当你在命令行执行 make run dev 时其实就会执行 NODE_ENV=development nodemon server.js 指令。

使用 Makefile 构建指令集可以很大的提升工作效率。

Makefile 基本语法

  1. <target>: <prerequisites>

  2. <commands>

target 其实就是执行的目标, prerequisites 是执行这条指令的前置条件, commands 就是具体的指令内容。

示例:

  1. build: clean

  2. go build -o myapp main.go


  3. clean:

  4. rm -rf myapp

这里的 build 有一个前置条件 clean ,意思就是当你执行 make build 时,会先执行 clean 的指令内容 rm-rf myapp ,然后再执行 build 的内容 go build-o myapp main.go 。

变量

自定义变量,示例:

  1. APP=myapp


  2. build: clean

  3. go build -o ${APP} main.go


  4. clean:

  5. rm -rf ${APP}

PHONY

上例中的定义了 target 目标有 build 和 clean ,如果当前目录中正好有一个文件叫做 build 或 clean,那么其指令内容不会执行,这是因为 make 会把 target 视为文件,只有当文件不存在或发生改变时才会去执行命令。

为了解决这个问题,我们需要使用 PHONY 声明 target 其实是伪目标:

  1. APP=myapp


  2. .PHONY: build

  3. build: clean

  4. go build -o ${APP} main.go


  5. .PHONY: clean

  6. clean:

  7. rm -rf ${APP}

多个 PHONY 也可以统一声明在一行中:

  1. .PHONY: build clean

递归的目标

假设我们的工程目录结构如下:

  1. ~/project


  2. ├── main.go

  3. ├── Makefile

  4. └── mymodule/

  5. ├── main.go

  6. └── Makefile

文件根目录下还有一个文件夹 mymodule,它可能是一个单独的模块,也需要打包构建,并且定义有自己的 Makefile :

  1. # ~/project/mymodule/Makefile


  2. APP=module


  3. build:

  4. go build -o ${APP} main.go

现在当你处于项目的根目录时,如何去执行 mymodule 子目录下定义的 Makefile 呢?

使用 cd 命令也可以,不过我们有其它的方式去解决这个问题:使用 -C 标志和特定的 ${MAKE} 变量。

修改项目根目录中的 Makefile 为:

  1. APP=myapp


  2. .PHONY: build

  3. build: clean

  4. go build -o ${APP} main.go


  5. .PHONY: clean

  6. clean:

  7. rm -rf ${APP}



  8. .PHONY: build-mymodule

  9. build-mymodule:

  10. ${MAKE} -C mymodule build

这样,当你执行 make build-mymodule 时,其将会自动切换到 mymodule 目录,并且执行 mymodule 目录下的 Makefile 中定义的 build 指令。

shell 输出作为变量

我们可以把 shell 中执行的指令的输出作为变量:

  1. V=$(shell go version)


  2. gv:

  3. echo ${V}

这里执行 make gv 就会先执行 go version 指令然后把输出的内容赋值给变量 V 。

判断语句

假设我们的指令依赖于环境变量 ENV ,我们可以使用一个前置条件去检查是否忘了输入 ENV :

  1. .PHONY: run

  2. run: check-env

  3. echo ${ENV}


  4. check-env:

  5. ifndef ENV

  6. $(error ENV not set, allowed values - `staging` or `production`)

  7. endif

这里当我们执行 make run 时,因为有前置条件 check-env 会先执行前置条件中的内容,指令内容是一个判断语句,判断 ENV 是否未定义,如果未定义,则会抛出一个错误,错误提示就是 error 后面的内容。

帮助提示

添加 help 帮助提示:

  1. .PHONY: build

  2. ## build: build the application

  3. build: clean

  4. @echo "Building..."

  5. @go build -o ${APP} main.go


  6. .PHONY: run

  7. ## run: runs go run main.go

  8. run:

  9. go run -race main.go


  10. .PHONY: clean

  11. ## clean: cleans the binary

  12. clean:

  13. @echo "Cleaning"

  14. @rm -rf ${APP}


  15. .PHONY: setup

  16. ## setup: setup go modules

  17. setup:

  18. @go mod init \

  19. && go mod tidy \

  20. && go mod vendor


  21. .PHONY: help

  22. ## help: prints this help message

  23. help:

  24. @echo "Usage: \n"

  25. @sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /'

这样当你执行 make help 时,就是打印如下的提示内容:

  1. Usage:


  2. build build the application

  3. run runs go run main.go

  4. clean cleans the binary

  5. setup setup go modules

  6. help prints this help message

参考资料

  • https://danishpraka.sh/2019/12/07/using-makefiles-for-go.html

  • http://www.ruanyifeng.com/blog/2015/02/make.html

  • https://www.gnu.org/software/make/manual/make.html



原文作者:系统架构师Go;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2017-03-30

  • 博文量
    154
  • 访问量
    63683