Linux 安裝 go 以及 arm linux 移植 go


背景

Go是一門全新的靜態類型開發語言,具有自動垃圾回收豐富的內置類型,函數多返回值錯誤處理匿名函數,並發編程反射等特性。

從Go1.4之后Go語言的編譯器完全由Go語言編寫,所以為了從源代碼編譯Go需要先編譯一個1.4版本的Go版本。

所以,搭建go語言開發環境(版本>1.4)只需要:
1)編譯go1.4版本,設置好GOROOT_BOOTSTRAP
2)然后再執行腳本編譯安裝GO1.4以上版本(任何支持的平台都可以)

注意,go的安裝/移植 比較奇怪,它是以 源碼包當前的路徑作為根目錄的,相當於prefix =PWD

有關資料: 【英文文檔】 Installing Go from source Go語言官方編譯指南 2019.02.27

開發環境介紹

  • 主機操作系統:Ubuntu18.04 64位
  • 目標平台:S5P6818(ARM-A53)
  • 交叉工具鏈:arm-none-linux-gnueabi-gcc,gcc7.3.0
  • Go版本:1.12 (https://github.com/golang/go/releases)
  • 編譯時間:2019.03.03

准備Go Bootstrap

編譯3個版本

#/** @file         make_go.sh
# *  @author       Schips
# *  @date         2020/09/15
# *  @version      v1.1
# *  @copyright    Copyright By Schips, All Rights Reserved
# *
# **********************************************************************************
# */
#!/bin/sh
BUILD_HOST=arm-eabi
BASE=`pwd`

ARM_GO_DIR=${BASE}/source/_arm_go
HIG_GO_DIR=${BASE}/source/_go_higher
BOOTSTRAP_DIR=${BASE}/source/_go_boot_strap

GOROOT_BOOTSTRAP=${BOOTSTRAP_DIR}/go

test_env() {
    CMD=$1
    command -v ${CMD} >/dev/null 2>&1 || { echo >&2 "Aborted : Require \"${CMD}\" but not found."; exit 1; }
}


CROSS_TOOL_DIR=`dirname \`whereis ${BUILD_HOST}-gcc | awk -F: '{ print $2 }'\``
if [ -z "$CROSS_TOOL_DIR" ]; then
    ARM_GCC_PATH=/home/schips/6818/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin
    echo "no found cross gcc, using ${ARM_GCC_PATH}"
    CROSS_TOOL_DIR=$ARM_GCC_PATH
fi

export PATH=$PATH:$CROSS_TOOL_DIR

test_env  ${BUILD_HOST}-gcc

make_dirs () {
    #為了方便管理,創建有關的目錄
    cd ${BASE} && mkdir compressed install source -p
}

tget () { #try wget
    filename=`basename $1`
    echo "Downloading [${filename}]..."
    if [ ! -f ${filename} ];then
        wget $1
    fi

    echo "[OK] Downloaded [${filename}] "
}

download_package () {
    cd ${BASE}/compressed

    tget https://dl.google.com/go/go1.4.3.src.tar.gz
    # 高版本
    tget https://dl.google.com/go/go1.13.8.src.tar.gz
}

tar_go_for_boot_stap () {
    cd ${BASE}/compressed

    mkdir ${BOOTSTRAP_DIR} -p
    tar -xf *go1.4* -C ${BOOTSTRAP_DIR}
}

make_go_for_boot_stap () {
    cd ${BOOTSTRAP_DIR}/go/src

    CGO_ENABLED=0 GOOS=linux GOARCH=amd64 ./make.bash
}

tar_go_version_higher_host () {
    cd ${BASE}/compressed
    HIGHER=`ls go* | grep -v 1.4 `

    mkdir ${HIG_GO_DIR} -p
    tar -xf $HIGHER -C ${HIG_GO_DIR}
}

make_go_version_higher_host() {
    export GOROOT_BOOTSTRAP=$GOROOT_BOOTSTRAP

    cd ${HIG_GO_DIR}/go/src
    GOOS=linux GOARCH=amd64 ./make.bash
}

tar_go_version_higher_arm () {
    cd ${BASE}/compressed
    HIGHER=`ls go* |grep -v 1.4 `
    mkdir ${ARM_GO_DIR} -p
    tar -xf $HIGHER -C ${ARM_GO_DIR}
}

make_go_version_higher_arm() {
    export GOROOT_BOOTSTRAP=$GOROOT_BOOTSTRAP

    cd ${ARM_GO_DIR}/go/src
    CGO="no"
    if [ $CGO = "yes" ]
    then
        echo "CGO is enable"
        # 開啟CGO編譯(參考下文)
        export  CC_FOR_TARGET=${CROSS_TOOL_DIR}/${BUILD_HOST}-gcc
        export CXX_FOR_TARGET=${CROSS_TOOL_DIR}/${BUILD_HOST}-g++
        CGO_ENABLED=1 GOOS=linux GOARCH=arm GOARM=7 ./make.bash
    else
        echo "CGO is disable"
        # 關閉CGO編譯
        CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 ./make.bash
    fi
}

show_config () {
    #echo "go bootstarp  is  : $GOROOT_BOOTSTRAP"
    echo "made go"
    tree ${BASE}/install/go_with_arm/bin
    echo "go bootstarp  is  : ${BASE}/install/go_boot_strap"
    echo " CC_FOR_TARGET is : ${CROSS_TOOL_DIR}/${BUILD_HOST}-gcc"
    echo "CXX_FOR_TARGET is : ${CROSS_TOOL_DIR}/${BUILD_HOST}-g++"

    # 關於下方的變量請參考有關文章
    GOROOT="${BASE}/install/go_with_arm"
    GOPATH=`dirname $GOROOT`/gopath
    echo "GOROOT is : ${GOROOT}"
    echo "GOPATH is : ${GOPATH}"
        echo "==========================================="
    echo "## for Run cmd-pc"
    echo "export GOROOT=${GOROOT}"
    echo "export GOPATH=${GOPATH}"
    echo "export PATH=\$PATH:\$GOROOT/bin:\$GOPATH/bin"
    echo
    echo "## for Next time bootstarp"
    echo "export GOROOT_BOOTSTRAP=${BASE}/install/go_boot_strap"
    echo "export    CC_FOR_TARGET=${CROSS_TOOL_DIR}${BUILD_HOST}-gcc"
    echo "export   CXX_FOR_TARGET=${CROSS_TOOL_DIR}/${BUILD_HOST}-g++"
    echo
    echo "## [Optional]"
        echo "alias arm-go=\"GOOS=linux GOARCH=arm GOARM=7 go build\""
        echo "alias gob=\"go build\""
    echo
    echo "## for Run cmd-target"
    echo "export GOROOT=${GOROOT}"
    echo "export GOPATH=${GOPATH}"
    echo "export PATH=\$PATH:\$GOROOT/bin:\$GOPATH/bin"
}

make_together () {
    #boot strap
    mv ${BOOTSTRAP_DIR}/go ${BASE}/install/go_boot_strap

    #higher_host(好像arm版本的編譯里面也自帶了本機可以用的go)
    #mv ${HIG_GO_DIR}/go  ${BASE}/install/go_host

    #higher_arm
    mv ${ARM_GO_DIR}/go ${BASE}/install/go_with_arm
    show_config
}


echo "Using ${BUILD_HOST}-gcc"
make_dirs
download_package

  tar_go_for_boot_stap
 make_go_for_boot_stap

#好像arm版本的編譯里面也帶了本機可以用的go,所以這2句腳本是不需要的
# tar_go_version_higher_host
#make_go_version_higher_host

 tar_go_version_higher_arm
 make_go_version_higher_arm

make_together

編譯完成以后,最后會提示應該如何配置環境變量(在下文中需要用到)

提示:當選擇開啟CGO編譯時必須配置先CC_FOR_TARGET和CXX_FOR_TARGET兩個環境變量
建議 高版本的go設置CGO=0;建議 arm版本的go 設置CGO=1。

腳本中編譯go的時候,用到了兩個變量:

  • GOOS:目標操作系統
  • GOARCH:目標操作系統的架構
OS ARCH OS version
linux 386 / amd64 / arm >= Linux 2.6
darwin 386 / amd64 OS X (Snow Leopard + Lion)
freebsd 386 / amd64 >= FreeBSD 7
windows 386 / amd64 >= Windows 2000

編譯其他平台的時候根據上面表格參數執行編譯就可以了。

    • $GOARM (for arm only; default is auto-detected if building on the target processor, 6 if not)

      This sets the ARM floating point co-processor architecture version the run-time should target. If you are compiling on the target system, its value will be auto-detected.

      • GOARM=5: use software floating point; when CPU doesn't have VFP co-processor
      • GOARM=6: use VFPv1 only; default if cross compiling; usually ARM11 or better cores (VFPv2 or better is also supported)
      • GOARM=7: use VFPv3; usually Cortex-A cores

If in doubt, leave this variable unset, and adjust it if required when you first run the Go executable. The GoARM page on the Go community wiki contains further details regarding Go's ARM support.

install/go_arm/目錄下會生成arm和amd64兩個平台的Go命令和依賴包,所以這個版本編譯的Go命令可以進行兩個平台的Go應用程序開發。

# schips @ ubuntu in ~/host/go/install/go_arm/bin [20:57:41]
$ tree
.
├── go(PC上正常使用的)
├── gofmt
└── linux_arm(這個目錄下的程序是在arm上運行的)
    ├── go
    └── gofmt

設置環境變量

在自己的bash中的對應資源文件(*rc)中添加如下內容(重啟命令行后生效)):

