Bazel中如何获取跨包生成文件thing.h的所在目录?
解决方法
方法一:用cc_library封装生成的头文件(推荐)
这是Bazel官方推荐的方式,通过cc_library统一管理头文件的依赖关系与include路径,无需手动调整编译选项。
- 修改
//foo/bar/baz/BUILD,将genrule生成的头文件封装进cc_library,并通过strip_include_prefix调整引用路径:
genrule( name = "thing_gen", outs = ["thing.h"], # 替换为你的实际头文件生成命令 cmd = "your_generation_command > $@", ) cc_library( name = "thing", hdrs = [":thing_gen"], # 去掉当前包路径前缀,让代码可直接用"thing.h"引用 strip_include_prefix = ".", # 根据需要设置可见性,允许consumer包访问 visibility = ["//path/to/consumer/package:__pkg__"], )
- 在consumer包的BUILD文件中,直接依赖上述cc_library即可,无需手动添加头文件到srcs或修改copts:
cc_binary( name = "consumer", srcs = ["consumer.cc"], deps = ["//foo/bar/baz:thing"], )
Bazel会自动将包含thing.h的目录加入编译include路径,代码里的#include "thing.h"就能正常解析。
方法二:生成到子目录配合cc_library
如果需要归类多个生成的头文件,可以让genrule输出到子目录,再通过cc_library暴露:
- 修改
//foo/bar/baz/BUILD:
genrule( name = "thing_gen", # 将头文件生成到include子目录下 outs = ["include/thing.h"], cmd = "your_generation_command > $@", ) cc_library( name = "thing", hdrs = [":thing_gen"], # 去掉include前缀,实现直接引用"thing.h" strip_include_prefix = "include", visibility = ["//path/to/consumer/package:__pkg__"], )
- consumer包的配置与方法一一致,直接依赖
//foo/bar/baz:thing即可。
方法三:手动传递头文件目录(不推荐)
若不想用cc_library封装,可通过辅助genrule获取头文件目录后传递给copts:
- 在consumer包的BUILD文件中添加辅助genrule:
genrule( name = "get_thing_h_dir", outs = ["thing_h_dir.txt"], srcs = ["//foo/bar/baz:thing.h"], cmd = "dirname $(rootpath //foo/bar/baz:thing.h) > $@", ) cc_binary( name = "consumer", srcs = ["consumer.cc"], deps = ["//foo/bar/baz:thing"], # 读取辅助规则生成的目录路径,加入include路径 copts = ["-I@$(location :get_thing_h_dir)"], )
该方法需额外维护辅助规则,仅作为临时替代方案。
内容的提问来源于stack exchange,提问作者David Given
相关产品推荐
相关产品推荐

