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

huangapple go评论93阅读模式
英文:

Golang fails to link an aarch64/arm64 binary on an x86_64 machine while cross compiling

问题

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

问题1:如何获取正确的arm64链接器?我猜我也需要交叉编译它?
问题2:为什么在交叉编译时GOTOOLPATH指向错误的位置,我该如何修复?

$ CC=aarch64-linux-gnu-gcc GOOS=linux GOARCH=arm64 CGO_ENABLED=1 go build -v -ldflags="-extld=$CC"
# github.com/mattn/go-sqlite3
sqlite3-binding.c: In function ‘sqlite3SelectNew’:
sqlite3-binding.c:125322:10: warning: function may return address of local variable [-Wreturn-local-addr]
125322 |   return pNew;
       |          ^~~~
sqlite3-binding.c:125282:10: note: declared here
125282 |   Select standin;
       |          ^~~~~~~
# github.com/joohoi/acme-dns
/usr/lib/go-1.15/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: error adding symbols: file in wrong format
collect2: error: ld returned 1 exit status
CC=aarch64-linux-gnu-gcc GOOS=linux GOARCH=arm64 CGO_ENABLED=1 go env
GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/home/voltagex/.cache/go-build"
GOENV="/home/voltagex/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/voltagex/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/voltagex/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/lib/go-1.15"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go-1.15/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="aarch64-linux-gnu-gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/btrfs/src/acme-dns/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build156138713=/tmp/go-build -gno-record-gcc-switches"

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

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

我已经尝试过golang 1.15和1.17.1。

主机操作系统是Debian 11,gcc 10.2.1。

英文:

I am trying to cross compile https://github.com/joohoi/acme-dns for an aarch64 machine on my x86_64 desktop.

$ CC=aarch64-linux-gnu-gcc GOOS=linux GOARCH=arm64 CGO_ENABLED=1 go build -v -ldflags="-extld=$CC"
# github.com/mattn/go-sqlite3
sqlite3-binding.c: In function ‘sqlite3SelectNew’:
sqlite3-binding.c:125322:10: warning: function may return address of local variable [-Wreturn-local-addr]
125322 |   return pNew;
       |          ^~~~
sqlite3-binding.c:125282:10: note: declared here
125282 |   Select standin;
       |          ^~~~~~~
# github.com/joohoi/acme-dns
/usr/lib/go-1.15/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: /tmp/go-link-266874795/go.o: error adding symbols: file in wrong format
collect2: error: ld returned 1 exit status
CC=aarch64-linux-gnu-gcc GOOS=linux GOARCH=arm64 CGO_ENABLED=1 go env
GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/home/voltagex/.cache/go-build"
GOENV="/home/voltagex/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/voltagex/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/voltagex/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/lib/go-1.15"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go-1.15/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="aarch64-linux-gnu-gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/btrfs/src/acme-dns/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build156138713=/tmp/go-build -gno-record-gcc-switches"

go env looks correct, except for GOTOOLDIR - I understand this is a calculated field.

go-sqlite3 itself seems to cross compile correctly.

I have tried this with golang 1.15 and 1.17.1.

Host OS is Debian 11, gcc 10.2.1

Two questions:

  1. How do I get the correct arm64 linker? I guess I'd need to cross compile this too?
  2. Why is GOTOOLPATH pointing to the wrong location while cross compiling and how do I fix this?

答案1

得分: 8

问题已经复现,并通过将-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

请注意第一个echo没有产生任何输出。

https://stackoverflow.com/questions/23185341/relocations-in-generic-elf-em-40 启发。

英文:

Problem reproduced, and resolved by replacing -ldflags="-extld=$CC" with -ldflags="-extld=aarch64-linux-gnu-gcc".

Alternatively, you can also export the CC variable beforehand.

The error output was caused by mismatching linker (with your original build command, it was still the x86-64 linker that got invoked).

Tested on two hosts of mine: one Ubuntu 20.04 + go1.13, the other Ubuntu 18.04 + go1.16.


More explanations:

Seems that the in-line CC env variable setting is passed to the go tool, but not used in the shell's parameter substitution. The following output (Bash 5.0) demonstrates this:

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

Note how the first echo does not produce any output.

> Inspired by https://stackoverflow.com/questions/23185341/relocations-in-generic-elf-em-40

huangapple
  • 本文由 发表于 2021年9月12日 00:09:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/69144677.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定