MacOS下用CMake链接共享库遇运行时加载失败求助
解决macOS下dyld无法加载共享库的替代方案
方案1:通过CMake设置RPATH(推荐开发阶段使用)
修改CMakeLists.txt,为可执行文件配置运行时搜索路径,让它自动定位到shared目录下的库:
cmake_minimum_required(VERSION 3.28) project(tryshared) set(CMAKE_CXX_STANDARD 23) # 启用运行时路径支持 set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) # 指定运行时搜索库的路径(这里用项目根目录下的shared文件夹) set(CMAKE_INSTALL_RPATH "${CMAKE_SOURCE_DIR}/shared") add_library(foo SHARED IMPORTED GLOBAL) set_target_properties(foo PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/shared/foo_shared_debug.dylib IMPORTED_SONAME foo_shared_debug.dylib ) add_executable(bar main.cpp) target_link_libraries(bar foo)
编译后,可执行文件运行时会自动去指定路径查找依赖库,无需移动文件。
方案2:修改共享库的install_name(适合部署场景)
macOS的动态库包含install_name属性,可执行文件会依据这个路径查找库。先修改库的install_name为相对路径,再配合CMake配置:
- 用
install_name_tool修改库的属性:
install_name_tool -id "@executable_path/../shared/foo_shared_debug.dylib" shared/foo_shared_debug.dylib
@executable_path代表可执行文件所在目录,../shared对应你的目录结构(假设可执行文件在build子目录,shared在项目根目录)。
- 更新CMakeLists.txt:
cmake_minimum_required(VERSION 3.28) project(tryshared) set(CMAKE_CXX_STANDARD 23) add_library(foo SHARED IMPORTED GLOBAL) set_target_properties(foo PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/shared/foo_shared_debug.dylib IMPORTED_SONAME "@executable_path/../shared/foo_shared_debug.dylib" ) add_executable(bar main.cpp) target_link_libraries(bar foo)
编译后,可执行文件会通过相对路径自动找到依赖库。
方案3:运行时临时指定库路径
如果只是临时测试,可通过环境变量临时指定库的搜索路径:
DYLD_LIBRARY_PATH=./shared ./bar
该方法适合快速验证,但不适合正式部署,每次运行都需要手动设置环境变量。
方案4:将库与可执行文件放在同一目录
修改CMake配置,让编译后的可执行文件和共享库处于同一目录:
cmake_minimum_required(VERSION 3.28) project(tryshared) set(CMAKE_CXX_STANDARD 23) # 设置可执行文件输出目录 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) # 编译完成后自动复制共享库到可执行文件目录 add_custom_command(TARGET bar POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/shared/foo_shared_debug.dylib $<TARGET_FILE_DIR:bar> ) add_library(foo SHARED IMPORTED GLOBAL) set_target_properties(foo PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/shared/foo_shared_debug.dylib) add_executable(bar main.cpp) target_link_libraries(bar foo)
编译后,两者在同一个bin目录下,dyld会自动识别到依赖库。
内容的提问来源于stack exchange,提问作者Josef
相关产品推荐
相关产品推荐

