zoukankan      html  css  js  c++  java
  • Golang交叉编译

    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    # 源代码文件
    
    
    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
    
    
    
    
  • 相关阅读:
    【shell脚本】批量修改扩展名===modifyExtension.sh
    【shell脚本】打印九九乘法表
    【shell脚本】显示进度条
    【Linux命令】Linux压缩及解压命令
    【Linux命令】ulimit设置最大文件打开数
    【mysql】修改mysql数据库密码
    【raid级别】RAID级别工作模式
    MyBatis之#{} and ${}
    MyBatis之foreach
    强制修改常量的值
  • 原文地址:https://www.cnblogs.com/jobgeo/p/13266429.html
Copyright © 2011-2022 走看看