不同bash對應rc文件也不同,比如 .ashrc,.bashrc,.zshrc 等
關於 go有關的環境變量可以參考: 《GOROOT、GOPATH、GOBIN變量的含義》

# 設置 GOROOT_BOOTSTRAP是為了下次 編譯的時候可以用
export GOROOT_BOOTSTRAP=根據上面腳本的編譯結果
export CC_FOR_TARGET=根據上面腳本的編譯結果
export CXX_FOR_TARGET=根據上面腳本的編譯結果

# 一定需要的
export GOROOT=根據上面腳本的編譯結果
export GOPATH=可以參考根據上面腳本的編譯結果
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

# 可選的,快捷命令
alias arm-go="GOOS=linux GOARCH=arm GOARM=7 go build"
alias gob="go build"

例如:

Installed Go for linux/amd64 in /home/schips/go/source/_go_boot_strap/go
Installed commands in /home/schips/go/source/_go_boot_strap/go/bin
CGO is disable
Building Go cmd/dist using /home/schips/go/source/_go_boot_strap/go.
Building Go toolchain1 using /home/schips/go/source/_go_boot_strap/go.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for host, linux/amd64.
Building packages and commands for target, linux/arm.
---
Installed Go for linux/arm in /home/schips/go/source/_arm_go/go
Installed commands in /home/schips/go/source/_arm_go/go/bin

go bootstarp  is  : /home/schips/go/install/go_boot_strap
CC_FOR_TARGET  is : /home/schips/6818/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi-gcc
CXX_FOR_TARGET is : /home/schips/6818/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi-g++
GOROOT is : /home/schips/go/install/go_arm
GOPATH is : /home/schips/go/install/gopath # 沒錯,真的是這么寫的

測試

驗證go 是否正常運行 以及 輸出版本

新開一個bash,輸入 go version 可以進行安裝的簡單驗證:

$ go version

go version go1.12 linux/amd64

有關程序的驗證

新建helloworld.go

package main

import "fmt"

func main() {
  fmt.Println("Hello world")
}

編譯與運行
在本地運行的結果:

go build helloworld.go

./helloworld
Hello world

在板子上:

# 在 host 上交叉編譯
GOOS=linux GOARCH=arm GOARM=7 go build helloworld.go

[root@6818 ~/nfs]#./helloworld
Hello world


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM