如何避免CMake链接@rpath,改用绝对路径?
问题原因
链接器处理macOS动态库依赖时,不会采用你链接时传入的库路径,而是读取库自身的install name(即库的ID,可通过otool -D /usr/local/lib/libmylib.dylib查看)。你的库install name设置为@rpath/libmylib.dylib,因此可执行文件的依赖列表会直接写入这个值,和CMake传入的绝对路径无关。
另一台机器生成绝对路径引用,本质是那台机器上的库install name本身就是绝对路径,而非CMake行为差异。
解决方法
1. 修正库的install name(根治方案)
如果是你用build2构建的库,直接在build2的buildfile中指定绝对路径的install name:
lib{mylib}: ... install_name = "/usr/local/lib/libmylib.dylib"
如果是第三方预编译库,用install_name_tool修改库的ID:
install_name_tool -id "/usr/local/lib/libmylib.dylib" /usr/local/lib/libmylib.dylib
注意:若该库还依赖其他动态库,需要同步修改那些依赖库的install name,否则仍会出现类似的加载问题。
2. 强制CMake链接时替换@rpath为绝对路径(无需修改库)
在CMakeLists.txt中给可执行文件添加链接选项,强制替换依赖路径:
target_link_options(my_executable PRIVATE -Wl,-headerpad_max_install_names -Wl,-change,@rpath/libmylib.dylib,/usr/local/lib/libmylib.dylib )
-headerpad_max_install_names用于预留足够的空间修改可执行文件的依赖路径,避免因空间不足报错。
3. 禁用CMake的RPATH功能(不推荐)
若想完全规避@rpath,可以关闭CMake的RPATH生成:
set(CMAKE_MACOSX_RPATH OFF)
此方法仅适合临时测试,会破坏CMake跨平台路径管理逻辑,且可能引发其他依赖库的加载问题。
额外说明
关于CMake未自动添加RPATH的问题:CMake默认会为构建目录外的库添加RPATH,但如果你未设置CMAKE_INSTALL_PREFIX或库路径不在CMake的默认RPATH规则范围内,可能不会自动生成。不过这只是运行时加载的问题,并非@rpath引用的根源——根源始终是库自身的install name设置。
内容的提问来源于stack exchange,提问作者nano

