Attention
这里的构建过程没有考虑
Golang Build Cache
的影响
Golang 的构建过程是典型的静态编译语言的编译过程,分为编译(compile)和链接(link)两个阶段。
包源码被编译为 .o
文件之后,会被 pack
工具打包成为 .a
文件,生成的 .a
会被放入临时构建文件夹,之后被链接成为可执行文件。
标准库的构建过程
标准库的源码存放在 $GOROOT/src
下,标准库编译的 .a
文件存放在 $GOROOT/pkg/
下,构建时如果已经存在 .a
文件,则会直接链接 .a
文件,否则会从源文件中进行编译。如果想强制从标准库的源码进行重新编译,可以通过两种办法:
- 删除相应的
.a
的文件 - 使用
go build -a
参数,这会将所有的源码重新编译一边,所以构建时间可能很长
非标准库的构建过程
同标准库的构建过程不同,非标准库在构建的时候都会从源码进行构建。使用 go install
命令可以将包的 .a
文件安装到 $GOPATH/pkg/
下,但在构建过程中会重新编译源码到 .a
,重新编译的文件会被放入构建的临时目录,临时目录的下的 .a
优先级会高于 $GOPATH/pkg/
中的 .a
。
程序构建过程
以下面结构的项目的为例,编译是使用命令 go build -x -v
输出详细构建日志:
$tree -F demo1
demo1
├── cmd/
│ └── app1/
│ └── main.go
└── pkg/
└── pkg1/
└── pkg1.go
程序 app1
的构建过程可分为下面几步:
- 建立临时工作目录,放入环境变量
WORK
,之后的工作都已$WORK
为当前目录 - 编译
app1
的依赖包pkg1
,将目标文件打包放入$WORK/<demo1_pkg_path>/pkg/pkg1.a
- 编译
app1
的 main 包, 将目标文件打包后放入$WORK/<demo1_pkg_path>/cmd/app1.a
- 链接器将
app1.a
,pkg1.a
链接成为$WORK/<demo1_pkg_path>/cmd/app1/_obj/exe/a.out
- 将
a.out
复制到go build
命令执行目录,并改名为app1