我正在尝试使用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
。谢谢!
答案 0 :(得分:0)
我一直在努力解决这个问题。我建议您尝试的第一件事是启用
copy_dynamic_libraries_to_binary
工具链功能。我认为它主要是为Windows设计的,但也应为Linux使用。
现在,出于我们的目的,我不得不采取更复杂的方法,但最终还是采用了更可靠的方法:我实现了以下方面:对于每个二进制文件,遍历依赖关系图,收集属于二进制输出文件夹的所有内容并生成文件复制操作,以便在构建二进制文件时将必要的文件放置在此处。这包括传递依赖关系,但足够灵活以复制输出文件夹中我们需要的其他文件-C ++运行时,数据文件等。如果您有兴趣,我可以剪辑和共享相关的代码片段。
康斯坦丁