为什么安装的程序在linux中加载共享库时出错(cmake)

时间:2014-03-05 18:27:09

标签: c++ linux cmake

我有一个问题与如何使用cmake安装构建的可执行程序有关,当它依赖于某些外部库时。假设我的可执行文件是abc,它依赖于两个外部库:lib1.solib2.so。代码的结构如下:

-.........
  |----bin (lib1.so lib2.so)
  |----include(lib1.h lib2.h)
  |----src(main.cpp)

使用以下cmake命令安装可执行程序时:

INSTALL(TARGETS ${Exe_Name}
    RUNTIME DESTINATION Path to bin
    LIBRARY DESTINATION Path to bin)

我希望可执行程序与lib1.solib2.so位于同一目录中。但是,当我在安装文件夹中执行构建的程序时,我遇到以下错误:

error while loading shared libraries: lib1 can not open shared object file No such file or directory

如果我使用ldd检查可执行文件,我找到了lib1.solib2.so not found。在搜索可能的解决方案后,我发现如果以这种方式调用可执行文件,那么它可以工作:

LD_LIBRARY_PATH=./ ./my_program_run

然后我的问题是如何让我的可执行程序在安装时用cmake知道共享库的位置?谢谢。

3 个答案:

答案 0 :(得分:2)

如果要将应用程序干净地安装到标准的Linux发行版中,那么您应该将支持的共享库安装到标准位置(/ usr / lib),或者应该将库位置添加到ld.so配置中,通过创建一个/etc/ld.so.conf.d/myprogram.conf文件,其中包含库所在目录的名称。

如果安装是临时的或更临时的,那么设置LD_LIBRARY_PATH的脚本是合适的。

答案 1 :(得分:2)

最好用最终可执行文件的RPATH解决这个问题。 RPATH是可执行文件本身的硬编​​码搜索路径,允许使用字符串$ORIGIN,它在运行时扩展到可执行文件的位置。请参阅此参考:http://man7.org/linux/man-pages/man8/ld.so.8.html

CMake在安装时剥离二进制文件的rpath,以避免二进制文件在您的开发树周围乱丢。但它也提供了一种简单的方法来修改安装路径,正是出于这个原因。这是简短的回答:

IF(UNIX)
  SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:\$ORIGIN/../bin:\$ORIGIN")
ENDIF()

此特定示例附加到现有rpath,并将.../bin添加到搜索路径,所有这些都相对于二进制文件的位置。

一些开发人员声称调整二进制文件的RPATH并不是一个好主意。在理想的世界中,所有库都将存在于系统库目录中。但是如果你把这种情况发挥到极致,你最终会得到Windows(至少是旧的),其中c:\ windows \ system32充满了垃圾,这些垃圾来自谁知道在哪里,可能与其他软件冲突,也可能不与其他软件发生冲突,使用rpath并将所有内容安装在一个地方似乎是一个很好的解决方案。

答案 2 :(得分:0)

在预定义的位置搜索库,其中包括使用ld.so.conf和LD_LIBRARY_PATH配置的标准库路径。您也可以尝试使用-rpath编译您的应用程序,但某些开发人员不建议这样做。我建议你创建一个包装脚本,它将设置LD_LIBRARY_PATH并像这样运行真正的应用程序:

“theapp”脚本:

#!/bin/sh
dir="`dirname \"$0\"`"
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}"$dir"
exec "$dir/theapp.real" # your real application

应用程序,脚本和库应位于同一位置(在bin /)下。