假设预编译依赖项由供应商提供:
$ ls /opt/vendor/protobuf/lib
libprotobuf.so.3 -> libprotobuf.so.3.0.0
libprotobuf.so.3.0.0
要将其与 Bazel 一起使用,可以创建以下目标:
cc_import(
name = "protobuf",
shared_library = "lib/libprotobuf.3.0.0",
)
这样,bazel构建的应用程序可以链接到库,但是它无法启动:
error while loading shared libraries: libprotobuf.so.3: cannot open shared object file: no such file or directory
根本原因是实际的so文件有一个自定义的SONAME
字段:
objdump -x libprotobuf.so.3.0.0|grep SONAME
SONAME libprotobuf.so.3
加载程序将查找 libprotobuf.so.3(而不是 3.0.0),但不会在沙箱中找到它,因为我们从未告诉 bazel 有关符号链接(symbolic link)的信息。符号链接(symbolic link)是相对的,在 cc_import 目标中指定它会产生类似的错误。
是否可以使用 bazel 创建一个可运行的二进制文件,链接到应该通过符号链接(symbolic link)找到的共享库?
最佳答案
设置 RPATH 可能是一种解决方法。 cc_import 需要由 cc_library 包装:
cc_library(
name = "protobuf",
deps = [":protobuf_impl"],
linkopts = ["-Wl,-rpath=/opt/vendor/protobuf/lib"],
)
cc_import(
name = "protobuf_impl",
shared_library = "lib/libprotobuf.3.0.0",
)
这将使二进制文件运行,但假设每个系统上都存在“/opt/vendor/protobuf/lib”(包括远程执行),并且加载程序在运行时仍然逃脱沙箱。一个更清晰的解决方案会很好。
关于c++ - 使用 bazel 链接到版本化的预构建库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68405534/