如何从Bazel aspect中获取cc_*规则的所有头文件依赖(含工具链头文件)
Bazel Aspect获取C/C++完整头文件及工具链头文件的实现方案
你可以通过两种稳定途径获取编译阶段一致的所有头文件,无需手动解析bazel-bin下的.d文件:
方案1:直接提取工具链内置头文件
C++工具链的内置头文件可以通过CcToolchainInfo直接获取:
- 首先在aspect定义中声明工具链依赖:
your_analysis_aspect = aspect( attrs = { "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")), }, toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], # 其余aspect配置保持不变 )
- 在aspect实现函数中读取工具链头文件:
def _aspect_impl(target, ctx): cc_toolchain = ctx.attr._cc_toolchain[cc_common.CcToolchainInfo] # 获取工具链所有关联文件,筛选出头文件即可 toolchain_headers = [ f for f in cc_toolchain.all_files.to_list() if f.extension in ["h", "hh", "hpp", "hxx", "inc"] ]
方案2:从编译动作获取完整依赖集合(推荐)
如果需要和编译阶段完全一致的全量头文件(包含srcs、hdrs、所有依赖头文件、工具链头文件),直接读取C++编译动作的输入列表即可,Bazel已经提前解析好所有依赖:
- 遍历目标的动作,找到
CppCompile类型的编译动作:
def _aspect_impl(target, ctx): cpp_compile_actions = [ action for action in target.actions if action.mnemonic == "CppCompile" ] all_headers = [] for action in cpp_compile_actions: # 该属性包含编译动作依赖的所有输入文件,和.d文件列出的依赖完全一致 all_headers += action.inputs.to_list() # 去重处理(可选) all_headers = list(dict.fromkeys(all_headers))
- 让所有头文件进入aspect运行沙箱:
你只需要在创建自定义分析动作时,将上述获取的头文件列表传入inputs参数,Bazel就会自动把这些文件放到沙箱中供分析工具使用:
ctx.actions.run( outputs = [your_analysis_output], # 传入所有头文件依赖 + 你的分析工具本身 inputs = all_headers + [ctx.executable._your_analysis_tool], executable = ctx.executable._your_analysis_tool, arguments = [ # 传入你需要的分析参数 ], # 其余动作配置保持不变 )
如果你确实需要获取.d文件本身做自定义解析,可以从
CppCompile动作的输出列表中筛选后缀为.d的文件即可,无需到bazel-bin目录手动查找。
内容的提问来源于stack exchange,提问作者Andreas
相关产品推荐
相关产品推荐

