前言
最近公司项目里是要对go做linux环境下的交叉编译,虽然自己部署的时候只需要./configure,make, make install之类的命令就能完成操作,但是还是想弄明白makefile的语法,因此抽空学习下makefile机制,目标是能读懂并且写出项目的makefile规则
Makefile基本结构
- 变量定义,通常为了输入和修改更方便
例如
GOROOT ?= /usr/local/go
- 伪目标,.PHONY关键字,认为目标并非是文件的形式,会跳过它的隐含规则搜索,直接执行命令,这就相当于定义了一条命令,因此每次执行都会重新执行一遍。一般修饰clean,确保每次运行都会clean一遍。
例如
.PHONY: clean
- 规则
格式
target: dependencies
system command
target是目标名,dependencies是依赖文件,system command是系统指令,一般是对应语言的编译指令或链接指令,而且命令前要有tab占位符(这个有遇到一个比较坑的问题是idea里直接tab发现不行,字符数不对,需要用文本编辑器里tab才ok)。默认情况下,target是生成文件的形式,每次执行make会根据依赖文件是否比target文件更新来决定是否要重新执行指令;而如果是all或者phony修饰的情况就可能完全是命令的形式。
例如
all: Microsoft
.PHONY: all
Microsoft:
mkdir -p disk/Microsoft
go build -o dist/Microsoft/Microsoft03 Microsoft/Microsoft03/Microsoft03.go
这里先利用all指定了最终目标,然后phony指定了all伪目标,然后定义了Microsoft规则,这里也是非文件类型目标,它没有依赖,默认运行make会执行make all。如果依赖里加上对应go文件,即使没有修改文件代码,每次执行都会重新build,而去掉all定义后,就不会这样,原因未知。
基本的语法就这三类,简单使用足矣。
特殊情况的处理
- 交叉编译
- 同时编译多个main文件
示例如下,
GOROOT ?= /usr/local/go
.PHONY:clean
all: linux
linux:
mkdir -p dist/linux
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOROOT)/bin/go build -ldflags="-s -w" -mod=vendor -o dist/linux/Microsoft Microsoft/Microsoft03/Microsoft03.go
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOROOT)/bin/go build -ldflags="-s -w" -mod=vendor -o dist/linux/Alibaba Alibaba/BornPig/babyPig.go
arm:
mkdir -p dist/arm
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 $(GOROOT)/bin/go build -ldflags="-s -w" -mod=vendor -o dist/arm/Microsoft Microsoft/Microsoft03/Microsoft03.go
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 $(GOROOT)/bin/go build -ldflags="-s -w" -mod=vendor -o dist/arm/Alibaba Alibaba/BornPig/babyPig.go
clean:
rm -rf dist