http://blog.csdn.net/free2o/article/details/38417293
go 语言最近很火,与时俱进,我也看了看go 的语法。
看起来 go 还是不错的,有很多新的feature。 就下载了代码研究了一下。
go 的 src 目录下面存在三套编译文件:
- window 平台, 所有 bat 文件
- plan9 平台,所有 rc 文件
- unix 类平台,所有bash 文件
以 unix 编译文件为例, go 的编译入口时在 src/all.bash , 这是一个bash 脚步, 这个脚步只是简单的调用了 make.bash 在脚步结束之后,调用 dist banner 输出编译的信息。
- set -e
- if [ ! -f make.bash ]; then
- echo 'all.bash must be run from $GOROOT/src' 1>&2
- exit 1
- fi
- OLDPATH="$PATH"
- . ./make.bash "$@" --no-banner
- bash run.bash --no-rebuild
- PATH="$OLDPATH"
- $GOTOOLDIR/dist banner # print build info
dist 是在 make.bash 中生成的一个可执行文件,go 的所有编译都是在这个文件的控制下完成的。 个人认为这并不是一个好的设计,导致维护编译系统的成功过高,如果要修改一下编译选项,往往要修改 dist 源代码。dist 的代码在目录: /src/cmd/dist 下。
dist 这个命令行程序支持如下几个参数:
- "banner print installation banner\n" ; 打印安装的一些信息
- "bootstrap rebuild everything\n" ; 重新编译所有的 go 代码
- "clean deletes all built files\n" ; 清楚编译的 go 代码
- "env [-p] print environment (-p: include $PATH)\n" ; 打印编译的环境
- "install [dir] install individual directory\n" ;安装某一个目录。会编译目录下代码,安装生成文件
- "version print Go version\n" ;大约go版本信息
想要研究编译细节一定要看看这个程序的代码,后续详细分析。
make.bash, 同样是一个 bash 脚步,打开这个脚步,可以看到这个脚步主要做了如下几件事情:
- 根据不同的系统,以及参数进行一些初始化的工作
- 编译生成 dist,调用dist 完成整个go 的编译. dist bootstrap
- 用编译生成的 go_bootstrap 完成整个安装过程
很遗憾,这个script 不支持 window。 window 下调用 make.bat 去完成编译。 go 的编译系统不能很好的支持cygwin, 这是让人觉得很不爽的地方。其实整个go 的编译应该建立在Makefile 机制上,而修改go 的编译脚本,让整个源代码不依赖于dist 去完成整个编译的过程,是让go 很好的支持各种不同平台的好的入手点。
有一些环境变量和 make.bash 结合的很紧密,也控制了编译的一些选项:
- GOROOT_FINAL : 这个变量用来表明 go 最终安装的路径,如果不设置,默认值为当前源代码的路径
- GOHOSTARCH : 设定编译 go 语音的电脑的 ARCH(架构) , 386 or amd64 or arm
- GOARCH : 编译生成的 go 所运行的 ARCH。
- GOOS : 编译生成的 go 所允许的操作系统
- GO_GCFLAGS: 编译 5g/6g/8g 时,额外指定的参数
- GO_LDFLAGS : 编译 5l/6l/8l 时, 额外指定的参数
- GO_CCFLAGS : 编译 5c/6c/8c 时,额外指定的参数
- CGO_ENABLED: 是否支持 cgo,设置为1 的话,cgo 相关文件会被编译,设置为0 的话,则不会编译
- GO_EXTLINK_ENABLED : 是否使用Host 环境的 link。设置1的话,则会使用编译环境中带的连接器,0,在不会
- CC : 设置C编译器名字, gcc 还是 clang , 这个设置的是 host 环境的编译器
- CC_FOR_TARGET : 设置C编译器名字,这个设置的是 能够生成目标环境代码的编译器
- CXX_FOR_TARGET: 设置CXX编译器名字, g++ or clang++这个设置的是 能够生成目标环境代码的编译器
- GO_DISTFLAGS : 为 dist bootstrap 提供额外的参数.
make.bash 的一些分析:
判断 run.bash 是否存在,不存在,则提示,退出
- if [ ! -f run.bash ]; then
- echo 'make.bash must be run from $GOROOT/src' 1>&2
- exit 1
- fi
判断当前是否在cygwin 或者 mingw ,或者其他window 环境下运行。 这里吧 cygwin 简单的划到window 的环境,是不合适的
- case "$(uname)" in
- *MINGW* | *WIN32* | *CYGWIN*)
- echo 'ERROR: Do not use make.bash to build on Windows.'
- echo 'Use make.bat instead.'
- echo
- exit 1
- ;;
- esac
- if [ "$(uname)" == "Darwin" ]; then
- # golang.org/issue/5261
- mflag="$mflag -mmacosx-version-min=10.6"
- fi
- # if gcc does not exist and $CC is not set, try clang if available.
- if [ -z "$CC" -a -z "$(type -t gcc)" -a -n "$(type -t clang)" ]; then
- export CC=clang CXX=clang++
- fi
编译生成 dist 程序,判断是否编译成功
- ${CC:-gcc} $mflag -O2 -Wall -o cmd/dist/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
- # -e doesn't propagate out of eval, so check success by hand.
- eval $(./cmd/dist/dist env -p || echo FAIL=true)
- if [ "$FAIL" = true ]; then
- exit 1
- fi
- if [ "$1" = "--dist-tool" ]; then
- # Stop after building dist tool.
- mkdir -p "$GOTOOLDIR"
- if [ "$2" != "" ]; then
- cp cmd/dist/dist "$2"
- fi
- mv cmd/dist/dist "$GOTOOLDIR"/dist
- exit 0
- fi
- echo "# Building compilers and Go bootstrap tool for host, $GOHOSTOS/$GOHOSTARCH."
- buildall="-a"
- if [ "$1" = "--no-clean" ]; then
- buildall=""
- shift
- fi
- ./cmd/dist/dist bootstrap $buildall $GO_DISTFLAGS -v # builds go_bootstrap
用 go_bootstrap 完成整个编译过程
- if [ "$GOHOSTARCH" != "$GOARCH" -o "$GOHOSTOS" != "$GOOS" ]; then
- echo "# Building packages and commands for host, $GOHOSTOS/$GOHOSTARCH."
- # CC_FOR_TARGET is recorded as the default compiler for the go tool. When building for the host, however,
- # use the host compiler, CC, from `cmd/dist/dist env` instead.
- CC=$CC GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH \
- "$GOTOOLDIR"/go_bootstrap install -ccflags "$GO_CCFLAGS" -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
- echo
- fi
- echo "# Building packages and commands for $GOOS/$GOARCH."
- CC=$CC_FOR_TARGET "$GOTOOLDIR"/go_bootstrap install $GO_FLAGS -ccflags "$GO_CCFLAGS" -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
- echo
有疑问加站长微信联系(非本文作者)