条件编译解决的是一份代码在不同编译平台和不同语言版本的兼容编译问题。

文件名后缀方式

go build 在不读取源文件的情况下可以通过文件名后缀来决定哪些文件参与编译。

后缀主要有以下几种形式

  • _$GOOS.go

  • _$GOARCH.go

  • $GOOS$GOARCH.go_

标签标注方式

通过在文件头增加条件编译标签可以提供更灵活的条件编译。

条件编译标签以 // +build 前缀开始,条件编译标签必须和普通的注释或代码通过空行进行分开,否则编译器无法识别。

条件编译标签类似这样

// +build linux,386 darwin,!cgo

语义为 (linux AND 386) OR (darwin AND (NOT cgo))
// +build linux darwin
// +build 386

语义为(linux OR darwin) AND 386

规则总结下来就是

空格 ' ' = OR
逗号 ',' = AND
感叹号 '!' = NOT
换行 = OR

具体的条件可以有

  • 操作系统,值可以通过 runtime.GOOS 获取

  • CPU 架构,值可以通过 runtime.GOARCH 获取

  • 编译器,如 gc,gccgo

  • 是否开启 cgo,cgo

  • 语言版本,Go 版本如 go1.1,go1.12

  • 自定义标签,可以是发布版本号,开发版本等。

build 时指定

Mac 下

# Linux
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go

# Win
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go

Linux 下

# Mac
SET CGO_ENABLED=0
SET GOOS=darwin
SET GOARCH=amd64
go build main.go

# Win
SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go build main.go

Win 下

需要写一个批处理程序,在里面去设置,因为windows 下的 terminal 不支持shell , 这跟 Mac 和 Linux下的有点不同

# Mac
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go

# Linux
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go

GOOS:目标平台的操作系统(darwin、freebsd、linux、windows)GOARCH:目标平台的体系架构(386、amd64、arm)交叉编译不支持 CGO 所以要禁用它。

GOOS 和 GOARCH 的值成对出现,而且只能是下面对应的值

$GOOS            $GOARCH
android            arm
darwin            386
darwin            amd64
darwin            arm
darwin            arm64
dragonfly   amd64
freebsd            386
freebsd            amd64
freebsd            arm
linux            386
linux            amd64
linux            arm
linux            arm64
linux            ppc64
linux            ppc64le
linux            mips
linux            mipsle
linux            mips64
linux            mips64le
linux            s390x
netbsd            386
netbsd            amd64
netbsd            arm
openbsd            386
openbsd            amd64
openbsd            arm
plan9            386
plan9            amd64
solaris            amd64
windows            386
windows            amd64

32 位程序就用 386 代替上面示例中的 amd64。

参考

[Go 编程: 交叉编译 vs 条件编译](Go 编程: 交叉编译 vs 条件编译)
Build Constraints