Golang交叉编译
1. 编译环境
宿主开发平台为:
Linux wanhy-ubuntu 5.3.0-62-generic
#56~18.04.1-Ubuntu SMP Wed Jun 24 16:17:03 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
目标执行平台为:
Linux pilotx-du 4.14.98+gebeb3d5
#1 SMP PREEMPT Wed Aug 21 10:17:13 UTC 2019 aarch64 GNU/Linux
2. 常规编译
2.1 Go Build使用
2.1.1 GOOS变量
The operating system for which to compile code.
Examples are linux, darwin, windows, netbsd.
2.1.2 GOARCH变量
The architecture, or processor, for which to compile code.
Examples are amd64, 386, arm, ppc64.
2.2.3 GOARM变量
For GOARCH=arm, the ARM architecture for which to compile.
Valid values are 5, 6, 7.
2.2 编译设置
2.2.1 建立Makefile
文件,内容如下:
NAME=agent
OS=linux
#OS=windows
# ARCH=amd64
# ARCH=arm
ARCH=arm64
ARM=7
build:
GOOS=$(OS) GOARCH=$(ARCH) GOARM=$(ARM) go build -o $(NAME)_$(OS)_$(ARCH)_$(ARM) ./max_client.go
2.2.2 编译指令:
make build
2.2.3 特别注意:
默认按照这种方式,在linux下可以正常输出linux,window,mac的可执行程序,但输出的arm不能在arm车机上运行,需要使用下面的交叉编译设置。
2. 交叉编译
本例使用docker环境来进行交叉编译环境的搭建。
2.1 获取阿里云的软件源
镜像网址为:https://developer.aliyun.com/mirror/
点击进入:系统->Ubuntu目录
网址为:https://developer.aliyun.com/mirror/ubuntu?spm=a2c6h.13651102.0.0.3e221b111qDsJK
复制ubuntu 18.04(bionic) 配置如下
内容到/etc/apt/sources.list
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
2.2 获取Golang安装文件
获取网址为:https://gomirrors.org/
使用最新的Go1.14.4版本 : https://gomirrors.org/dl/go/go1.14.4.linux-amd64.tar.gz
2.3 Dockerfile
Dockerfile文件内容为:
FROM ubuntu:18.04
VOLUME /opt/go_docker/
WORKDIR /go_workspace
COPY ./src ./
COPY ./entry.sh ./
COPY sources.list /etc/apt/sources.list
ENTRYPOINT [ "sh", "./entry.sh" ]
2.3 entry.sh
echo "bash"
# 更新软件源ls
apt-get update
# 安装交叉编译库
apt install g++-aarch64-linux-gnu -y
apt install gcc-aarch64-linux-gnu -y
# 添加此选项可以避免一个go run时的一个错误,错误描述为:
# X509
apt install ssh -y
# 解压并安装golang
tar -xvf go1.14.4.linux-amd64.tar.gz -C /usr/local
export PATH=$PATH:/usr/local/go/bin
echo $PATH
# 设置golang为国内代理
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.io,direct
bash
2.4 src文件夹内容
.
├── build.sh
├── go1.14.4.linux-amd64.tar.gz #golang安装文件
├── go.mod # 使用 go mod init utils 生成
├── go.sum # go run max_client.go 自动创建
└── hello.go # 源代码文件
2.5 hello.go
package main
import (
"log"
"github.com/gorilla/websocket"
)
func main() {
go recv_message("ws://127.0.0.1:2303/maxcount")
for {
}
}
func recv_message(ws_url string) {
log.Println("Dial To:", ws_url)
conn, _, err := websocket.DefaultDialer.Dial(ws_url, nil)
if err != nil {
log.Fatal("Dial Error:", err)
}
defer conn.Close()
for {
message_type, message_data, err := conn.ReadMessage()
if err != nil {
log.Println("ReadMessage Error:", err)
break
}
log.Printf("Recv [%v] : [%s]", message_type, message_data)
break
}
}
2.6 build.sh
export CGO_ENABLED=1
export GOOS=linux
export GOARCH=arm64
export GOARM=7
export BINARY_NAME=agent
# export CC=/usr/bin/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc
# export CXX=/usr/bin/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-g++
export CC=/usr/bin/aarch64-linux-gnu-gcc
export CXX=/usr/bin/aarch64-linux-gnu-g++
go build -o ./bin/${BINARY_NAME}_${GOOS}_${GOARCH}_${GOARM} ./hello.go
2.6 运行指令
#进入docker环境后,执行
sh build.sh
#会在bin目录下创建 agent_linux_arm64_7文件
3 测试运行
为了测试编译的arm执行文件是否可以正确运行,需要搭建arm的docker运行环境,步骤如下:
3.1 在宿主机安装 qemu
sudo apt install qemu-user-static -y
3.2 建立Dockerfile
FROM arm64v8/ubuntu
VOLUME /opt/go_docker/
WORKDIR /go_workspace
COPY ./src ./
ENTRYPOINT [ "bash" ]
3.2 运行docker
sudo docker run -it --name service_test -v /usr/bin/qemu-aarch64-static:/usr/bin/qemu-aarch64-static service_test:v1.0
3.3 运行结果
2020/07/08 13:30:24 Dial To: ws://127.0.0.1:2303/maxcount
2020/07/08 13:30:24 Recv [1] : [1594186224]
4. 存在问题
其实里面还存在一个问题,但我仅仅在程序内
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello Golang")
}
编译出的程序是不能运行的,原因是编译出的程序为statically linked
,暂时还不能解决此问题。
(base) wanhy@wanhy-ubuntu:~/Project/backer777_github/go_workspace/test_docker_golang/test_build2/src$ file agent_linux_arm64_7
agent_linux_arm64_7: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, not stripped
(base) wanhy@wanhy-ubuntu:~/Project/backer777_github/go_workspace/test_docker_golang/test_build2/src$ file agent_linux_arm64_7_cc
agent_linux_arm64_7_cc: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, not stripped