Aaffo 原创

2 minute read

背景

由于最近需要用到Gmail api进行邮件相关操作,客户端库选择了go语言版本,目标环境是Arm cortexa9hf开发板 (姑且这么叫他吧,硬件结构啥的不太懂),所以现在要将go编译成开发板支持的共享库供c++调用。

PC端测试共享库

OK,当前环境 GOOS=linux GOARCH=amd64,先在PC上简单测试下,测试代码如下:

//test.go
package main

import "C"
import "fmt"

//export hello
func hello() {
	fmt.Println("hello world")
}

//export add
func add(a, b int) int {
	return a + b
}
func main() {
}

这里注意cgo函数导出要有//export + (function name) 的注释在函数上一行。然后我们使用以下命令开始编译:

go build -o libtest.so -buildmode=c-shared test.go

这步没什么问题,接下来随便写个c++代码:

#include <iostream>
#include "libtest.h"
using namespace std;

int main() {
    cout << "Hello World!" << endl;
    cout << add(1,2) <<endl;
    hello();
    return 0;
}

执行以下,报错了噢:

error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory

貌似找不到库,这是因为在默认查找路径找不到这个库,需要设置下LD_LIBRARY_PATH指向刚才编译出来库的位置, 刚才命令会编译到test.go同目录下

export LD_LIBRARY_PATH="/path/to/libtest.so"

再跑以下,这下可以了

Hello World!
3
hello world

编译Arm端共享库

试下刚才的库能不能给arm应用直接用,用arm环境build,报错了:

cgo-gcc-export-header-prolog:25: error: size of array '_check_for_64_bit_pointer_matching_GoInt' is negative

果然不行,那么开始交叉编译,用go应用那一套加上前面的编译命令试一下

GOARCH="arm" GOOS="linux" go build -o libtest.so -buildmode=c-shared test.go

error:  go: no Go source files

咋回事呢,这就要面向谷歌编程了,在这里找到方法

CGO_ENABLED=1 GOARCH="arm" GOOS="linux" go build -o libtest.so -buildmode=c-shared test.go

# runtime/cgo
gcc: error: unrecognized command line option '-marm'; did you mean '-mabm'?

go env 查看一下,明明CGO_ENABLED="1”,为什么加上这个就可以编译了,这个目前不清楚。

然后可以看到这里报错信息变了,继续

还需要指定gcc编译器,不能用当前环境的gcc了

export CC="/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc"
CGO_ENABLED=1 GOARCH="arm" GOOS="linux" go build -o libtest.so -buildmode=c-shared test.go

# runtime/cgo
_cgo_export.c:3:20: fatal error: stdlib.h: No such file or directory
compilation terminated.

看来是库和头也要加上

export CGO_CFLAGS="-g -O2 --sysroot=/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa9hf-neon-poky-linux-gnueabi"
export CGO_LDFLAGS="--sysroot=/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa9hf-neon-poky-linux-gnueabi"

# runtime/cgo
In file included from /opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa9hf-neon-poky-linux-gnueabi/usr/include/features.h:392:0,
                 from /opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa9hf-neon-poky-linux-gnueabi/usr/include/stdlib.h:24,
                 from _cgo_export.c:3:
/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa9hf-neon-poky-linux-gnueabi/usr/include/gnu/stubs.h:7:29: fatal error: gnu/stubs-soft.h: No such file or directory
compilation terminated.

这里涉及的好像有点远了,跟着做吧, 给编译器设置参数”-mfloat-abi=hard”,‘hard’不行可以换成‘soft’、‘softfp’试下。

export CC="/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc -mfloat-abi=hard"

此时环境应该是这样的,‘xx'代表user name噢

GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/xx/.cache/go-build"
GOENV="/home/xx/.config/go/env"
GOEXE=""
GOFLAGS=" -mod="
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/xx/GoApplications"
GOPRIVATE=""
GOPROXY="https://goproxy.cn"
GOROOT="/home/xx/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/xx/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/xx/GoApplications/src/testcode/go.mod"
CGO_CFLAGS="-g -O2 --sysroot=/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa9hf-neon-poky-linux-gnueabi"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="--sysroot=/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa9hf-neon-poky-linux-gnueabi"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-mfloat-abi=hard -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build083164815=/tmp/go-build -gno-record-gcc-switches"

继续编译

$ CGO_ENABLED=1 GOARCH="arm" GOOS="linux" go build -o libtest.so -buildmode=c-shared test.go
$ 

没有消息就是最好的消息,此时库已经编译成功了,别忘了把库放进目标机器噢

comments powered by Disqus