好了,现在正式开始吧。
1 workspace
那怎样才可以说这个是一个Bazel项目或者源码库呢?Bazel的文件组织方式就是目录,只要在某个文件夹里放上一个WORKSPACE文件(或者WORKSPACE.bazel,如果目录中两个文件都存在,后者优先),这个目录就是一个workspace。除了根目录中的WORKSPACE文件,其子目录中的WORKSPACE文件都会被忽略,不能在某个workspace里面再创建另一个workspace。
WORKSPACE文件有了,那它里面放什么呢?它的主要功能是引入外部依赖,比如说你的这个workspace里面用到了一个函数,它定义在另一个workspace里面,你又不想复制粘贴,就可以在WORKSPACE文件里面来从那个workspace引入到当前的workspace中。当然如果你没有用到任何外部库或第三方库,它应该是空的。
2 repository
现在workspace有了,万一将来其他的workspace需要引用它的某个部分,或者它的里面有多个部分,需要相互引用。那引用的时候应该如何称呼啊?Bazel称呼这种代码的组织方式为repository,放置WORKSPACE文件的根目录称为main repository,代号为@。在WORKSPACE文件里面可以给这个repository起个名字,这样别人就很方便来引用它了。
3 package
如果项目很小,源文件数量很少,也许一个WORKSPACE文件就够用了。不过,Bazel可是能够支持10万+输入文件的超大规模项目的构建工具,所以合理化的分块管理也是必要的。一个repository的基本代码组织单元是package,一般我们都是把关系紧密的模块放在一起,组成一个package。
在repository的根目录下的某个目录,只要它有一个BUILD或BUILD.bazel文件,这个目录及其子目录,那它就是一个package。不过,如果子目录的某个目录中也有一个BUILD文件,那这个子目录及其包含的子目录就是另一个package,这两个package都是各个独立的package,没有从属或包含关系。
如果在repository的根目录下也放上一个BUILD文件,根目录也可以是一个package。
4 Target
假如我们正在着手开发一个网络通信库,Net-Comm repository,新建一个目录net-comm,里面放上一个空的WORKSPACE文件。库的功能包含网络传输和数据加密,我们再新建两个子目录net和crypt,在里面先各放上一个空的BUILD文件。好了,repository和packages都规划好了。
下面开始进攻package了。我们需要支持多种网络通信协议来完成数据传输,将来其他的项目可能只会用到其中某一种协议,将每种协议的实现单独组织、独立引用,应该是一个不错的选择。好了,引用路径的终点终于来了,target!package是个容器,里面的元素就是一个一个的target。target的主要类型是rule(还有file和package groups,这些不常用,我也不太明白)。rule主要有三种,它们是binary,library,test,从名字上很容易猜出来:执行程序,库和测试,没错。binary可以运行,library通常都是提供给其他target、package、repository来引用的,test是单元测试。
比如net这个package,我们规划为tcp协议和udp协议,这样net的BUILD文件中会定义两个library,分别是tcp和udp,还会定义两个test,tcp-test和udp-test,一共是4个target。实现之后,我们可以通过Bazel命令来构建它们,还可以运行测试来检查实现是否正确。
今天先到这里,下期是个简单的hello world,来消化一下上面的几个术语,你会发现非常简单、方便,我这个make菜鸟一开始也是这样的感觉。