所以我正在开发一个旨在在远程服务器上运行的项目。我在本地电脑上开发程序,编译它,然后上传到远程服务器。本地电脑和远程服务器都运行在CentOS 7.7上。
该程序使用 CLion IDE 开发,并使用 CMake 配置。该程序依赖于一些共享库,根据我在 CMake 中编写的内容,这些库应该链接到可执行文件。在我的本地PC上,我可以完美地编译和运行该程序。但是,当我将项目的整个目录scp
到远程服务器后,可执行文件无法运行。根据 ldd 的说法,它找不到任何“.so”文件。
这是我的 CMakeList.txt,每个路径都是相对路径,而不是绝对路径。
cmake_minimum_required(VERSION 3.15)
project(YS_Test)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_PATH_ src)
file(GLOB SOURCE_FILES_ ${SOURCE_PATH_}/*.*)
set(PROJECT_LIBS_ libTapQuoteAPI.so libTapTradeAPI.so libTapDataCollectAPI.so)
include_directories(api/include)
link_directories(api/lib/linux)
add_executable(YS_Test ${SOURCE_FILES_})
target_link_libraries(YS_Test ${PROJECT_LIBS_})
请不要告诉我设置LD_LIBRARY_PATH
来解决我的问题。该程序在没有 LD_LIBRARY_PATH
的本地电脑上运行良好,因此我希望它能够在没有 LD_LIBRARY_PATH
的远程服务器上运行。我想知道这里到底发生了什么,而不是解决问题。谢谢!
最佳答案
如果我正确理解您的问题,您希望将编译的 YS_Test
程序与一些依赖项一起发送,并让它在远程服务器上运行。默认情况下,可执行文件只会在 /etc/ld.so
中配置的目录中查找,其中不包含部署路径。
注意:通常您不会部署整个构建目录,而只会部署已编译的工件和依赖项。对于这个答案,我假设您将二进制文件及其依赖项部署到相同目录。
您有两个选择:
- 要求程序的用户自行或通过包装脚本设置
LD_LIBRARY_PATH
。该变量也将指示动态链接器在指定的目录中查找。即使您不喜欢此解决方案,它也是迄今为止最常见的方法。 将
-Wl,-rpath='$ORIGIN'
添加到链接器选项中。这会将DT_RUNPATH
属性添加到可执行文件的动态部分。当您使用 CMake 时,您还可以使用BUILD_RPATH
和/或INSTALL_RPATH
目标属性进行设置。 ld.so 联机帮助页对此属性的描述如下:If a shared object dependency does not contain a slash, then it is searched for in the following order:
- ...
- Using the directories specified in the DT_RUNPATH dynamic section attribute of the binary if present.
$ORIGIN
部分扩展到包含程序或共享的目录 对象。
如果您确实坚持发布构建目录(例如在开发期间),您可以查看 CMake BUILD_RPATH_USE_ORIGIN
属性(及其通常的全局对应项 CMAKE_BUILD_RPATH_USE_ORIGIN),这会将相对路径嵌入到二进制文件中,而不是绝对路径。
关于linux - scp 后 C++ 可执行文件无法链接到共享库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58969832/