【发布时间】:2021-02-15 22:57:52
【问题描述】:
我正在尝试使用 Bazel 构建二进制应用程序。这个二进制文件依赖于一个外部的、预编译的库,我们称之为liba.so。反过来,liba.so 依赖于libb.so(我通过readelf -d liba.so | grep NEEDED 获得此信息。
为了构建它,我在 Bazel 中有以下设置:
cc_import(
name = "liba",
shared_library = "liba.so",
deps = [":libb"],
)
cc_import(
name = "libb",
shared_library = "libb.so",
)
cc_binary(
name = "my_app",
srcs = ["main.cpp"],
deps = [":liba"],
)
构建工作正常,但是在运行时(通过bazel run 或直接)ldd 无法找到libb.so。
我一直在阅读这方面的内容,原因是 Bazel 仅向二进制文件的 RUNPATH 添加了它的直接依赖项。由于libb.so 是传递依赖,所以二进制找不到它。
为了解决这个问题,我可以想到以下技巧:
-
添加丑陋的链接器标志以告诉 Bazel 添加到
RPATH而不是RUNPATH。然而,这被认为是一个坏主意,因为RPATH已被弃用,并且不允许通过LD_LIBRARY_PATH覆盖。 -
修补第三方 .so 文件以添加到他们的
RUNPATH。这可行,但修补我不拥有的库感觉不太好。 -
使传递依赖成为二进制的直接依赖。这不好,每个库都应该对它的依赖负责。二进制文件不需要知道
liba.so依赖什么。
有没有更好的方法来做到这一点?我尝试过的其他事情没有成功:
- 使用
cc_library而不是cc_import - 使用
data而不是deps。
谢谢!
【问题讨论】:
-
您的第三点非常值得商榷:liba 依赖于 libb 的事实可能是由您在 liba 中使用的内容引起的
-
如果
liba包含函数a(),它又从libb调用函数b(),我不想在我的应用程序中链接libb。应该只链接直接依赖项
标签: shared-libraries bazel rpath