使用 Golang 已经有一阵了,在 Golang 的开发过程中,我已经习惯于不断重复地手动执行 go buildgo test 这两个命令. 不过,现在我已经摆脱了这个习惯。如果只用到了不带参数的简单命令,直接这么操作可能并不可怕。但是在一些复杂的任务中,如果依旧是手动执行 go buildgo test ,就可能会成为一个让人头疼的事情。

我们可以通过其他方式解决这个问题。比如,可以用一个 bash 脚本来完成这些工作,或者一个更好的选择(至少对于我来说)是,写一个 makefile. make 这个工具生来就是为了做这些事情,在 makefile 中我们可以将所有常见的任务都放在一起。我并不是一个 makefile 专家,所以可能不太能够教大家如何写一个好的 makefile. 但是在本文,我将向大家展示我所使用的 Makefile,我的大部分项目都使用了这些 makefile 。让我们开始吧:

# Go parameters
GOCMD=go
GOBUILD=$(GOCMD) build
GOCLEAN=$(GOCMD) clean
GOTEST=$(GOCMD) test
GOGET=$(GOCMD) get
BINARY_NAME=mybinary
BINARY_UNIX=$(BINARY_NAME)_unixall: test build
build:$(GOBUILD) -o $(BINARY_NAME) -v
test:$(GOTEST) -v ./...
clean:$(GOCLEAN)rm -f $(BINARY_NAME)rm -f $(BINARY_UNIX)
run:$(GOBUILD) -o $(BINARY_NAME) -v ./..../$(BINARY_NAME)
deps:$(GOGET) github.com/markbates/goth$(GOGET) github.com/markbates/pop# Cross compilation
build-linux:CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOBUILD) -o $(BINARY_UNIX) -v
docker-build:docker run --rm -it -v "$(GOPATH)":/go -w /go/src/bitbucket.org/rsohlich/makepost golang:latest go build -o "$(BINARY_UNIX)" -v

我比较喜欢 DRY(Don't Repeat Yourself) 原则。所以,在 makefile
的开头定义常用的命令和变量,我们可以在后面方便地对定义的命令和变量进行引用。

# Basic go commands
GOCMD=go
GOBUILD=$(GOCMD) build
GOCLEAN=$(GOCMD) clean
GOTEST=$(GOCMD) test
GOGET=$(GOCMD) get# Binary names
BINARY_NAME=mybinary
BINARY_UNIX=$(BINARY_NAME)_unix

: 前面的叫做 makefile 的目标,比如 build:, build 就是一个目标。如果在执行 make 命令时指定目标,比如 make run,那么 make 就会构建该目标。如果没有提供任何参数,那么 make 默认会执行第一个目标。在我们的示例中,也就是叫 all 的目标会被构建。

$ make run ## call specific task
$ make     ## make tool calls "all" task

基本命令

makefile 最关键的部分就是构建。当 make 进行执行时,定义的变量会被展开,$(GOBUILD) 会被展开为 go build, make 实际就会执行 go build 命令。生成的二进制文件被命名为 -o $(BINARY_NAME). 另外,我发现使用 -v 参数切换到 verbose mode 非常有用。在 verbose mode 中,你可以看到当前正在构建的包。

build:$(GOBUILD) -o $(BINARY_NAME) -v ## expands to: "go build -o mybinary -v"

因为我们大部分人都很懒,所以就有了一个叫做 run 的目标。run 会构建二进制文件,并且在 build 完成后执行这个二进制文件。

run:$(GOBUILD) -o $(BINARY_NAME) -v ./..../$(BINARY_NAME)

通常来讲,test 命令应该是 makefile 的一部分。我个人总是喜欢使用 verbose mode 来更好地 debug 和观测 test 的运行。

test:$(GOTEST) -v ./...

如果项目使用 CI(Continuous Integration)/CD(Continuous Delivery), 哪怕仅仅是为了一致性,将一系列依赖维护在包里面也是一个非常好的做法。这可以通过 deps 目标来完成,它会通过 go get 命令获取所有相关的依赖。

deps:$(GOGET) github.com/markbates/goth$(GOGET) github.com/markbates/pop

clean 来结束这一节的内容。rm -f 命令被用来移除名为
$(BINARY_XXX) 的二进制文件。

clean:$(GOCLEAN)rm -f $(BINARY_NAME)rm -f $(BINARY_UNIX)

交叉编译命令

如果项目开发是在一个系统上,而需要在另一个系统上运行,那么在 makefile 中包含一个交叉编译的命令是非常方便的。我通常在容器的 Linux 平台上运行二进制,所以 makefile 包含了 Linux 构建。

build-linux:CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOBUILD) -o $(BINARY_UNIX) -v

如果你的代码使用了 C binding,你可能会遇到一些问题。CGO 的问题在于你需要一个与给定平台兼容的 gcc. 如果开发在 OSX/Windows 上完成,那么你需要有一个能够兼容 Linux 的 gcc. 至少对我来说,在 OSX 上使用配置 gcc 交叉编译 C 代码并不容易。如果需要 CGO, docker 镜像是创建 Linux 构建的最好方式。这种方式唯一的要求就是必须安装 Docker。

docker-build:docker run --rm -it -v "$(GOPATH)":/go -w /go/src/bitbucket.org/rsohlich/makepost golang:latest go build -o "$(BINARY_UNIX)" -v

本文的 Makefile 示例可在 这里 找到。

作者:liuchengxu
链接:https://www.jianshu.com/p/88163922edd1
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

