编译和目录结构介绍

介绍openshift的编译和目录结构介绍。

介绍openshift的源码编译和目录结构组织,为了方便代码调试和了解大型Golang项目的构建方式

编译

无论是openshift还是Kubernetes等大型Golang项目都用到了Makefile, 所以有必要从此开始说起,这里只说项目里用到的makefile特性,想了解更多的可以参考跟我一起写Makefile

Makefile介绍

makefile 关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、 模块分别放在若干个目录中,makefile 定义了一系列的规则来指定,哪些文件需要先编译, 哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile 就像一个 Shell 脚本一样,其中也可以执行操作系统的命令。 makefile 带来的好 处就是——“自动化编译”,一旦写好,只需要一个 make 命令,整个工程完全自动编译, 极大的提高了软件开发的效率。

Makefile里的规则,就在做两件事,一个是指明依赖关系,另一个是生成目标的方法

Golang项目里用到的Makefile规则比较简单,基本就是定义一个目标的生成方法,下面的示例是Openshift项目里makefile中定义的第一个目标。

all build:
	hack/build-go.sh $(WHAT) $(GOFLAGS)
.PHONY: all build

  • all build,是定义的目标,看到这个就知道可以在源码的根目录上执行make all build来编译了

  • 第二行说明生成目标的方法,就是去hack目录下执行build-go.sh脚本,这里还支持传入一些参数

  • 第三行 .PHONY,起到一个标识的作用,没什么实际意义,是用来告诉make命令,这里是个伪目标,也可以说成是默认目标,所以在openshift的根目录上直接执行make, 等效于make all build

还可以自己决定是否编译出镜像或者rpm包(make release, make build-rpms)

编译openshift

上边介绍了,直接敲make就可以自动编译出所有平台(linux, mac, windows)的二进制,编译前介绍两个hack方法,

  • 在hack/build-go.sh的第二行加上set -x, 这样的话,shell脚本在运行时,里面的所有变量和执行路径会全部打印出来,一目了然,不用自己一行一行的加echo debug了

  • 如下修改hack/build-cross.sh,不然会编译出多平台的二进制,花的时间略长啊。。。

    # by default, build for these platforms
    platforms=(
      linux/amd64
      # darwin/amd64
      # windows/amd64
      # linux/386
    )
    

下面简易说下执行make后,都发生了什么,只会捡关键点说。

➜  origin git:(xxpDev) ✗ make

hack/build-go.sh  

# 初始化一大堆变量,关键函数都在common.sh里实现的
source hack/common.sh hack/util.sh hack/lib目录下的所有脚本

# 还会改动GOPATH,然后会在$GOPATH/src/github.com/openshift下建个软连指向origin目录
export GOPATH=_output/local/go

# 最终组合成下面一条最原始的命令,来进行编译
go install \
  -pkgdir /home/xxp/Github/src/github.com/openshift/origin/_output/local/pkgdir/linux/amd64 \
  -tags ' ' \
  -ldflags '-X github.com/openshift/origin/pkg/bootstrap/docker.defaultImageStreams=centos7 \
    -X github.com/openshift/origin/pkg/cmd/util/variable.DefaultImagePrefix=openshift/origin \
    -X github.com/openshift/origin/pkg/version.majorFromGit=3 \
    -X github.com/openshift/origin/pkg/version.minorFromGit=6+ \
    -X github.com/openshift/origin/pkg/version.versionFromGit=v3.6.0-alpha.0+83e3250-176-dirty \
    -X github.com/openshift/origin/pkg/version.commitFromGit=83e3250 \
    -X github.com/openshift/origin/pkg/version.buildDate=2017-04-06T05:34:29Z \
    -X github.com/openshift/origin/vendor/k8s.io/kubernetes/pkg/version.gitCommit=43a9be4 \
    -X github.com/openshift/origin/vendor/k8s.io/kubernetes/pkg/version.gitVersion=v1.5.2+43a9be4 \
    -X github.com/openshift/origin/vendor/k8s.io/kubernetes/pkg/version.buildDate=2017-04-06T05:34:29Z \
    -X github.com/openshift/origin/vendor/k8s.io/kubernetes/pkg/version.gitTreeState=clean' \
  github.com/openshift/origin/cmd/openshift \
  github.com/openshift/origin/cmd/oc \
  github.com/openshift/origin/pkg/sdn/plugin/sdn-cni-plugin \
  github.com/openshift/origin/vendor/github.com/containernetworking/cni/plugins/ipam/host-local \
  github.com/openshift/origin/vendor/github.com/containernetworking/cni/plugins/main/loopback

可以看到openshift会编译出5个二进制来,其中3个和网络CNI接口有关,最后会放置到_output/local/bin/linux/amd64, 并作相关的软链接(oadm, kubelet)

所以以后分析程序的切入点就从cmd/openshift和 cmd/oc入手就行了

来看下编译成果

➜  origin git:(xxpDev) ✗ _output/local/bin/linux/amd64/oc version
oc v3.6.0-alpha.0+83e3250-176-dirty
kubernetes v1.5.2+43a9be4
features: Basic-Auth

看到输出v3.6.0-alpha.0+83e3250-176-dirty, 这就是上面编译时传进去的参数。

-X github.com/openshift/origin/pkg/version.majorFromGit=3,意思是说编译文件github.com/openshift/origin/pkg/version.go时,对常量majorFromGit赋值为3

项目目录结构

-- 未完待续