我正在使用CMake构建一个跨平台项目。目前我正尝试在Linux上运行它。我最近添加了一个用于运行测试的项目,但它无法运行,因为它找不到共享库之一,特别是libtbbmalloc.so.2
:
/tests: error while loading shared libraries: libtbbmalloc.so.2: cannot open shared object file: No such file or directory`
当我在可执行文件上运行ldd
时,我得到以下结果:
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如下所示:
set(test_sourcefiles main_tests.cpp)
add_executable(tests ${test_sourcefiles})
target_link_libraries(tests Catch2::Catch2 MyLib)
MyLib使用tbb,我猜这就是为什么我的可执行文件(tests)会搜索它。当在MyLib上运行ldd时,它会找到这个库(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)
我已经尝试在我的tests/CMakeLists.txt target_link_libraries(${project} /home/username/dev/tbb/libtbbmalloc.so.2)
中专门添加libttbbmalloc.so.2,但是没有任何区别。
如果我将/home/username/dev/tbb/
添加到LD_LIBRARY_PATH
中,则程序运行,ldd报告找到了libtbbmalloc.so.2。
有没有什么想法,我可能做错了什么,以及我如何让我的程序运行没有设置LD_LIBRARY_PATH
?
更新:我发现可以使用chrpath -l name-of-executable
打印runpath/rpath。当在我的可执行文件上使用此工具时,看起来像是libtbbmalloc.so.2文件夹被添加到runpath中,但程序仍然无法运行:
larjr@DESKTOP:~/dev/project/build/tests$ chrpath -l tests
tests: RUNPATH=/home/larsjr/dev/project/build/MyLib:/home/username/dev/tbb
3条答案
按热度按时间nzkunb0c1#
您遇到的问题听起来确实与共享库的直接和间接链接的搜索路径有关。CMake可能会使用新的ld RUNPATH变量来构建,该变量只对直接依赖项有效,而RPATH将递归地对所有间接依赖项有效。正如本文底部的片段所示,这可能取决于您的GCC版本。要检查您的可执行文件使用的是RPATH还是RUNPATH,跑步:
并在依赖项后面找到库rpath / runpath行。ie/eg:它可能会显示以下任一项:
您展示了您使用的命令chrpath -l ./executable,它实际上输出:
larjr@DESKTOP:~/开发/项目/构建/测试$ chrpath -l测试
测试:运行路径=/home/larsjr/dev/项目/build/我的库:/home/用户名/dev/tbb
这里说的“RUNPATH”是非递归的-这是你的错误。
请参考这个优秀的github问题,其中成员正在讨论与CMake的间接链接问题,强烈建议阅读全部。它有一个关于依赖关系和它们的搜索路径的很好的例子。https://github.com/conan-io/conan/issues/2660
有关可能导致此“问题”的新旧链接器行为的代码段:
您在conan-deptest中遇到的问题(顺便说一下,这是一个非常好的孤立案例!)是您正在记录的行为,在DT_RPATH和DT_RUNPATH之间。它是CMake(而不是conan),它在构建可执行文件时传递-rpath标志以及相关库的正确路径。问题是在某些平台(发出DT_RUNPATH,它们以前在此处发出DT_RPATH。实际上,readelf -d列出RUNPATH标记时就是这种情况。
还有另一个stackoverflow帖子,用户询问LD/GCC中的行为变化:如何用GCC/LD设置RPATH和RUNPATH?
一位柯南成员进一步阐述了如何改变这种行为:
在发出RUNPATH的链接器版本上复制此行为的方法是将--disable-new-dtags标志传递给链接器。
由此产生的结果可以:
现在如果你重新编译,并在你的可执行文件上检查readelf -d,你应该会看到RPATH标记。
要查看传递到每个依赖项的搜索路径中的RPATH:
希望这能解决您的问题!
额外的好处:链接到共享库教程。在文章的底部显示了runpath与rpath + origin!https://amir.rachum.com/blog/2016/09/17/shared-libraries/
relj7zay2#
我相信您正在寻找在可执行文件上设置运行时路径:
安装路径
在使用RPATH的系统上构建可执行文件等时,CMake通常会使用RPATH的构建树。安装软件时,CMake会重新链接可执行文件等以安装RPATH。如果此变量设置为true,则软件始终使用RPATH的安装路径构建,安装时不需要重新链接。
使用安装路径构建
在使用RPATH的系统上构建可执行文件等时,CMake通常会使用RPATH的构建树。安装软件时,CMake会重新链接可执行文件等以安装RPATH。如果此变量设置为true,则软件始终使用RPATH的安装路径构建,安装时不需要重新链接。
olmpazwi3#
在可执行安装命令旁边添加
set_target_properties