macOS下CMake配合Conan引入fmt共享库未生成完整RPATH问题
问题根因
- macOS的动态库采用install name机制,和Linux的链接逻辑不同:即使链接时传入动态库的绝对路径,链接器也不会直接将该路径写入可执行文件的加载命令,而是优先读取动态库本身内置的install name字段,把这个字段的值写入最终可执行文件的
LC_LOAD_DYLIB段。你可以执行otool -D /Users/.../.conan/data/fmt/6.1.2/_/_/package/8cb4659713397fdd78e4947cac0468f7f7ca515d/lib/libfmtd.dylib验证,输出结果一定是libfmtd.6.dylib,没有前缀路径,这就是你otool查看到的加载路径来源。 - 你虽然开启了
CMAKE_MACOSX_RPATH ON,但你使用的cmake_find_package是Conan的旧版生成器,它生成的fmt::fmt目标不会自动将fmt库的Conan存储路径添加到可执行文件的RPATH中,导致运行时动态加载器无法通过相对库名找到对应文件。
解决方案
方案1:更换Conan生成器(推荐)
把conan_cmake_configure配置中的GENERATORS cmake_find_package替换为GENERATORS CMakeDeps,这是Conan官方推荐的新一代CMake集成生成器,生成的目标会自动将依赖库的存储路径添加到对应目标的RPATH配置中,无需额外修改即可正常运行。
方案2:手动添加RPATH配置
不换生成器的前提下,在CMakeLists.txt的find_package(fmt)之前添加如下配置:
set(CMAKE_BUILD_RPATH_USE_ORIGIN ON) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) # 显式添加fmt库的Conan存储路径到RPATH list(APPEND CMAKE_BUILD_RPATH ${CONAN_LIB_DIRS_FMT})
重新构建后可执行文件会新增LC_RPATH加载命令指向fmt库的存储路径,运行时即可正常找到动态库。
方案3:修改fmt库的install name(不推荐)
可以手动执行install_name_tool -id <fmt库绝对路径>/libfmtd.6.dylib <fmt库绝对路径>/libfmtd.dylib修改动态库内置的install name为全路径,后续重新链接你的项目即可。不过该修改只对本地当前的fmt库包生效,重新拉取Conan包后需要重新修改。
内容的提问来源于stack exchange,提问作者Gabriel
相关产品推荐
相关产品推荐

