CMake项目无法找到共享库 [英] CMake project fails to find shared library

查看:215
本文介绍了CMake项目无法找到共享库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用CMake构建跨平台项目。目前,我正在尝试在Linux上运行它。我最近添加了一个用于运行测试的项目,但由于无法找到共享库之一,特别是 libtbbmalloc.so.2

I am using CMake to build a cross platform project. For the moment I am trying to run it on Linux. I have recently added a project for running tests, but it will not run because it cannot find one of the shared libraries, specifically libtbbmalloc.so.2:

/tests: error while loading shared libraries: libtbbmalloc.so.2: cannot open shared object file: No such file or directory`

当我在可执行文件上运行 ldd 时,我得到以下信息:

When I run ldd on the executable I get the following:

linux-vdso.so.1 (0x00007fffeb572000)
libtbbmalloc_proxy.so.2 => /home/username/dev/tbb/libtbbmalloc_proxy.so.2 (0x00007f50afe00000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f50afa70000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f50af6d0000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f50af4b0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f50af0a0000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f50aee90000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f50aec70000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f50aea60000)
/lib64/ld-linux-x86-64.so.2 (0x00007f50b0400000)
libtbbmalloc.so.2 => not found

我的测试项目的CMakeLists.txt看起来像这样:

The CMakeLists.txt for my test project looks like this:

set(test_sourcefiles main_tests.cpp)

add_executable(tests ${test_sourcefiles})

target_link_libraries(tests Catch2::Catch2 MyLib)

MyLib使用tbb,我想这就是我的可执行文件(测试)进行搜索。在MyLib上运行ldd时,它会找到该库(libtbbmalloc.so.2):

MyLib uses tbb, and I guess that is why my executable (tests) searches for it. When running ldd on MyLib it finds the library (libtbbmalloc.so.2):

(removed some output for readability)
libtbbmalloc_proxy.so.2 => /home/username/dev/tbb/libtbbmalloc_proxy.so.2 (0x00007f9af8110000)
libtbbmalloc.so.2 => /home/username/dev/tbb/libtbbmalloc.so.2 (0x00007f9ac4eb0000)

我专门尝试过在我的测试/CMakeLists.txt target_link_libraries($ {project} /home/username/dev/tbb/libtbbmalloc.so.2)中添加libttbbmalloc.so.2没有区别。

I have tried specifically adding libttbbmalloc.so.2 in my tests/CMakeLists.txt target_link_libraries(${project} /home/username/dev/tbb/libtbbmalloc.so.2), but it makes no difference.

如果我将 / home / username / dev / tbb / 添加到 LD_LIBRARY_PATH ,程序运行,ldd报告找到libtbbmalloc.so.2。

If I add /home/username/dev/tbb/ to LD_LIBRARY_PATH, the program runs, and ldd reports that libtbbmalloc.so.2 is found.

关于我可能做错了什么的任何想法,以及如何在不设置 LD_LIBRARY_PATH 的情况下使程序运行?

Any ideas on what I might be doing wrong, and how can I get my program to run without setting LD_LIBRARY_PATH?

更新:我发现可以使用 chrpath -l可执行文件名。在我的可执行文件上使用此工具时,看起来带有libtbbmalloc.so.2的文件夹已添加到runpath,但该程序仍无法运行:

Update: I found out that it's possible to print runpath/rpath by using chrpath -l name-of-executable. When using this tool on my executable, it looks like the folder with libtbbmalloc.so.2 is added to runpath, but the the program still won't run:

larjr@DESKTOP:~/dev/project/build/tests$ chrpath -l tests
tests: RUNPATH=/home/larsjr/dev/project/build/MyLib:/home/username/dev/tbb


推荐答案

您遇到的问题是声音与共享库直接和间接链接的搜索路径有关。 CMake可以使用新的ld RUNPATH变量进行构建,该变量仅对直接依赖项起作用,而RPATH将对所有间接依赖项递归起作用。如本文底部的摘要所示,这可能取决于您的GCC版本。要检查您的可执行文件是使用RPATH还是RUNPATH,请运行:

The issue you are encountering does sound to be related to the search path for direct and indirect linkage of shared libraries. CMake may build with the new ld RUNPATH variable which will only work on direct dependents, where RPATH will work recursively on all indirect dependents. As shown in the snippet at bottom of this post, this may depend on your version of GCC. To check if your executable is using RPATH or RUNPATH, run:

$ readelf -d ./executable

并在依赖后找到库rpath / runpath行。 ie / eg:它可能显示以下内容之一:

and find the library rpath / runpath line after your dependencies. ie/eg: It may show either of the below:

a) 0x000000000000001d (RUNPATH)            Library runpath: [/some/dir/lib]
b) 0x000000000000001d (RPATH)              Library rpath:   [/some/dir/lib]

您显示您使用了命令chrpath -l ./executable,它实际上吐出了:

You showed you used the command chrpath -l ./executable, which actually spat out:


larjr @ DESKTOP:〜/ dev /项目/构建/测试$ chrpath -l测试

larjr@DESKTOP:~/dev/project/build/tests$ chrpath -l tests

测试:RUNPATH = / home / larsjr / dev / project / build / MyLib:/ home / username / dev / tbb

tests: RUNPATH=/home/larsjr/dev/project/build/MyLib:/home/username/dev/tbb

在这里说 RUNPATH是非递归的,这是您的错误。

It says here "RUNPATH" which is non-recursive - that's your error.

请参阅此出色的github问题,成员正在讨论与CMake的间接链接问题,强烈建议阅读所有内容。它有一个关于依赖项及其搜索路径的出色示例。
https://github.com/conan-io/conan/issues/ 2660

Refer to this excellent github issue where members are discussing indirect linking issues with CMake, highly suggest reading it all. It has a a great example regarding dependencies and their search paths. https://github.com/conan-io/conan/issues/2660

有关新链接器行为与旧链接器行为的摘要,可能导致此问题:

A snippet regarding new vs old linker behavior which can cause this 'issue':


您在conan-deptest中遇到的问题(顺便说一句,是极好的隔离情况!)是您正在记录的行为,介于 DT_RPATH DT_RUNPATH
是CMake(而不是柯南),它在构建可执行文件时将-rpath标志与正确的路径传递给从属库。
问题是某些平台上的链接程序较新版本会发出 DT_RUNPATH ,而在以前,它们会发出 DT_RPATH 。确实是这种情况,因为readelf -d列出了RUNPATH标记。

The problem you are experiencing in conan-deptest (excellent isolated case, by the way!) is the behaviour that you are documenting, between DT_RPATH and DT_RUNPATH. It is CMake (and not conan), that passes the -rpath flag with the correct paths to the dependent libraries, when building the executable. The problem is that newer versions of the linker in some platforms, emit DT_RUNPATH where they used to emit DT_RPATH. Indeed this is the case as readelf -d is listing the RUNPATH tag.

还有另一个stackoverflow帖子,用户在此询问LD / GCC中的行为更改:
如何用GCC / LD设置RPATH和RUNPATH?

There is also another stackoverflow post where a user asks about this change in behaviour in LD/GCC: How to set RPATH and RUNPATH with GCC/LD?

柯南成员进一步阐述了如何更改此行为:

A conan member further elaborates on how to change this behavior:


在发出RUNPATH的链接器版本上复制此行为的方法是将--disable-new-dtags标志传递给链接器。

The way to replicate this behaviour on versions of the linker that emit RUNPATH instead, is to pass the --disable-new-dtags flag to the linker.

和结果是:

target_link_libraries(target "-Wl,--disable-new-dtags")

现在,如果您进行重建,并检查在可执行文件上的readelf -d上,应该看到RPATH标记。您可以运行:

Now if you rebuild, and check readelf -d on your executable, you should see the RPATH tag. You can run:

env LD_DEBUG=files,libs ./executable

,以查看RPATH正在传递给每个依赖项的搜索路径:

to see RPATH being passed into the search path for each dependency:

31658:  file=libbar.so.1 [0];  needed by /home/user/projectA/lib/libfoo.so.2.5 [0]
31658:  find library=libbar.so.1 [0]; searching
31658:   search path=/home/user/projectA/lib        (RPATH from file ./executable)
31658:    trying file=/home/user/projectA/lib/libbar.so.1

希望这可以解决您的问题!

Hopefully this fixes your issue!

奖金:
链接到共享库的教程。在拐杖的底部显示了runpath vs rpath + origin!
https://amir.rachum.com/blog / 2016/09/17 / shared-libraries /

这篇关于CMake项目无法找到共享库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