如何解决Bazel-如何处理外部.so库的传递依赖项?
我正在尝试使用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
。
谢谢!
解决方法
我一直在努力解决这个问题。我建议您尝试的第一件事是启用
copy_dynamic_libraries_to_binary
工具链功能。我认为它主要是为Windows设计的,但也应为Linux使用。
现在,出于我们的目的,我不得不采取更复杂的方法,但最终还是采用了更可靠的方法:我实现了以下方面:对于每个二进制文件,遍历依赖关系图,收集属于二进制输出文件夹的所有内容并生成文件复制操作,以便在构建二进制文件时将必要的文件放置在此处。这包括传递依赖关系,但足够灵活以复制输出文件夹中我们需要的其他文件-C ++运行时,数据文件等。如果您有兴趣,我可以剪辑和共享相关的代码片段。
康斯坦丁
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。