原由

在 Golang 的开发过程中,我们习惯于不断重复地手动执行 go buildgo test 这两个命令。但是在一些复杂的任务中,如果依旧是手动执行 go buildgo test ,就可能会成为一个让人头疼的事情。

我们可以通过其他方式解决这个问题。比如,可以用一个 bash 脚本来完成这些工作。但更好的选择是,写一个 makefile.。make 这个工具生来就是为了做这些事情,在 makefile 中我们可以将所有常见的任务都放在一起。

这样能够将makefile文件放在git记录中,方便多人协作和共享。毕竟大型项目有很多依赖关系,build或者测试更加复杂。

平常很多时候都是直接在命令行输入go build进行编译的

1
go build .

或者测试使用go run运行项目

1
go run main.go

大型开源项目都是如下方式

1
2
3
make build

make install

我们打包运行这个过程,还有一个更加贴切的词语叫做构建项目。

Makefile介绍

Makefile 是和 make 命令一起配合使用的。它是开源的构建工具,很多大型项目的编译都是通过 Makefile 来组织的。

1
2
3
4
BINARY_NAME=hello
build:
go build -o $(BINARY_NAME) -v
./$(BINARY_NAME)

解释下上面各行的意思:

  • 第一行,声明了一个变量BINARY_NAME他的值是hello,方便后面使用
  • 第二行,声明一个 target,其实你可以理解成一个对外的方法
  • 第三行,这就是这个target被调用时执行的脚本,这行就是build这个项目,编译后的二进制文件放在当前工程目录下,名字是变量BINARY_NAME的值
  • 第四行,这一行就是直接执行当前目录下的二进制文件

注意:

第三行,第四行前面一定要用tab键缩进,否者会报下面的错:

1
Makefile:3: *** missing separator.  Stop.

Demo

在公司项目中,常常是这样使用的。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
IMAGE=hello
TAG=$(shell git describe --always --tags)
REGISTRY=registry.cn-shenzhen.aliyuncs.com/螃蟹壳

all:
docker build -t ${REGISTRY}/${IMAGE}:${TAG} .

push: all
docker push ${REGISTRY}/${IMAGE}:${TAG}

publish: push
docker tag ${REGISTRY}/${IMAGE}:${TAG} ${REGISTRY}/${IMAGE}:latest
docker push ${REGISTRY}/${IMAGE}:latest

builder:
docker build -t go-builder:latest . -f builder.dockerfile
docker push go-builder:latest

test:
gotest -v ./... || go test -v ./...

lint:
ls -l | grep '^d' | awk '{print $$NF}' | grep -v vender | xargs golint

count:
cloc --progress=1 ./ --exclude-dir=vendor,doc,pb

pb:
mkdir -p pb && protoc -Iprotos $^ --go_out=plugins=grpc:pb

pb/%.pb.go: protos/%.proto
mkdir -p pb && protoc -Iprotos $^ --go_out=plugins=grpc:pb

.PHONY: test pb stages

使用

1
2
3
4
5
6
7
8
9
10
11
# 编译
make all

# push
make push

# grpc文件生成
make pb

# test
make test

还可以结合多重构建方式](http://www.pangxieke.com/linux/docker-auto-multi-build.html),更加规范的构建项目