使用Bazel集群链接动态库时找不到版本脚本文件求助
问题分析与解决方案
核心问题
集群构建失败的根源在于链接选项的写法错误,导致ld尝试访问硬编码的相对路径(tool/vs.ld),而Bazel集群构建的沙箱环境中不存在该路径。本地构建时文件路径与工作目录一致,所以能正常找到,但集群构建时所有依赖文件会被复制到沙箱的临时路径下,必须通过Bazel的$(location)宏获取正确路径。
具体修复步骤
1. 修正linkopts的写法
原写法将-Wl,--version-script,和$(location :vis_ld)拆分为两个独立选项,ld会将第二个参数视为单独的文件路径,而非版本脚本的路径参数。需将两者合并为单个选项:
cc_library( name = "a", srcs = ["a.cc"] ) filegroup( name = "vis_ld", srcs = ["tool/vis.ld"] ) cc_library( name = "b", hdrs = ["b.h"], srcs = ["b.cc"], deps = [":a"], ) cc_binary( name = "libgeta.so", deps = [":b"], linkshared = True, # 合并选项,确保$(location)被正确解析为沙箱内的文件路径 linkopts = [ "-Wl,--version-script=$(location :vis_ld)" ], data = [":vis_ld"] )
2. 简化依赖(可选)
filegroup并非必须,可直接引用原始文件路径,减少冗余:
cc_library( name = "a", srcs = ["a.cc"] ) cc_library( name = "b", hdrs = ["b.h"], srcs = ["b.cc"], deps = [":a"], ) cc_binary( name = "libgeta.so", deps = [":b"], linkshared = True, linkopts = [ "-Wl,--version-script=$(location tool/vis.ld)" ], data = ["tool/vis.ld"] )
3. 若使用genrule生成版本脚本
如果版本脚本是通过genrule生成的,需确保genrule的输出被正确引用:
cc_library( name = "a", srcs = ["a.cc"] ) cc_library( name = "b", hdrs = ["b.h"], srcs = ["b.cc"], deps = [":a"], ) genrule( name = "generate_vis_ld", srcs = [], # 若有输入文件请在此添加 outs = ["vis.ld"], cmd = "echo 'YOUR_VERSION_SCRIPT_CONTENT' > $@", # 替换为实际生成逻辑 ) cc_binary( name = "libgeta.so", deps = [":b"], linkshared = True, linkopts = [ "-Wl,--version-script=$(location :generate_vis_ld)" ], data = [":generate_vis_ld"] )
关键原理
Bazel集群构建时会创建隔离的沙箱环境,所有依赖文件会被复制到沙箱的临时路径中。$(location)宏会自动替换为该文件在沙箱内的绝对路径,确保ld能正确找到版本脚本;而拆分选项的写法会导致ld忽略$(location)的替换结果,直接使用硬编码的相对路径,最终触发文件找不到的错误。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

