如何强制Bazel构建可合并多个cc_library的单归档产物目标
Bazel合并多个静态库为单个归档的解决方案
问题原因
原生cc_library规则不会将依赖的其他静态库合并到自身的归档产物中,你声明在srcs中的:lib1、:lib2只会作为传递链接标识存在:
- 单独构建
release-lib时,Bazel仅会完成依赖检查,不会生成对应的静态库文件 - 只有当上层
cc_binary依赖release-lib时,Bazel才会将lib1、lib2的归档传递给链接器参与二进制生成
解决方案
你可以通过genrule手动调用ar工具实现多静态库合并,BUILD配置示例如下:
cc_library( name = "lib1", srcs = ["src1.c"] ) cc_library( name = "lib2", srcs = ["src2.c"] ) genrule( name = "release-lib", # 填入所有需要合并的静态库目标 srcs = [ ":lib1", ":lib2", ], # 声明输出的合并归档文件名 outs = ["librelease.a"], cmd = """ # 创建临时目录避免不同库的同名.o文件冲突 temp_dir=$$(mktemp -d) for lib in $(SRCS); do lib_name=$$(basename $$lib .a) mkdir -p $$temp_dir/$$lib_name # 提取单个库的所有目标文件 cd $$temp_dir/$$lib_name && $$(dirname $(AR))/ar x $$(realpath $$lib) && cd - done # 将所有提取出的目标文件打包为新的静态库 $(AR) rcs $@ $$temp_dir/*/*.o # 清理临时文件 rm -rf $$temp_dir """, # 依赖C++工具链的ar命令 tools = ["@bazel_tools//tools/cpp:current_cc_toolchain"], toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], visibility = ["//visibility:public"], )
执行构建命令后就可以在bazel-out目录下找到生成的librelease.a:bazel build //:release-lib
补充说明
如果你需要对外暴露合并库的头文件,可以额外新增一个cc_library统一管理导出头文件:
cc_library( name = "release-lib-headers", # 填入所有需要对外暴露的头文件路径 hdrs = glob([ "lib1/include/**/*.h", "lib2/include/**/*.h", ]), visibility = ["//visibility:public"], )
其他目标需要依赖该合并库时,同时依赖release-lib和release-lib-headers即可正常编译链接。
内容的提问来源于stack exchange,提问作者Mohamed Mahrous
相关产品推荐
相关产品推荐

