# 4. Go 程序是如何编译的?
实例程序:
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
运行:
go build -n . #不实际编译,只输出编译过程
输出:
# 1. 创建工作目录
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg << 'EOF' # internal
# 2. 引入相关依赖
packagefile fmt=/usr/local/opt/go/libexec/pkg/darwin_amd64/fmt.a
packagefile runtime=/usr/local/opt/go/libexec/pkg/darwin_amd64/runtime.a
EOF
# 3. 进入项目目录并编译成一堆 .a 文件
cd /Users/hedonwang/GolandProjects/go-advance
/usr/local/opt/go/libexec/pkg/tool/darwin_amd64/compile -o $WORK/b001/_pkg_.a -trimpath "$WORK/b001=>" -p main -lang=go1.18 -complete -buildid qTV5GO9_7bKkS0N7SO2j/qTV5GO9_7bKkS0N7SO2j -goversion go1.18.5 -c=4 -nolocalimports -importcfg $WORK/b001/importcfg -pack ./main.go
/usr/local/opt/go/libexec/pkg/tool/darwin_amd64/buildid -w $WORK/b001/_pkg_.a # internal
cat >$WORK/b001/importcfg.link << 'EOF' # internal
# 编译产物是一堆 .a 文件(机器码中间件)
packagefile go-advance=$WORK/b001/_pkg_.a
....
packagefile path=/usr/local/opt/go/libexec/pkg/darwin_amd64/path.a
modinfo "0w\xaf\f\x92t\b\x02A\xe1\xc1\a\xe6\xd6\x18\xe6path\tgo-advance\nmod\tgo-advance\t(devel)\t\nbuild\t-compiler=gc\nbuild\tCGO_ENABLED=1\nbuild\tCGO_CFLAGS=\nbuild\tCGO_CPPFLAGS=\nbuild\tCGO_CXXFLAGS=\nbuild\tCGO_LDFLAGS=\nbuild\tGOARCH=amd64\nbuild\tGOOS=darwin\nbuild\tGOAMD64=v1\n\xf92C1\x86\x18 r\x00\x82B\x10A\x16\xd8\xf2"
EOF
mkdir -p $WORK/b001/exe/
cd .
# 4. 将所有 .a 文件链接成一个可执行文件 a.out,最后会对它进行重命名,默认为应用名(本例子中为 go-advance)
/usr/local/opt/go/libexec/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -buildmode=exe -buildid=JcVORsNHChlDnsHiGpRn/qTV5GO9_7bKkS0N7SO2j/qTV5GO9_7bKkS0N7SO2j/JcVORsNHChlDnsHiGpRn -extld=clang $WORK/b001/_pkg_.a
/usr/local/opt/go/libexec/pkg/tool/darwin_amd64/buildid -w $WORK/b001/exe/a.out # internal
mv $WORK/b001/exe/a.out go-advance
总结:
如何查看生成的 SSA 码?
编译前:
- windows:$env:GOSSAFUNC="指定函数"
- unix: export GOSSAFUNC=指定函数
如何查看生成的 Plan9 汇编代码?
- go build -gcflags -S main.go