CentOS7_Debian中_带sqlite3_CGO的golang程序_交叉编译_arm_win_mips
转载注明来源: 本文链接 来自osnosn的博客,写于 2019-10-28.
编写了个golang程序,用到了这个CGO库github.com/mattn/go-sqlite3
,用来支持sqlite3。
在x86_64机器中编译运行都ok。另有一台arm机器,装了armbian。
想在x86_64机器中交叉编译到arm64,碰到了一些问题。
经过摸索,似乎解决了。写下笔记给后来人参考。
环境:
- x86_64机器,装的是centos7,64位的。
- arm机器,aarch64-Linux-5.0.2-aml-s905, little_endian,装的armbian,64位的。
尝试用go直接交叉编译
- 用
CGO_ENABLED=1 GOOS=linux GOARCH=arm GOARM=7 go build -v -ldflags "-w -s" -o arm-mygofile mygofile.go
交叉编译失败。 - 用
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -v -ldflags "-w -s" -o arm-mygofile mygofile.go
交叉编译成功,但执行时发现sqlite3库没有加载。
golang在没有CGO时,直接可以交叉编译。有CGO就不行了。
尝试用arm的gcc
- 在centos7中安装,
yum install gcc-arm-linux-gnu
- 用
CGO_ENABLED=1 GOOS=linux GOARCH=arm GOARM=7 CC=arm-linux-gnu-gcc go build -v -ldflags "-w -s" -o arm-mygofile mygofile.go
交叉编译失败。说stdlib.h找不到。
从 arm-linux-gnu-gcc -v
中找到 sysroot目录的位置。我看到的是 /usr/arm-linux-gnu/sys-root/
, 目录为空。
从 yum search 中,也没找到对应的包。看来只能手工去下载编译用的head文件和库文件。
尝试交叉编译 arm 执行文件(32bit)
- 之前已经安装
yum install gcc-arm-linux-gnu
- 去
https://releases.linaro.org/components/toolchain/binaries/
找latest-7
- 下载
arm-linux-gnueabi/sysroot-glibc-linaro-2.25-2019.02-arm-linux-gnueabi.tar.xz
- 自己找个目录, 解压
tar Jxvf sysroot-glibc-linaro-2.25-2019.02-arm-linux-gnueabi.tar.xz
build时,指定 sysroot 的位置。
- 用
CGO_ENABLED=1 GOOS=linux GOARCH=arm GOARM=7 CC=arm-linux-gnu-gcc CGO_CFLAGS="-g -O2 --sysroot=/..../sysroot-glibc-linaro-2.25-2019.02-arm-linux-gnueabi/" CGO_LDFLAGS="-g -O2 --sysroot=/..../sysroot-glibc-linaro-2.25-2019.02-arm-linux-gnueabi/" go build -v -ldflags "-w -s" -o arm-mygofile mygofile.go
编译成功。
但copy到armbian后,无法执行(动态库ld-linux.so找不到)。似乎是32位的动态库没找到。
尝试加上 -static 参数。使用静态链接。
- 用
CGO_ENABLED=1 GOOS=linux GOARCH=arm GOARM=7 CC=arm-linux-gnu-gcc CGO_CFLAGS="-g -O2 --sysroot=/..../sysroot-glibc-linaro-2.25-2019.02-arm-linux-gnueabi/" CGO_LDFLAGS="-g -O2 --sysroot=/..../sysroot-glibc-linaro-2.25-2019.02-arm-linux-gnueabi/ -static" go build -v -ldflags "-w -s" -o arm-mygofile mygofile.go
编译成功(有错误警告,说sqlite3使用了glibc动态库)。
copy到armbian后,执行正常。执行文件是32位静态链接的。
---似乎成功了---
用 armeb-linux-gnueabihf
中的 sysroot-glibc-linaro....-armlinux-gnueabihf.tar.xz
文件 应该也可以。听说64位的arm,默认就是带hf的。
我没有尝试。
s905,好像是armv8的。估计用 armv8l-linux-gnueabihf
也行。我也没尝试。
交叉编译 aarch64 执行文件(64bit)
- 在centos7中安装,
yum install gcc-aarch64-linux-gnu
- 去
https://releases.linaro.org/components/toolchain/binaries/
找latest-7
- 下载
aarch64-linux-gnu/sysroot-glibc-linaro-2.25-2019.02-aarch64-linux-gnu.tar.xz
- 自己找个目录, 解压
tar Jxvf sysroot-glibc-linaro-2.25-2019.02-aarch64-linux-gnu.tar.xz
build时,指定 sysroot 的位置。
- 用
CGO_ENABLED=1 GOOS=linux GOARCH=arm64 CC="aarch64-linux-gnu-gcc" CGO_CFLAGS="-g -O2 --sysroot=/..../sysroot-glibc-linaro-2.25-2019.02-aarch64-linux-gnu/" CGO_LDFLAGS="-g -O2 --sysroot=/..../sysroot-glibc-linaro-2.25-2019.02-aarch64-linux-gnu/" go build -v -ldflags "-w -s" -o arm-mygofile mygofile.go
编译成功。
copy到armbian后,执行正常。执行文件是64位动态链接的。
---成功了---
直接在armbian中用arm的golang build得到的执行文件,也是64位动态链接的。但体积要小些。比交叉编译的小几百KB。不知道为什么。
- 在debian11中,只需装
apt install gcc-aarch64-linux-gnu
- 用
CGO_ENABLED=1 GOOS=linux GOARCH=arm64 CC="aarch64-linux-gnu-gcc" go build -v -ldflags "-w -s" -o arm-mygofile mygofile.go
就可以编译成功了。
debian10中,带go-sqlite3包的golang程序,交叉编译到win64
- 参考【golang交叉编译:Linux - Windows】
- 因为要开启 CGO 所以用 linux的gcc 是不能编译win的exe。
apt install gcc-mingw-w64
, 然后指定用 mingw 的 gcc 编译器, 交叉编译。- 32bit exe:
CGO_ENABLED=1 GOOS=windows GOARCH=386 CC=i686-w64-mingw32-gcc go build -v myfile.go
或者
64bit exe:CGO_ENABLED=1 GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc go build -v myfile.go
- 成功交叉编译出 exe 文件。
- 注意: i686-gcc 不能编译 amd64, x86_64-gcc 不能编译 386.
go 编译静态链接文件
- go 生成的本来就应该是静态链接的。如果不是,应该用了别的库。
- 没用CGO,只有网络操作,这个命令也能生成静态链接。
go build -tags netgo -ldflags "-w -s" -o test_run ./test.go
看命令go help buildconstraint
,不过没提到缺省的tags有些什么。 - 再不行,试试这个。
go build -ldflags "-w -s -linkmode external -extldflags=-static" -o test_run ./test.go
- 如果使用了 CGO,试试这个。
CGO_LDFLAGS="-g -O2 -static" go build -tags netgo -ldflags "-w -s" -o test_run ./test.go
debian11中,无CGO的golang程序,交叉编译到mipsel
静态链接,32bit,给 mt7620/mt7621 使用。(写于2022-8月)。
CGO_ENABLED=0 GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -ldflags "-w -s" -o mipsel-test ./test.go
- 成功。
debian11中,带go-sqlite3包的golang程序,交叉编译到mipsel
在 mt7620/mt7621 的 openwrt 中使用。(写于2023-2月)。
apt install gcc-mipsel-linux-gnu
CGO_ENABLED=1 GOOS=linux GOARCH=mipsle CC=mipsel-linux-gnu-gcc go build -ldflags "-w -s" -o mipsel-test ./test.go
- 编译通过,执行时出现
Illegal instruction
,看【解决GO语言编译程序在openwrt(mipsle架构)上运行提示Illegal instruction问题】。 CGO_ENABLED=1 GOOS=linux GOARCH=mipsle GOMIPS=softfloat CC=mipsel-linux-gnu-gcc go build -ldflags "-w -s" -o mipsel-test ./test.go
编译报错gnu/stubs-o32_soft.h: No such file or directory
。网上搜索,说是 glibc没有加入softfloat的支持。
放弃 !-
利用 openwrt 官方的SDK。
- 下载对应版本,cpu架构的 SDK,例如op-22.03.3, mt7621,
是【openwrt-sdk-22.03.3-ramips-mt7621_gcc-11.2.0_musl.Linux-x86_64.tar.xz】。
解压出来。 -
编译通过,但有警告export STAGING_DIR=/path-to-SDK.../staging_dir CGO_ENABLED=1 GOOS=linux GOARCH=mipsle GOMIPS=softfloat CC=/path-to-SDK.../staging_dir/toolchain-mipsel_24kc_gcc-11.2.0_musl/bin/mipsel-openwrt-linux-musl-gcc go build -ldflags "-w -s" -o mipsel-test ./test.go
environment variable 'STAGING_DIR' not defined
,这个环境变量的定义,无论写在什么位置,都不解决问题。
程序是动态链接的musl库,执行成功,网络操作正常,sqlite3 读写正常。 -
编译通过,也有警告,CGO_ENABLED=1 GOOS=linux GOARCH=mipsle GOMIPS=softfloat CC=/path-to.../staging_dir/toolchain-mipsel_24kc_gcc-11.2.0_musl/bin/mipsel-openwrt-linux-musl-gcc CGO_LDFLAGS="-g -O2 -static" go build -ldflags "-w -s" -o mipsel-test ./test.go
'STAGING_DIR' not defined
。
程序是静态链接的,执行成功,网络操作正常,sqlite3 读写正常。
- 下载对应版本,cpu架构的 SDK,例如op-22.03.3, mt7621,
其他
---end---
转载注明来源: 本文链接 https://www.cnblogs.com/osnosn/p/11749922.html 来自osnosn的博客.