GO条件编译

go build 参数
附加参数备注
-v编译时显示包名
-p n开启并发编译,默认情况下为CPU核数
-a强制重新构建所有的文件
-n打印编译时会用的所有命令,但不真正执行
-x打印编译时会用到的所有命令
-race开启竞态检测,支持linux/amd64,freebsd/amd64,darwin/amd64,windows/amd64
-work打印临时工作目录的名称
-o指定输出文件
-tags构建出带tag的版本
-gccgoflagsgccgo 编译/链接器参数(少用)
条件编译方式一:编译标签

在源码添加标注,通常称之为编译标签(build tag),编译标签是在尽量靠近源代码文件顶部的地方用注释的方式添加,如下所示:

// +build darwin freebsd netbsd openbsd

这个将会让这个源文件只能在支持kqueue的BSD系统中编译

// +build linux darwin
// +build 386
// +build !linux
package main // <- it's wrong
// +build !linux

package main // <- it's right
条件编译方式二:文件后缀
这个方法通过改变文件名的后缀来提供条件编译,这种方案比编译标签要简单, go/build可以在不读取源文件的情况下就可以决定哪些文件不需要参与编译
_$GOOS.go_$GOARCH.go_$GOOS_$GOARCH.go
编译标签和文件后缀的选择
  • 通常情况来讲,如果源文件与平台或者CPU架构完全匹配,那么用文件后缀
  • 相反,如果这个源文件可以在超过一个平台/CPU架构下使用,或者去除指定平台,那么使用编译标签

CGO条件编译

CGO也可以使用上述GO的条件编译方式来进行条件编译。这里只针对与对于跨平台情况下需要链接不同的库的注释写法:
条件链接依赖库

先来看一段正常的cgo代码:

// #cgo CFLAGS: -DPNG_DEBUG=1 -I./include
// #cgo LDFLAGS: -L/usr/local/lib -lpng
// #include <png.h>
import "C"
#cgo
#cgo
#cgoCFLAGSCPPFLAGSCXXFLAGSFFLAGSLDFLAGSLDFLAGSCFLAGS
条件选择
#cgo
// #cgo windows CFLAGS: -DX86=1
// #cgo !windows LDFLAGS: -lm
// #cgo amd64 CFLAGS: -lpthread
// #cgo arm64 CFLAGS: -lpng

如上就是在不同操作系统预定义宏,链接不同库的操作。

#cgo
package main

/*
#cgo windows CFLAGS: -DCGO_OS_WINDOWS=1
#cgo darwin CFLAGS: -DCGO_OS_DARWIN=1
#cgo linux CFLAGS: -DCGO_OS_LINUX=1

#if defined(CGO_OS_WINDOWS)
    const char* os = "windows";
#elif defined(CGO_OS_DARWIN)
    const char* os = "darwin";
#elif defined(CGO_OS_LINUX)
    const char* os = "linux";
#else
#    error(unknown os)
#endif
*/
import "C"

func main() {
    print(C.GoString(C.os))
}