golang源码分析-编译(二)
本文主要介绍golang编译脚本的构建过程
接下来主要分析go1.4编译脚本的主要内容
首先来看go1.4编译脚本,$GOROOT_BOOTSTRAP/src/make.bash
114 echo '# Building C bootstrap tool.'
115 echo cmd/dist
116 export GOROOT="$(cd .. && pwd)"
117 GOROOT_FINAL="${GOROOT_FINAL:-$GOROOT}"
118 DEFGOROOT='-DGOROOT_FINAL="'"$GOROOT_FINAL"'"'
119
120 mflag=""
121 case "$GOHOSTARCH" in
122 386) mflag=-m32;;
123 amd64) mflag=-m64;;
124 esac
125 if [ "$(uname)" == "Darwin" ]; then
126 # golang.org/issue/5261
127 mflag="$mflag -mmacosx-version-min=10.6"
128 fi
129 # if gcc does not exist and $CC is not set, try clang if available.
130 if [ -z "$CC" -a -z "$(type -t gcc)" -a -n "$(type -t clang)" ]; then
131 export CC=clang CXX=clang++
132 fi
133 ${CC:-gcc} $mflag -O2 -Wall -Werror -o cmd/dist/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
这段代码最终生成一条编译指令,如下
gcc -m64 -O2 -Wall -Werror -o cmd/dist/dist -Icmd/dist -DGOROOT_FINAL="$GOROOT_FINAL" cmd/dist/*.c
通过gcc编译后生成二进制可执行程序$GOROOT_BOOTSTRAP/src/cmd/dist/dist
# 通过上一步生成的dist工具构建go_bootstrap
159 ./cmd/dist/dist bootstrap $buildall $GO_DISTFLAGS -v # builds go_bootstrap
# 通过go_bootstrap安装go及相关工具
175 CC=$CC_FOR_TARGET "$GOTOOLDIR"/go_bootstrap install $GO_FLAGS -ccflags "$GO_CCFLAGS" -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
以上代码主要是通过dist生成go_bootstrap,然后通过go_bootstrap安装高版本的go及对应的工具
接下来详细分析下dist工具源码,源码文件如下:
$GOROOT_BOOTSTRAP/src/cmd/dist
├── a.h
├── arg.h
├── arm.c
├── buf.c
├── build.c
├── buildgc.c
├── buildgo.c
├── buildruntime.c
├── main.c
├── plan9.c
├── README
├── unix.c
└── windows.c
plan9.c,unix.c,windows.c分别为不同移植平台的入口文件;main.c为可移植的入口文件;build.c,buildgc.c及buildruntime.c分别对应dist工具的核心功能;a.h定义了两个核心的数据结构Buf(字节缓冲区)及Vec(字符串切片),buf.c主要实现两种核心数据结构的相关操作
Buf及Vec的数据结构定义如下
// A Buf is a byte buffer, like Go's []byte.
typedef struct Buf Buf;
struct Buf
{
char *p;
int len;
int cap;
};
// A Vec is a string vector, like Go's []string.
typedef struct Vec Vec;
struct Vec
{
char **p;
int len;
int cap;
};
我们采用centos系统中的gcc进行源码编译,因此移植平台的入口文件是unix.c
main函数主要职责
1、初始化GO相关全局变量(goroot,goarch等)
2、调用可移植入口文件main.c的函数xmain
xmain的主要功能是根据dist工具获取子命令参数,执行相应的函数功能
static struct {
char *name;
void (*f)(int, char**);
} cmdtab[] = {
{"banner", cmdbanner},
{"bootstrap", cmdbootstrap},
{"clean", cmdclean},
{"env", cmdenv},
{"install", cmdinstall},
{"version", cmdversion},
};
dist工具的子命令包含
banner(显示安装相关信息)
bootstrap(生成go_bootstrap)
clean(清理编译过程中生成的文件及目录)
env(显示环境变量)
install(安装相关目录对应的库,包及二进制可执行工具)
version(dist的版本)
函数cmdbootstrap主要负责生成go_bootstrap,具体实现在build.c文件中
cmdbootstrap函数主要按照buildorder顺序调用install函数进行编译,buildorder主要包含依赖的c函数库,编译器及包依赖
install函数主要功能如下
1、构建gcc编译lib9,libbio,liblink c库指令,生成.o中间文件
2、构建gcc编译6a(amd64架构汇编编译器),6c(amd64架构c语言编译器),6g(amd64架构go语言编译器),6l(amd64架构链接器)指令,生成.o中间文件
3、通过6a,6c,6g编译生成中间文件,通过6l链接中间文件生成二进制可执行文件go_bootstrap
go_bootstrap工具的源码在$GOROOT_BOOTSTRAP/src/cmd/go目录下,下一节主要分析通过go_bootstrap工具安装go标准库,自定义库及相关工具的源码