GoLang不需要Rakefile/Makefile,是如何實現交叉編譯的?如在X86上生成MIPS的可執行。


Go有自己的assembler和linker, 能夠自己從源代碼一直做到最後機器碼。再加上整個toolchain都是用Go實現的可以到處移植,所以任何可以運行Go compiler的host machine都能輸出所有支持的架構的binary. 沒有準備特殊toolchain做交叉編譯的需要。

Assembler設計時就考慮到支持多架構,讓不同架構的彙編源碼格式相同,然後用簡單的碼錶就能輸出不同架構的機器碼。這其實就是Rob Pike在Gophercon 2016上的演講題目 https://talks.golang.org/2016/asm.slide ,看視頻評論似乎大部分人都沒聽懂或者把它跟LLVM的中間碼混淆了。

至於不同OS的支持,一是可執行文件的格式不同,這是linker最後一點小工作。 二是系統API, Go標準庫是self-contained的,甚至不依賴glibc, 大部分時候只需要實現特定系統的syscall和特有功能就可以了,這部分實現通常涉及彙編代碼,而Go的assembler又是跨平台的,於是事情就很簡單了。


通過自行設計的工具鏈、彙編器實現,不藉助外部工具。

1. GNU的auotools工具鏈其實是個特例,新語言並非一定要遵循GNU的模式。

2. 官方編譯器已經支持MIPS,不再需要gccgo了。

3. 當目標操作系統為Linux時,支持mips,mipsle,mips64,mips64le四種架構。

方法是設置環境變數,例如在bash下:

export GOOS=linux

export GOARCH=mips64

4. 具體支持的架構可以在文檔「Installing Go from source」中找到。
https://golang.org/doc/install/source

(段落「Optional environment variables」)


google go 用GOOS和GOARCH環境變數指定,但不支持MIPS

gccgo才支持MIPS


各種操作系統 都會提供 API (system call) 供程序調用

如Windows API , Linux syscall

glibc (gnu libc) 封裝了 這些 系統API,像 socket ,read ,write, accept, select, epoll_* 等

用gccgo 編譯器,會 通過調用 glibc中 封裝系統API的函數來 間接調用 系統API(system call)

而用普通的 gc 編譯器,會直接調用 系統API,不通過glibc,因此golang的程序,可以實現 純靜態,但 支持的系統有限,需要後續額外添加支持。

而glibc 已經支持 大多數系統API。


makefile這麼醜陋的東西了,沒有才是最好


推薦閱讀:

作為一名WEB工程師從長遠的角度來講 哪幾種語言 更值得深入學習?
如何理解 Golang 中「不要通過共享內存來通信,而應該通過通信來共享內存」?
為什麼 Go 語言如此不受待見?
Golang 里的fatal error怎麼處理?
golang里gc相關的write barrier(寫屏障)是個什麼樣的過程或者概念?

TAG:x86 | file | Go語言 | Makefile | make |