如何在自定义Bazel规则中正确引入编译依赖的头文件?
我想要创建一个Bazel规则,该规则接收.yaml文件,利用其中信息生成源码,将其编译并归档为类似cc_library的静态库,且可被cc_rules依赖。我可以创建生成源码的规则并将其封装在cc_library宏中,但希望避免生成源码的目标与宏创建的目标使用不同名称。参考官方示例编写规则时,在引入依赖时遇到问题。假设我的规则中有deps属性,如何在编译命令中正确引入这些依赖?以下代码片段中的include_directories参数不正确,请问如何引入构建文件中deps属性指定的目标相关的所有头文件?
cpp_compile_variables = cc_common.create_compile_variables( feature_configuration = feature_configuration, cc_toolchain = cc_toolchain, user_compile_flags = ctx.fragments.cpp.copts, source_file = type_publisher.path, output_file = type_publisher_object_file.path, include_directories = [dep.attrs.hdrs for dep in ctx.files.deps] )
直接从ctx.files.deps提取头文件路径的方式是错误的,因为它无法收集deps目标的头文件目录、传递依赖的头文件等信息。正确做法是通过Bazel的编译上下文(compile context)统一处理依赖的头文件与编译参数:
聚合依赖的编译上下文
使用cc_common.merge_compile_contexts合并所有deps目标的编译上下文,自动处理传递依赖的头文件、宏定义、包含目录等内容:compile_contexts = [dep[CcInfo].compile_context for dep in ctx.attr.deps] merged_compile_context = cc_common.merge_compile_contexts( compile_contexts = compile_contexts, )提取正确的包含目录
从合并后的编译上下文中获取所有需要的包含目录,包括用户头目录和系统头目录:include_dirs = merged_compile_context.includes + merged_compile_context.system_includes修正编译变量初始化
将include_directories参数替换为上述正确的目录列表,同时可以把依赖的宏定义合并到编译参数中:# 合并依赖的宏定义到编译参数 compile_defines = merged_compile_context.defines user_compile_flags = ctx.fragments.cpp.copts + ["-D{}".format(def) for def in compile_defines] cpp_compile_variables = cc_common.create_compile_variables( feature_configuration = feature_configuration, cc_toolchain = cc_toolchain, user_compile_flags = user_compile_flags, source_file = type_publisher.path, output_file = type_publisher_object_file.path, include_directories = include_dirs )生成完整编译命令
后续使用cc_common.get_memory_inefficient_command_line生成编译命令时,这些包含目录会自动被转换为-I或-isystem参数,无需手动拼接。
另外要确保规则的deps属性类型设置为attr.label_list(providers=[CcInfo]),这样才能正确获取每个依赖的CcInfo提供者。
内容的提问来源于stack exchange,提问作者Emile Papillon-Corbeil

