osnosn

  博客园 :: 首页 :: 博问 :: 闪存 :: :: 联系 :: 订阅 订阅 :: 管理 ::

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 读写正常

其他

---end---


转载注明来源: 本文链接 https://www.cnblogs.com/osnosn/p/11749922.html 来自osnosn的博客.

posted on 2019-10-28 00:35  osnosn  阅读(3251)  评论(1编辑  收藏  举报