多package项目概述
模块化编程中除了主程序部分,更多的具备复用性、公共性或者按照服务化拆分的应用会按照模块化、lib化方式来编译构建程序。
前面的简单例子可以进一步分拆,从单个的package模式切换为多个package模式。
这么做的好处很明显:
1)多个package维护拆分的不同模块,每个模块都有自己的BUILD编译构建规则文件,便于单独维护各自模块。
2)多个package拆分有助于单独编译构建、调试各自的模块,也能加快编译构建的速度。
还是前面的实例,拆分为两个package后的项目结构如下:
└──TestBazelMulPk
├──lib
│ ├── BUILD
│ ├── PrintfTime.cpp
│ ├── PrintfTime.h
├──main
│ ├── BUILD
│ ├── TestPrintfTime.cpp
├── ....待生成编译构建文件
└── WORKSPACE
此时上述代码文件不动,lib中作为单个package存放拆分的模块库,main中作为单个package存放主程序。(模块命名可以约定规则,这里lib和main只是区分下而已)
准备源码项目实例
源码方面也要做些修改,主要是头文件的位置部分:
1)lib源文件
头文件PrintfTime.h
#include <ctime>
#include <string>
#include <iostream>
std::string get_greet(const std::string& who);
void print_localtime();
源文件PrintfTime.cpp
#include "lib/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));
}
2)main源文件
源文件TestPrintfTime.cpp
#include "lib/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;
}
编写构建BUILD文件
1)lib中的BUILD
cc_library(
name = "TimeLib",
srcs = ["PrintfTime.cpp"],
hdrs = ["PrintfTime.h"],
visibility = ["//main:__pkg__"],
)
由于每个target编译构建输出的可见性都是私有的,因此在拆分出来的package中的BUILD文件需要使用visibility构建命令设置该lib的package对main主程序的package可见。
2)main主程序中的BUILD
cc_binary(
name = "TestPrintfTime",
srcs = ["TestPrintfTime.cpp"],
deps = [
"//lib:TimeLib",
],
)
主程序的BUILD不同之处在于,依赖的lib库名需要加上该lib的package名lib。
编译构建项目
编译构建情况如下:
编译构建成功之后查看工作空间目录:
查询编译构建输出
此时可以进入bazel-bin输出target目录查看输出情况:
bazel-bin目录中输出了lib库和执行程序目录main。
1)lib构建输出
2)main构建输出
查看依赖关系
使用bazel提供的query生成项目依赖数据:
打开graphviz工具,贴入依赖数据,生成依赖关系: