编译C++程序后分享他人出现libCommon.so加载失败问题求助
问题
本地编译C++程序后运行正常,但将整个build目录打包发送给朋友后,朋友运行时出现以下错误:
error while loading shared libraries: libCommon.so: cannot open shared object file: No such file or directory
怀疑共享库未正确链接,主CMakeLists.txt内容如下:
cmake_minimum_required(VERSION 3.16) project(Vibranium_Core) #set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_CXX_STANDARD 17) set(FLATBUFFERS_MAX_PARSING_DEPTH 16) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") set(CMAKE_INSTALL_RPATH "$ORIGIN") set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) if(APPLE) set(OPENSSL_INCLUDE_DIR "/opt/homebrew/opt/openssl@1.1/include") endif() if(EXISTS "${CMAKE_SOURCE_DIR}/.git") execute_process( COMMAND git rev-list --count HEAD WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( COMMAND git rev-parse --abbrev-ref HEAD WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_BRANCH OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( COMMAND git log -1 --format=%h WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( COMMAND git --no-pager log -1 --format=%ai WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_RELEASED_ON OUTPUT_STRIP_TRAILING_WHITESPACE ) else(EXISTS "${CMAKE_SOURCE_DIR}/.git") set(GIT_BRANCH "") set(GIT_COMMIT_HASH "") endif(EXISTS "${CMAKE_SOURCE_DIR}/.git") message(STATUS "VibraniumCore current branch: ${GIT_BRANCH}") message(STATUS "VibraniumCore Version: ${GIT_VERSION}") message(STATUS "VibraniumCore commit hash: ${GIT_COMMIT_HASH}") message(STATUS "Released on: ${GIT_RELEASED_ON}") message(STATUS "Generating version.h") configure_file( ${CMAKE_SOURCE_DIR}/cmake/version.h.in ${CMAKE_SOURCE_DIR}/Source/Common/Version.h ) add_definitions(-DGIT_COMMIT_HASH="${GIT_COMMIT_HASH}") add_definitions(-DGIT_BRANCH="${GIT_BRANCH}") add_definitions(-DGIT_VERSION="${GIT_VERSION}") add_definitions(-DGIT_RELEASED_ON="${GIT_RELEASED_ON}") if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") message(STATUS "Target is 64 bits") if (WIN32) set(WINXXBITS Win64) endif(WIN32) else("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") message(STATUS "Target is 32 bits") if (WIN32) set(WINXXBITS Win32) endif(WIN32) endif("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") # set macro-directory list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/macros") find_package(CURL REQUIRED) find_package(MySQL REQUIRED) find_package(Flatbuffers REQUIRED PATHS /usr/local/flatbuffers) find_package(Protobuf REQUIRED) find_package(OpenSSL REQUIRED) find_package(gRPC CONFIG REQUIRED) include_directories(${MYSQL_INCLUDE_DIR}) if(APPLE) include_directories(/opt/homebrew/include) include_directories(/usr/local/include) endif() # set default buildoptions and print them include(cmake/options.cmake) # Find revision ID and hash of the sourcetree include(cmake/genrev.cmake) # print out the results before continuing include(cmake/showoptions.cmake) # add dependencies add_subdirectory(dep) # add libraries and projects add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Source/Common) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Source/WorldServer) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Source/AuthServer) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Source/ClientEmulator) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Source/GameServerClientEmulator) add_subdirectory(Tests) set_target_properties(VibraniumCoreTests PROPERTIES EXCLUDE_FROM_ALL TRUE) set_target_properties(gtest PROPERTIES EXCLUDE_FROM_ALL TRUE) set_target_properties(gmock PROPERTIES EXCLUDE_FROM_ALL TRUE) set_target_properties(gtest_main PROPERTIES EXCLUDE_FROM_ALL TRUE) set_target_properties(gmock_main PROPERTIES EXCLUDE_FROM_ALL TRUE) set_target_properties( Common WorldServer AuthServer ClientEmulator PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/lib" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/lib" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" )
原因分析
- RPATH配置仅对安装阶段生效:当前设置的
CMAKE_INSTALL_RPATH和CMAKE_BUILD_WITH_INSTALL_RPATH是针对make install流程的,直接打包build目录下的编译产物时,这些RPATH规则不会被应用到可执行文件中,导致动态链接器找不到libCommon.so。 - 库与可执行文件的路径关系:可执行文件位于
bin/目录,libCommon.so在bin/lib/目录,系统默认的动态链接路径不包含这个相对位置,因此无法自动定位到库文件。
修复方案
方案一:修改CMake配置,让编译阶段生效RPATH
替换原CMakeLists.txt中的RPATH相关设置,让build目录下的可执行文件直接携带正确的动态链接路径:
# 替换原有的CMAKE_INSTALL_RPATH相关两行代码 set(CMAKE_RPATH "$ORIGIN/lib") set(CMAKE_BUILD_WITH_RPATH TRUE) # 确保编译时不跳过RPATH设置 set(CMAKE_SKIP_BUILD_RPATH FALSE) # 安装时保留RPATH规则 set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
$ORIGIN代表可执行文件所在的目录,$ORIGIN/lib会直接指向bin/lib/,动态链接器运行时会自动到该路径查找libCommon.so。修改后重新编译,打包build目录即可正常分发。
方案二:通过make install生成可分发包
保留现有CMake配置,通过安装流程生成带有正确RPATH的文件:
# 在build目录执行以下命令 cmake -DCMAKE_INSTALL_PREFIX=./install .. make make install # 打包安装目录 tar -czf vibranium_core.tar.gz install/
将打包后的vibranium_core.tar.gz发给朋友,解压后直接运行install/bin/下的可执行文件即可。
方案三:朋友端临时解决(快速测试用)
让朋友在运行前设置环境变量,指定动态链接库的路径:
# 进入bin目录后执行 export LD_LIBRARY_PATH=./lib:$LD_LIBRARY_PATH # 运行可执行文件,例如 ./WorldServer
或者直接在运行时临时指定:
LD_LIBRARY_PATH=./lib ./WorldServer
内容的提问来源于stack exchange,提问作者Venelin
相关产品推荐
相关产品推荐

