提纲:
1,go与C的交叉编译
2,项目的跨平台编译
只说我的实现:
1,go与C的交叉编译
go项目嵌入C,编译使用cgo(https://github.com/golang/go/wiki/cgo#global-functions),动态链接的方式比较复杂,本来C部分还有C++,为使用方便,我要求C工程师把C++部分使用C实现,这里多说一句,有时碰到问题,不要一上来就埋头干,看能不能通过沟通解决或降低一定的复杂性,有些东西,前端实现起来很简单,后台实现起来很麻烦;也有些东西,前端实现很复杂,后台实现很简单,要多沟通,哪一端实现简单,就让哪一端去实现。go嵌入C,可以把C代码写到go代码文件里,也可以把C文件(.c/.h)独立出来,为了以后更好维护,我采用的是把C文件独立出来:
hello.h文件
void world();
hello.c文件
#include hello.h
void world(){
printf("hello world...");
}
go文件
package main
/*
include "hello.h"
*/
import C
func main(){
C.world()
}
这里比较关键的是import C与上面的(注释的)include,之间不能有空格。
不能使用go run,直接使用go run不能编译通过,使用go build编译成二进制文件,然后运行二进制文件,就OK了。
如果go调用的C有指针和数组这些操作,可以参考http://ju.outofmemory.cn/entry/337861,基本上实现起来不是很复杂。
2,跨平台编译
我自己的电脑是mac,服务器的系统是centos,所以我需要跨平台编译。因为我使用了beego框架,所以使用bee工具进行打包,
报错了,一个第一次碰到的错误,build constraints,很底层的样子,我想起我项目中有C,嗯,加上CGO_ENABLED=1,应该就OK了吧,于是我重新打包,又报错了
NND,好像这次的错误更底层,我想会不会是bee工具的问题,我就用go build打包吧,还报错
go build和bee打包,错误差不多,束手无策了。
找解决方案,百度、google都没有现成的方案,各种尝试,有些答案说需要安装xcode和xcode commond line,都不行,直到后来看到了xgo(https://github.com/karalabe/xgo),我觉得,这个应该能解决我的问题。
使用xgo需要先安装docker,还好我之前有使用过docker,对docker不陌生。docker最简单的描述就是:一个占资源很少的虚拟机,它NB在可以帮你下载软件,安装环境(变量),部署。详细介绍可以百度。
mac下安装docker
https://docs.docker.com/docker-for-mac/install/,安装好了以后,右上方会有小海豚的图标。
然后安装xgo docker镜像(mac 命令行下):
docker pull karalabe/xgo-lates
若下载镜像慢,可以参考https://www.jianshu.com/p/2137a0e22b40和https://blog.youkuaiyun.com/small_to_large/article/details/77334973。
然后安装xgo
go get github.com/karalabe/xgo
测试xgo交叉编译环境是否OK:
$ cd $GOPATH/src // If you have multiple (I have at least 3 in there), change into any, doesn't matter
$ mkdir xgo_test
$ cd xgo_test
$ echo -e 'package main\n import "fmt"\n func main(){\nfmt.Println("Hello")\n}' > main.go
$ xgo .
执行完上述命令后在当前目录查看是否有编译生成的可执行文件,需要注意的是文件夹(xgo_test)需要在$GOPATH/src下。
使用xgo编译自己的项目
cd 到项目目录下,使用命令:
xgo --targets=linux/amd64 .
需要注意的是,自己的项目同样需要放到$GOPATH/src下。
xgo的命令、用法、功能很多,我只是结合自己遇到的问题,做了这个笔记;感兴趣的,可以去详细的了解xgo。