交叉编译时,Golang 无法在 x86_64 机器上链接 aarch64/arm64 二进制文件

Ada*_*ter 8 cross-compiling go cgo

我正在尝试为 x86_64 桌面上的 aarch64 机器交叉编译https://github.com/joohoi/acme-dns 。

\n
$ CC=aarch64-linux-gnu-gcc GOOS=linux GOARCH=arm64 CGO_ENABLED=1 go build -v -ldflags="-extld=$CC"\n# github.com/mattn/go-sqlite3\nsqlite3-binding.c: In function \xe2\x80\x98sqlite3SelectNew\xe2\x80\x99:\nsqlite3-binding.c:125322:10: warning: function may return address of local variable [-Wreturn-local-addr]\n125322 |   return pNew;\n       |          ^~~~\nsqlite3-binding.c:125282:10: note: declared here\n125282 |   Select standin;\n       |          ^~~~~~~\n# github.com/joohoi/acme-dns\n/usr/lib/go-1.15/pkg/tool/linux_amd64/link: running gcc failed: exit status 1\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)\n/usr/bin/ld: /tmp/go-link-266874795/go.o: error adding symbols: file in wrong format\ncollect2: error: ld returned 1 exit status\n
Run Code Online (Sandbox Code Playgroud)\n
CC=aarch64-linux-gnu-gcc GOOS=linux GOARCH=arm64 CGO_ENABLED=1 go env\nGO111MODULE=""\nGOARCH="arm64"\nGOBIN=""\nGOCACHE="/home/voltagex/.cache/go-build"\nGOENV="/home/voltagex/.config/go/env"\nGOEXE=""\nGOFLAGS=""\nGOHOSTARCH="amd64"\nGOHOSTOS="linux"\nGOINSECURE=""\nGOMODCACHE="/home/voltagex/go/pkg/mod"\nGONOPROXY=""\nGONOSUMDB=""\nGOOS="linux"\nGOPATH="/home/voltagex/go"\nGOPRIVATE=""\nGOPROXY="https://proxy.golang.org,direct"\nGOROOT="/usr/lib/go-1.15"\nGOSUMDB="sum.golang.org"\nGOTMPDIR=""\nGOTOOLDIR="/usr/lib/go-1.15/pkg/tool/linux_amd64"\nGCCGO="gccgo"\nAR="ar"\nCC="aarch64-linux-gnu-gcc"\nCXX="g++"\nCGO_ENABLED="1"\nGOMOD="/btrfs/src/acme-dns/go.mod"\nCGO_CFLAGS="-g -O2"\nCGO_CPPFLAGS=""\nCGO_CXXFLAGS="-g -O2"\nCGO_FFLAGS="-g -O2"\nCGO_LDFLAGS="-g -O2"\nPKG_CONFIG="pkg-config"\nGOGCCFLAGS="-fPIC -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build156138713=/tmp/go-build -gno-record-gcc-switches"\n
Run Code Online (Sandbox Code Playgroud)\n

go env 看起来正确,除了 GOTOOLDIR - 我知道这是一个计算字段。

\n

go-sqlite3 本身似乎可以正确交叉编译。

\n

我已经用 golang 1.15 和 1.17.1 尝试过这个。

\n

主机操作系统是 Debian 11、gcc 10.2.1

\n

两个问题:

\n
    \n
  1. 如何获得正确的arm64链接器?我想我也需要交叉编译这个?
  2. \n
  3. 为什么交叉编译时 GOTOOLPATH 指向错误的位置以及如何修复此问题?
  4. \n
\n

Cha*_*ian 9

问题重现,并通过替换为-ldflags="-extld=$CC"解决-ldflags="-extld=aarch64-linux-gnu-gcc"

或者,您也可以预先指定export变量CC

错误输出是由链接器不匹配引起的(使用原始构建命令,它仍然是调用的 x86-64 链接器)。

在我的两台主机上进行了测试:一台 Ubuntu 20.04 + go1.13,另一台 Ubuntu 18.04 + go1.16。


更多解释:

似乎内联CC环境变量设置已传递给go工具,但未在 shell 的参数替换中使用。以下输出 (Bash 5.0) 演示了这一点:

anna@LAPTOP-KV4759EJ:~/git/github.com/joohoi/acme-dns$ CC=123 echo $CC

anna@LAPTOP-KV4759EJ:~/git/github.com/joohoi/acme-dns$ export CC=123; echo $CC
123
Run Code Online (Sandbox Code Playgroud)

请注意第一个echo不会产生任何输出。

受到通用 ELF 中的重定位的启发(EM:40)