我愿做你的欢喜套路你的一生 發表於 2019-10-28 00:35:00

CentOS7_Debian中_带sqlite3_CGO的golang程序_交叉编译_arm_win_mips

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