使用Bazel重构CMake项目:多依赖模块单独编译及头文件问题
Bazel重构常见问题解答
1. 多依赖模块的编译方式
Bazel完全支持将各个互相依赖的模块单独编译为独立库,这正是Bazel模块化构建的核心优势,完全没必要打包成单个大库。
具体做法是给每个模块单独编写BUILD文件,用cc_library定义该模块的库目标,并通过visibility控制其他模块的访问权限,依赖模块通过deps字段引用目标即可。
示例:
- 模块A的
BUILD文件:
cc_library( name = "module_a", srcs = ["a.cpp"], hdrs = ["a.h"], visibility = ["//visibility:public"], # 允许其他模块引用 )
- 依赖A的模块B的
BUILD文件:
cc_library( name = "module_b", srcs = ["b.cpp"], hdrs = ["b.h"], deps = ["//path/to/module_a"], # 引用模块A的目标路径 )
这种方式下,Bazel会自动处理模块间的依赖关系,仅编译必要的部分,还能利用增量编译缓存提升效率。
2. 非子目录头文件依赖的解决办法
Bazel的构建基于沙箱机制,无法通过includes或copts直接引用未声明的外部目录文件,必须通过构建目标来管理依赖,以下是几种可行方案:
方案一:将依赖目录转为Bazel库目标
如果依赖的非子目录属于项目内部,在该目录下创建BUILD文件,用cc_library封装头文件,并设置合适的可见性:
cc_library( name = "external_headers_lib", hdrs = glob(["*.h", "**/*.h"]), # 匹配所有层级的头文件 visibility = ["//path/to/current_module:__pkg__"], # 仅允许当前模块访问 )
然后在当前模块的BUILD文件中,通过deps引用这个库目标:
cc_library( name = "current_module", srcs = ["main.cpp"], deps = ["//path/to/external_headers:external_headers_lib"], )
方案二:调整头文件路径前缀
如果依赖的头文件路径层级较深,可通过include_prefix或strip_include_prefix简化代码中的引用路径:
cc_library( name = "foo_lib", hdrs = ["foo/bar/include/my_header.h"], strip_include_prefix = "foo/bar/include", # 去掉多余路径前缀 visibility = ["//visibility:public"], )
此时代码中只需写#include "my_header.h"即可匹配到目标文件。
方案三:导入外部第三方库
如果依赖的是项目外的第三方库,在WORKSPACE文件中用new_local_repository(本地库)或http_archive(远程库)导入:
# 导入本地第三方库示例 new_local_repository( name = "third_party_lib", path = "/absolute/path/to/third_party_lib", build_file_content = """ cc_library( name = "lib", hdrs = glob(["include/**/*.h"]), srcs = glob(["lib/*.a"]), # 若有静态库文件需添加 visibility = ["//visibility:public"], ) """, )
之后在当前模块的BUILD文件中通过deps引用:
deps = ["@third_party_lib//:lib"],
内容的提问来源于stack exchange,提问作者geek123
相关产品推荐
相关产品推荐

