使用Bazel构建C++项目时如何避免#include语句使用相对路径
警告原因说明
你对文件系统路径的理解是正确的,但Bazel对cc_*规则的includes属性有严格的包封装限制:所有includes指定的路径必须在当前目标所属的包(即当前BUILD文件所在的目录)范围内,不允许通过../跳出包的边界。你写的../lib会被Bazel解析为工作区根目录下的lib目录,这个目录不在is_binary_tree包的范围内,因此触发警告,未来版本的Bazel会直接将这种写法判定为错误。
配置错误修正
你不应该在下游的is_binary_tree目标中声明上游依赖的头文件路径,正确的做法是将includes属性配置在提供头文件的lib库目标中,由库自身对外暴露可用的头文件搜索路径:
- 修改
lib/BUILD配置:
cc_library( name = "graphs", srcs = ["graphs.cpp"], hdrs = ["graphs.h"], # 路径相对于当前lib包目录,声明后所有依赖该库的目标都会自动加入该搜索路径 includes = ["."], visibility = ["//is_binary_tree:__pkg__"] # 按需设置可见范围,也可以设为//visibility:public公开给所有包 )
- 删除
is_binary_tree/BUILD中的includes配置,仅保留依赖声明即可:
cc_binary( name="is_binary_tree", srcs=["is_binary_tree.cpp"], deps=["//lib:graphs"], )
修改后不需要改动is_binary_tree.cpp的代码,直接#include "graphs.h"即可正常编译,也不会再触发警告。
模块化引用最佳实践
要实现代码和工作区目录结构解绑、避免长路径引用,遵循以下规则即可:
- 遵循「提供头文件的库负责声明搜索路径」的原则,下游依赖仅需通过
deps引入对应库,不需要手动配置任何头文件搜索路径 - 如果要避免头文件重名冲突,可以给库增加命名空间层级:比如将
graphs.h放到lib/graphs/graphs.h,然后lib/BUILD的includes保持为["."],下游引用时写#include "graphs/graphs.h",就算后续把lib目录整体移动到工作区其他位置,只要库内部的目录结构不变,所有下游的#include语句都不需要修改 - 永远不要在
includes中使用../跳出当前包范围,也不要在C++代码中使用相对路径引用其他模块的头文件,所有跨模块的头文件引用都通过依赖库暴露的搜索路径实现
内容的提问来源于stack exchange,提问作者Emile Papillon-Corbeil
相关产品推荐
相关产品推荐

