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

标签 go cross-compiling cgo

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

$ 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 看起来正确,除了 GOTOOLDIR - 我知道这是一个计算字段。
go-sqlite3 本身似乎可以正确交叉编译。
我已经用 golang 1.15 和 1.17.1 试过了。
主机操作系统是 Debian 11,gcc 10.2.1
两个问题:
  • 如何获得正确的 arm64 链接器?我想我也需要交叉编译这个?
  • 为什么交叉编译时 GOTOOLPATH 指向错误的位置,我该如何解决?
  • 最佳答案

    问题重现,并通过替换 -ldflags="-extld=$CC" 解决与 -ldflags="-extld=aarch64-linux-gnu-gcc" .
    或者,您也可以 export CC变量预先。
    错误输出是由不匹配的链接器引起的(使用您的原始构建命令,它仍然是被调用的 x86-64 链接器)。
    在我的两台主机上测试:一台 Ubuntu 20.04 + go1.13,另一台 Ubuntu 18.04 + go1.16。

    更多解释:
    好像在线CC env 变量设置传递给 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不产生任何输出。

    Inspired by Relocations in generic ELF (EM: 40)

    关于Golang 在交叉编译时无法在 x86_64 机器上链接 aarch64/arm64 二进制文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69144677/

    相关文章:

    windows - 如何将 uintptr 转换为 go struct

    golang udp客户端无法从服务器接收消息

    python - 在 Mac Os 中编译和链接 Python 模块

    go - 如何仅调用具有注释或标签的特定函数

    go - 在 Go 中将未转义的 HTML 解析为 HTML 模板

    python - 如何使用cgo在golang中导入cython生成的文件

    使用cmake对树莓派进行C交叉编译找不到头文件

    linux - 为 ARM 交叉编译 WebRTC

    macos - 不使用 cgo 或 SWIG 时不允许使用 C 源文件

    docker - undefined reference - 使用 Docker 构建 Golang CGO 失败,但在主机上失败