内部构建机器都是 amd64 架构,项目大多数都没用 cgo,用了的几个都是 sqlite 这种长期稳定的,编译 arm64 的是下面的步骤:
FROM xxx/golang:xxx 带 gcc-aarch64-linux-gnu 的 amd64 golang 镜像 COPY ... RUN CC=aarch64-linux-gnu-gcc GOARCH=arm64 CGO_ENABLED=1 \ go build xxxx
前不久有个 odbc 的 cgo 项目,这样报错:
/usr/lib/gcc-cross/aarch64-linux-gnu/7/../../../../aarch64-linux-gnu/bin/ld.gold: error: cannot find -lodbc
<h2>解决过程</h2>
上面报错是因为 amd64 的镜像里安装 unixodbc-dev 的是 amd64 架构的,sqlite 没问题应该是它单元测试覆盖率很高了,而且安卓是 arm64 ,头文件里很多差异性估计用 #define 做 if else 了所以没问题。qemu go build hangs
FROM --platform=linux/arm64 xxx/golang:xxx RUN apt install -y unixodbc-dev COPY ... RUN GOARCH=arm64 CGO_ENABLED=1 \ go build xxxx
arm64 机器上编译是没问题的,但是我们构建机器都是 amd64 架构(centos 7,内核 419 版本)使用的 利用 qemu user 模式和 binfmt_misc 构建其他架构的 docker 镜像 ,时不时卡在 go build 上升级了 qemu 版本和 docker 版本,还是卡住,后面打算升级内核。
安装 arm64 lib
但是升级内核之前想了下,能不能在 amd64 里安装 arm64 的 odbc lib,然后传递 CGO_CFLAGS、CGO_LDFLAGS 指定 arm64 的 odbc path,最终搞出来了:
FROM --platform=linux/arm64 debian:buster-slim as deb RUN set -eux; \ if [ -e /etc/apt/sources.list ];then sed -ri 's/[a-zA-Z0-9.]+(debian.org|ubuntu.com)/mirrors.aliyun.com/g' /etc/apt/sources.list; fi; \ apt update; \ cd /tmp; \ apt download libodbc1 unixodbc-dev; \ mkdir -p /test/usr/local/lib_arm64 /test/usr/local/include_arm64; \ ls *.deb | while read deb;do dpkg-deb -x $deb /opt/; done; \ find /opt; \ find /opt/usr/lib/ -not -type d -exec cp -a {} /test/usr/local/lib_arm64 \; ; \ find /opt/usr/include/ -not -type d -exec cp -a {} /test/usr/local/include_arm64 \; ; \ ls -l /test/usr/local/lib_arm64 /test/usr/local/include_arm64 FROM scratch COPY --from=deb /test /odbc
上面镜像构建成 xxxxx/file/odbc:v1
FROM xxxxx/file/odbc:v1 as odbc FROM xxx/golang:xxx # apt install -y gcc-aarch64-linux-gnu 的 amd64 golang 镜像 COPY --from=odbc /odbc / RUN CC=aarch64-linux-gnu-gcc GOARCH=arm64 CGO_ENABLED=1 \ CGO_CFLAGS='-g -O2 -I/usr/local/include_arm64' \ CGO_LDFLAGS='-g -O2 -L/usr/local/lib_arm64 -lodbc' \ go build xxx
-g -O2 是默认的值,主要是后面的参数