编译构建-Bazel单package多target项目

2019/02/15 开发管理

对于多个源码文件的项目,一般在代码模块设计上有两类做法:
1)把主入口的main的文件作为可执行分类;
2)将其它部分认为可以定义为lib的源码作为lib分类;
同时在Bazel中也有两种做法(bazel对于Package内部的拆分采用多target来区分,每个target其实就是BUILD文件中的一个个编译构建函数):
1)定义在一个package中,内部区分可执行程序和lib,在bazel中定义称为拆成多个编译构建的target。
2)定义在不同的Package中,通过不同的package区分可执行程序和不同的lib,当然这种方式更适合大粒度的模块化拆分。
这里先在一个Package中看看多源文件拆分分类的情况,Bazel是如何构建的。该项目实例结构如下:


└──TestBazelHello
   ├──PrintfTime
   │ ├── BUILD
   │ ├── PrintfTime.cpp
   │ ├── PrintfTime.h
   │ ├── TestPrintfTime.cpp
   ├── ....待生成编译构建文件
   └── WORKSPACE
   

准备源代码

源代码的内容和之前相同,只是将其拆分成多个文件存放。
源文件PrintfTime.h


    #include <ctime>
    #include <string>
    #include <iostream>
    std::string get_greet(const std::string& who);
    void print_localtime();

源文件PrintfTime.cpp


    #include "PrintfTime.h"
    std::string get_greet(const std::string& who) {
      return "Hello " + who;
    }
    void print_localtime() {
      std::time_t result = std::time(nullptr);
      std::cout << std::asctime(std::localtime(&result));
    }

包含main入口的源文件TestPrintfTime.cpp


    #include "PrintfTime.h"
    int main(int argc, char** argv) {
      std::string who = "world";
      if (argc > 1) {
        who = argv[1];
      }
      std::cout << get_greet(who) << std::endl;
      print_localtime();
      return 0;
    }

拆成多个源文件后,为了便于拆分管理,计划将拆分出来的PrintfTime.h/PrintfTime.cpp打包成lib,将拆分的包含入口main源文件通过依赖lib方式编译构建出可执行程序。最大的区别在BUILD文件中的构建规则。
BUILD文件:


cc_library( //表明为一个lib库
    name = "PrintfTime", //库的名字
    srcs = ["PrintfTime.cpp"], //源文件
    hdrs = ["PrintfTime.h"], //头文件
)

cc_binary( //表明为一个可执行程序
    name = "TestPrintfTime", //可执行程序名
    srcs = ["TestPrintfTime.cpp"], //源文件
    deps = [ //表明需要依赖库
        ":PrintfTime", //需要依赖库的名称
    ],
)

上传源码后编译构建

进入项目上传目录检查该上传的代码文件列表,没有缺少的情况下,运行编译构建命令。

Alt text

回到工作空间一级目录,执行编译命令“bazel build //PrintfTime:TestPrintfTime”:

Alt text

此时来看看构建生成的目录:

Alt text

进入生成的可执行文件目录,运行生成的可执行程序:

Alt text

查看依赖关系

这种拆分一旦完成,那么我们如何来查看一个项目的依赖关系呢?这里我们扩展开来,介绍一个好用的查询依赖关系的工具“graphviz”。

这个可视化的工具可以在windows操作系统上安装,网上可以搜索下载地址,安装基本上默认安装即可。(注意要把该工具的安装的bin目录添加到path环境变量)
那么bazel编译构建后的程序如何体现依赖关系呢,bazel提供了query指令,通过该命令,能生成依赖关系的数据,我们将该数据输入到graphviz工具即可生成依赖图。

1)生成依赖数据

Alt text

2)windows上打开graphviz工具,新建一个文件

Alt text

3)输入生成的依赖数据:

Alt text

输出该可执行程序项目的依赖关系:
该项目可执行程序为TestPrintfTime,依赖一个Timelib库和一个包含main入口的源文件。

Search

    Table of Contents