Go 編譯過程分析(一) -- 編譯指令碼

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

    go 語言最近很火,與時俱進,我也看了看go 的文法。

    看起來 go 還是不錯的,有很多新的feature。 就下載了代碼研究了一下。

    go 的 src 目錄下面存在三套編譯檔案:

  1. window 平台, 所有 bat 檔案
  2. plan9 平台,所有 rc 檔案
  3. unix 類平台,所有bash 檔案

     以 unix 編譯檔案為例, go 的編譯入口時在 src/all.bash , 這是一個bash 腳步, 這個腳步只是簡單的調用了 make.bash 在腳步結束之後,調用 dist banner 輸出編譯的資訊。 

set -eif [ ! -f make.bash ]; then        echo 'all.bash must be run from $GOROOT/src' 1>&2        exit 1fiOLDPATH="$PATH". ./make.bash "$@" --no-bannerbash run.bash --no-rebuildPATH="$OLDPATH"$GOTOOLDIR/dist banner  # print build info

    dist 是在 make.bash 中產生的一個可執行檔,go 的所有編譯都是在這個檔案的控制下完成的。 個人認為這並不是一個好的設計,導致維護編譯系統的成功過高,如果要修改一下編譯選項,往往要修改 dist 原始碼。dist 的代碼在目錄: /src/cmd/dist 下。

  dist 這個命令列程式支援如下幾個參數:   

   "banner         print installation banner\n" ; 列印安裝的一些資訊   "bootstrap      rebuild everything\n"        ; 重新編譯所有的 go 代碼   "clean          deletes all built files\n"   ; 清楚編譯的 go 代碼   "env [-p]       print environment (-p: include $PATH)\n"  ; 列印編譯的環境   "install [dir]  install individual directory\n"  ;安裝某一個目錄。會編譯目錄下代碼,安裝組建檔案   "version        print Go version\n"              ;大約go版本資訊

  想要研究編譯細節一定要看看這個程式的代碼,後續詳細分析。

  make.bash, 同樣是一個 bash 腳步,開啟這個腳步,可以看到這個腳步主要做了如下幾件事情:

  1. 根據不同的系統,以及參數進行一些初始化的工作
  2. 編譯產生 dist,調用dist 完成整個go 的編譯. dist bootstrap
  3. 用編譯產生的 go_bootstrap 完成整個安裝過程

    很遺憾,這個script 不支援 window。 window 下調用 make.bat 去完成編譯。  go 的編譯系統不能很好的支援cygwin, 這是讓人覺得很不爽的地方。其實整個go 的編譯應該建立在Makefile 機制上,而修改go 的編譯指令碼,讓整個原始碼不依賴於dist 去完成整個編譯的過程,是讓go 很好的支援各種不同平台的好的入手點。

    有一些環境變數和 make.bash 結合的很緊密,也控制了編譯的一些選項:

  1. GOROOT_FINAL :  這個變數用來表明 go 最終安裝的路徑,如果不設定,預設值為當前原始碼的路徑
  2. GOHOSTARCH :   設定編譯 go 語音的電腦的 ARCH(架構) , 386 or amd64 or arm
  3. GOARCH : 編譯產生的 go 所啟動並執行 ARCH。
  4. GOOS : 編譯產生的 go 所允許的作業系統
  5. GO_GCFLAGS: 編譯 5g/6g/8g 時,額外指定的參數
  6. GO_LDFLAGS : 編譯 5l/6l/8l 時, 額外指定的參數
  7. GO_CCFLAGS  :  編譯 5c/6c/8c 時,額外指定的參數
  8. CGO_ENABLED:   是否支援 cgo,設定為1 的話,cgo 相關檔案會被編譯,設定為0 的話,則不會編譯
  9. GO_EXTLINK_ENABLED : 是否使用Host 環境的 link。設定1的話,則會使用編譯環境中帶的連接器,0,在不會
  10. CC : 設定C編譯器名字, gcc 還是 clang , 這個設定的是 host 環境的編譯器
  11. CC_FOR_TARGET : 設定C編譯器名字,這個設定的是 能夠產生目標環境代碼的編譯器
  12. CXX_FOR_TARGET: 設定CXX編譯器名字, g++ or clang++這個設定的是 能夠產生目標環境代碼的編譯器
  13. GO_DISTFLAGS :  為 dist bootstrap 提供額外的參數.

   make.bash 的一些分析:

    判斷 run.bash 是否存在,不存在,則提示,退出

if [ ! -f run.bash ]; then        echo 'make.bash must be run from $GOROOT/src' 1>&2        exit 1fi

     判斷當前是否在cygwin 或者 mingw ,或者其他window 環境下運行。 這裡吧 cygwin 簡單的划到window 的環境,是不合適的

case "$(uname)" in*MINGW* | *WIN32* | *CYGWIN*)       echo 'ERROR: Do not use make.bash to build on Windows.'       echo 'Use make.bat instead.'       echo       exit 1       ;;esac
  如果當前是 Darwin 系統,則在編譯選項中加入設定最小 macos 版本的條件

if [ "$(uname)" == "Darwin" ]; then        # golang.org/issue/5261        mflag="$mflag -mmacosx-version-min=10.6"fi
如果CC 沒有設定,並且 gcc 在host 環境上沒有, clang 確是在host 環境上存在,則設定編譯器 為 clang

# if gcc does not exist and $CC is not set, try clang if available.if [ -z "$CC" -a -z "$(type -t gcc)" -a -n "$(type -t clang)" ]; then        export CC=clang CXX=clang++fi

編譯產生 dist 程式,判斷是否編譯成功

${CC:-gcc} $mflag -O2 -Wall -o cmd/dist/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c# -e doesn't propagate out of eval, so check success by hand.eval $(./cmd/dist/dist env -p || echo FAIL=true)if [ "$FAIL" = true ]; then        exit 1fi
如果呼叫指令碼的時候,傳遞如參數 "--dist--tool" ,那麼意味著僅僅編譯dist,那麼產生disk 之後,安裝dist,然後退出

if [ "$1" = "--dist-tool" ]; then        # Stop after building dist tool.        mkdir -p "$GOTOOLDIR"        if [ "$2" != "" ]; then                cp cmd/dist/dist "$2"        fi        mv cmd/dist/dist "$GOTOOLDIR"/dist        exit 0fi
否則,就重新編譯所以的代碼,編譯 go_bootstrap,通過執行命令 dist bootstrap

echo "# Building compilers and Go bootstrap tool for host, $GOHOSTOS/$GOHOSTARCH."buildall="-a"if [ "$1" = "--no-clean" ]; then        buildall=""        shiftfi./cmd/dist/dist bootstrap $buildall $GO_DISTFLAGS -v # builds go_bootstrap

用 go_bootstrap 完成整個編譯過程

if [ "$GOHOSTARCH" != "$GOARCH" -o "$GOHOSTOS" != "$GOOS" ]; then        echo "# Building packages and commands for host, $GOHOSTOS/$GOHOSTARCH."        # CC_FOR_TARGET is recorded as the default compiler for the go tool. When building for the host, however,        # use the host compiler, CC, from `cmd/dist/dist env` instead.        CC=$CC GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH \                "$GOTOOLDIR"/go_bootstrap install -ccflags "$GO_CCFLAGS" -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std        echofiecho "# Building packages and commands for $GOOS/$GOARCH."CC=$CC_FOR_TARGET "$GOTOOLDIR"/go_bootstrap install $GO_FLAGS -ccflags "$GO_CCFLAGS" -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v stdecho

  

   

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.