c - 在所有情况下,.so 库是否需要在所有情况下都存在于运行时



我的问题与.so共享库有关。我正在构建一个在一台 ubuntu 机器上使用 cmake 但在另一台 ubuntu 机器上运行该应用程序的项目。

在 CMakeLists.txt 文件中,我有以下几行:

project (clientapp)
add_executable(${PROJECT_NAME} ${SOURCES} ${WAKAAMA_SOURCES} ${SHARED_SOURCES})
LINK_DIRECTORIES(/home/user//mraa-master-built/build/src)
target_link_libraries (clientapp libmraa.so)
target_link_libraries(clientapp m)

这些行将两个库 libmraa.so 和数学库添加到可执行文件中,并在另一台计算机上成功运行。

我对共享库的理解是,它们必须在编译时和应用程序启动时存在。但是我在另一台机器上没有 libmraa.so 文件,并且应用程序运行正常。我以为它不起作用。

我的假设正确吗?

通常,gccclang支持符号的延迟链接/绑定,但不支持整个库。这意味着所有共享对象(即:.so文件)至少应在应用程序启动时存在。一个例外是,如果您修改了makefile以不链接到这些库,并且通过dlopen()/dlsym()等手动调用库函数。

这些库中各个符号的绑定可以推迟到需要它们之后,或者您可以分别使用-z lazy-z now强制在启动时解析所有符号。

奇怪的是,您的应用程序在没有libmraa.so的情况下运行。应用程序在没有库的情况下运行的两个最可能的原因是:

  • 应用程序未使用库中定义的任何符号,因此链接器在生成时忽略库(尝试ldd app_name并查看库是否存在于ldd提供的库列表中)。
  • 构建脚本中存在问题,并且您正在静态链接到库的.a存档。

编辑:为了响应应用程序知道如何查找库的方式,链接器(在本例中为ld)将使用rpath查找来决定在搜索相应库时使用哪些目录。您可以通过从命令行执行类似LD_DEBUG=libs app_name的操作来了解其工作原理。您还可以通过LD_LIBRARY_PATH=/some/path app_name添加额外的路径。

我的假设正确吗?

是的。

对于应用程序运行的原因,有两种可能的解释:

  1. 你错了,机器上的某个地方libmraa.so(尽管可能不在你看的地方),或者
  2. 默认情况下,编译器默认为-Wl,--as-needed,并且您的二进制文件实际上并不依赖于libmraa.so,尽管它出现在链接行上。

您可以简单地确认或反驳上述任何一种猜测。

要确认猜测 2,请执行以下操作:

readelf -d clientapp | grep NEED | grep libmraa
# if there is no output, guess 2 is correct

如果猜测 2 是错误的,要确认猜测 1,请执行以下操作(在没有libmrra.so的机器上):

ldd clientapp | grep libmraa.so
# if guess 2 is incorrect, and this command produces no output, then
# your dynamic loader is broken, which is very unlikely.

相关内容

最新更新