GO&CGO的条件编译

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
    

    这个将限制此源文件只能在Linux/386或者darwin/386平台下编译

  • 关于注释的说明:

    编译标签和包的声明一定要用空行隔开,如下为***错误示范***

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

    下面这个才是正确示范:

    // +build !linux
    
    package main // <- it's right
    

    可以用go vet命令来检测这个缺少空行的错误

条件编译方式二:文件后缀
这个方法通过改变文件名的后缀来提供条件编译,这种方案比编译标签要简单, go/build可以在不读取源文件的情况下就可以决定哪些文件不需要参与编译
  • 文件命名约定:

    • 编译平台约束:源文件后缀包括:_$GOOS.go
    • 编译CPU架构约束:源文件后缀包括: _$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语句

在import "C"语句前的注释中可以通过#cgo语句设置编译阶段和链接阶段的相关参数。编译阶段的参数主要用于定义相关宏和指定头文件检索路径。链接阶段的参数主要是指定库文件检索路径和要链接的库文件

#cgo语句主要影响CFLAGSCPPFLAGSCXXFLAGSFFLAGSLDFLAGS几个编译器环境变量。LDFLAGS用于设置链接时的参数,除此之外的几个变量用于改变编译阶段的构建参数(CFLAGS用于针对C语言代码设置编译参数)

条件选择

#cgo指令还支持条件选择,当满足某个操作系统或某个CPU架构类型时后面的编译或链接选项生效。比如下面是分别针对windows和非windows下平台的编译和链接选项

// #cgo windows CFLAGS: -DX86=1
// #cgo !windows LDFLAGS: -lm
// #cgo amd64 CFLAGS: -lpthread
// #cgo arm64 CFLAGS: -lpng

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

如果在不同的系统下cgo对应着不同的c代码,我们可以先使用#cgo指令定义不同的C语言的宏,然后通过宏来区分不同的代码:

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))
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值