Go1.18 新特性:編譯后的二進制文件,將包含更多信息
大家好,我是煎魚。
我有一個朋友,,開開心心入職,想著施展拳腳,第一個任務就是對老舊的二進制文件進行研究。
他一看,這文件,不知道是編譯器用什么參數(shù),是怎么編譯出來的,環(huán)境不知道是什么,更不知道來自什么代碼分支?
這除了是項目流程上的問題外,Go 在這塊也有類似的小問題,處理起來比較麻煩。
背景
日常中很難從 Go 二進制文件中檢索元信息,要么是信息完全缺失,要么提取需要對二進制文件進行大量解析。
包含的元信息如下:
元信息 | 提取處 |
Go 構建版本 | 符號表,通過全局變量 ? |
構建信息,例如:模塊和版本 | 符號表,通過全局變量 ? |
編譯器選項,例如:構建模式、編譯器、gcflags、ldflags 等 | 無法獲取 |
用戶定義的自定義數(shù)據(jù),例如:應用程序版本等 | 需在編譯時設置全局字符串變量,才可以獲取 |
關注到編譯器選項,也就是參數(shù)等都是無法得知的,也就是會提高獲取如何編譯出來的難度。
新提案
Michael Obermüller 提出了一個新的提案《cmd/go: add compiler flags, relevant env vars to 'go version -m' output》用于解決上述問題。
在提案中想要的是 JSON 格式的結構輸出:
{
"version": "go1.13.4",
"compileropts": {
"compiler": "gc",
"mode": "pie",
"os": "linux",
...
},
"buildinfo": {
"path": "腦子進煎魚了",
"main": {
"path": "HelloWorld",
"version": "(devel)",
},
"deps": []
},
"user": {
"customkey": "customval",
...
}
}
Russ Cox 表示由于編譯信息已有既有格式,并且默認使用 JSON 只會讓二進制文件變得更大。好處少,沒必要,改為了選項化的支持。
新的 Go1.18 版本中,可以通過既有的:
go version -m
查看到提案所提到的信息。
例如:
$ gotip version
go version devel go1.18-eba0e866fa Mon Oct 18 22:56:07 2021 +0000 darwin/amd64
$ gotip build ./
$ gotip version -m ko
...
build compiler gc
build tags goexperiment.regabiwrappers,goexperiment.regabireflect,goexperiment.regabiargs
build CGO_ENABLED true
build CGO_CPPFLAGS
build CGO_CFLAGS
build CGO_CXXFLAGS
build CGO_LDFLAGS
build gitrevision 6447264ff8b5d48aff64000f81bb0847aefc7bac
build gituncommitted true
若需要輸出 JSON 格式,也可以通過指定 go version -json 達到一樣的效果。
在上面的輸出中,現(xiàn)有的編譯器選項等都會包含在內(nèi),能夠讓大家對整體編譯后的二進制文件溯源有一個更好的認知。
總結
在今天這篇文章中,給大家介紹了 Go1.18 的一個新的變化。
新版本中,編譯器選項/參數(shù)、相關環(huán)境變量等,將會包含在編譯后的二進制文件中,能夠更便于后人排查和查看信息。