Go build tag

Golang build tag

Go build tag 在 Golang 的源码中被大量使用,因为 Go 要适配各种各样的操作系统和架构,有时候我们做程序在不同操作系统的适配的时候也可以用 build tag,它有两种使用方式,我们一起来看下。

文件注释

Go 编译约束(build constraint),或者直接叫 build tag, 在 Go 文件中往往是以下面开头的一行:

// +build

它列出了文件被编译的时候是否能够被包含在 package 中的条件。这种约束可能在各种源文件中(不仅在 Go 文件中),但是它必须出现在文件的顶部附近,在空白行或者注释行前面, 当然也要在你声明的 package 语句前面。

为了能够从 package 的文档中区分开 build tag,需要在后面追加一空白行。

如果 build tag 是用 空格 分开的,那么他们之间是 的关系。 如果 build tag 是用 逗号 分开的,那么他们之间是 的关系。 如果 build tag 前面有 !, 则是 的意思。

Build tag 可以由字母、数字、下划线和点组成。下面是几个 build tag 的例子:

// +build linux,386 darwin,!cgo

它们相当于:

(linux AND 386) OR (darwin AND (NOT cgo))

一个文件可能会有多行 build tag。它们之前是 的关系。像下面这样:

// +build linux darwin
// +build amd64

它们相当于:

(linux OR darwin) AND amd64

在特定的构建过程中,它们可以对下面几中情况进行约束:

- 目标操作系统, 由 runtime.GOOS 指定, 可以通过 GOOS 环境变量设置。
- 目标架构, 由 runtime.GOARCH 指定,可以通过 GOARCH 环境变量设置。
- 使用的编译器, 使用 "gc" 或者 "gccgo",(小写的 gc 代表 go compiler)。
- "cgo", 如果 cgo 被支持 (在 'go help environment' 中查看 CGO_ENABLED)。
- Go 发布版本, 比如 "go1.1" 是从 go1.1 起。
- 其他通过 -tags 参数进行指定的额外参数 (请参看 'go help build').

Go Beta版本 或 minior 版本没有单独的构建标记,只能使用类似 go1.16 这样的在 major 版本号。

通过文件名

如果是通过文件名指定 build tag,那么去除扩展名和可能的 _test 后缀之后可能可以匹配到下面几种:

*_GOOS
*_GOARCH
*_GOOS_GOARCH

例如:source_windows_amd64.go,其中 GOOSGOARCH 表示任何已知的操作系统和体系结构值,该文件被认为具有隐式构建约束。

使用 GOOS=android 可以匹配和 GOOS=linux 一样 build tag 的文件,另外还可以匹配 android build tags 的文件。

使用 GOOS=illumos 可以匹配和 GOOS=solaris 一样 build tag 的文件,另外还可以匹配 illumos build tags 的文件。

使用 GOOS=ios 可以匹配和 GOOS=darwin 一样 build tag 的文件,另外还可以匹配 ios build tags 的文件.

为了避免该文件用于编译,你可以使用下面的语句忽略:

// +build ignore

在 Linux 或 OS X 系统上只用 cgo 编译该文件:

// +build linux,cgo darwin,cgo

有时候我们有一些其他系统的实现在另外一个文件中实现了, 这个时候我们可以使用:

// +build !linux,!darwin !cgo

以 dns_windows.go 只有在 Windows 系统构建时才会被使用; 同样的, math_386.s 只有在编译 32-bit x86 的 package 时才会被使用到。