go使用makefile相关推荐

  1. 浅显易懂 Makefile 入门 (12)— Makefile 常见的错误信息

    1. 常见的错误信息 make 执行过程中所产生错误并不都是致命的,特别是在命令行之前存在 -.或者 make 使用 -k 选项执行时. make 执行过程的致命错误都带有前缀字符串 ***.错误信息 ...

  2. 浅显易懂 Makefile 入门 (10)— 嵌套执行 make、export 的使用

    1. 嵌套执行 make 在一个大的工程文件中,不同的文件按照功能被划分到不同的模块中,每个模块可能都会有自己的编译顺序和规则,如果在一个 Makefile 文件中描述所有模块的编译规则,就会很乱,执 ...

  3. 浅显易懂 Makefile 入门 (09)— include 文件包含、MAKECMDGOALS

    1. include文件包含 当 make 读取到 include 关键字的时候,会暂停读取当前的 Makefile,而是去读 include 包含的文件,读取结束后再继读取当前的 Makefile ...

  4. 浅显易懂 Makefile 入门 (08)— 默认 shell (/bin/sh)、命令回显、make参数(-n 只显示命令但不执行,-s 禁止所有回显)、单行命令、多行命令、并发执行

    1. shell 相关 1.1 默认 shell Makefile 所使用的命令是由 shell 命令行组成,他们是一条一条执行的. 多个命令之间要使用分号隔开,Makefile 中的任何命令都要以 ...

  5. 浅显易懂 Makefile 入门 (07)— 其它函数(foreach 、if、call、origin )

    1. foreach 函数 foreach 函数定义如下: $(foreach <var>,<list>,<text>) 函数的功能是:把参数 <list&g ...

  6. 浅显易懂 Makefile 入门 (06)— 文件名操作函数(dir、notdir、suffix、basename、addsuffix、addperfix、join、wildcard)

    编写 Makefile 的时候,很多情况下需要对文件名进行操作.例如获取文件的路径,去除文件的路径,取出文件前缀或后缀等等. 注意:下面的每个函数的参数字符串都会被当作或是一个系列的文件名来看待. 1 ...

  7. 浅显易懂 Makefile 入门 (03)— 目标文件搜索(VPATH 和 vpath 的区别和使用)、隐含规则

    1. 目标文件搜索(VPATH和vpath) 如果需要的文件是存在于不同的路径下(即源文件与 Makefile 文件不在同一个路径下),在编译的时候就用到了 Makefile 中为我们提供的目录搜索文 ...

  8. 浅显易懂 Makefile 入门 (02)— 普通变量和自动变量定义、使用($@、$^、$< 作用)、变量覆盖 override、变量的来源 origin

    1. 变量的定义 Makefile 文件中定义变量的基本语法如下: 变量的名称=值列表 变量的名称可以由大小写字母.阿拉伯数字和下划线构成.等号左右的空白符没有明确的要求,因为在执行 make 的时候 ...

  9. 浅显易懂 Makefile 入门 (01)— 什么是Makefile、为什么要用Makefile、Makefile规则、Makefile流程如何实现增量编译

    1. 什么是 Makefile Makefile 文件描述了 Linux 系统下 C/C++ 工程的编译规则,它用来自动化编译 C/C++ 项目.一旦写编写好 Makefile 文件,只需要一个 ma ...

  10. Android 的NDK的Makefile编写

    Android.mk 是google根据Linux GNU Makefile精简编译脚本.具体来说:这就是GNU Makefile的一小部分. 举一个简单例子: LOCAL_PATH := $(cal ...

最新文章

  1. 京东员工因两年一毛钱没涨而离职,618后跳槽涨薪翻倍
  2. 基于GAN模型的生成人脸重构、返老还童、看见前世今生(Age Progression/Regression)
  3. ISE和Modelsim联合仿真
  4. Redhat9五笔输入法安装
  5. java 计算协方差_Java的深度:通过协方差暴露的API泄漏
  6. java继承父类执行顺序_java中子类继承父类程序执行顺序问题
  7. Windows下启动Apache报错:ServerRoot must be a valid directory
  8. UGUI Scrollbar控件
  9. 【python】52周存钱法功能改进
  10. 物联网和工业物联网有什么区别?
  11. 笔记本CPU正常温度是多少?
  12. VBA金额转换中文大写(原创新解版)
  13. 码云 注册 注册个性域名报错---已经解决
  14. Java多线程篇--原子包、阻塞队列和并行流
  15. 撩人飙新意,美汁源首次转战“AR微电影”,要你变身当“导演”
  16. 流氓软件和骚扰电话是时候该清理下了
  17. iPhone6 和 iPhone 6 plus的适配
  18. vue VNode如何使用,是什么东西?
  19. 头歌实训平台C语言答案
  20. Pyinstaller打包exe附带图片的方法

热门文章

  1. python canny算法_Python 实现 Canny 边缘检测算法
  2. 底部显示水平滚动_LG专利展示带有可滚动显示屏和触控笔的智能手机
  3. python dataframe排序_python – Pandas DataFrame排序忽略了这种情况
  4. AI技术人才成长路线十大方向
  5. 如何建立DB2分区数据库?(转)
  6. hibernate - Transaction not successfully started
  7. 策略→需求→建模→规划→执行
  8. Excel组件使用配置文档下载
  9. LeetCode(557)——反转字符串中的单词 III(JavaScript)
  10. HTML、CSS、JS对unicode编码字符的规则