在使用 CMake 编译基于第三方动态库 的项目时,你是否遇到过类似下面的报错?
/home/user/toolchain/bin/ld: CMakeFiles/test.dir/example/demo.cpp.o: in function `xxxxxxx':
demo.cpp:(.text+0x588): undefined reference to `xxxxxxxxx'
/home/user/toolchain/bin/ld: demo.cpp:(.text+0x60c): undefined reference to `RK_MPI_SYS_Init'
...
错误原因:
-
这些
undefined reference
错误表明 链接器在编译时找不到动态库。 -
但动态库明明在
../lib/
目录下,为什么找不到? -
可能的原因是 RPATH(运行时库路径)设置不正确,导致链接器和运行时都找不到这些库。
解决方案:使用 set_target_properties
在 CMakeLists.txt
中添加以下代码,确保 CMake 在编译和运行时都能正确找到 ../lib/
目录下的动态库:
set_target_properties(test PROPERTIES
INSTALL_RPATH "../lib" # 设置 RPATH,运行时会优先从 "../lib" 目录查找动态库
CMAKE_BUILD_WITH_INSTALL_RPATH TRUE # 让 CMake 在编译时就使用 INSTALL_RPATH
LINK_FLAGS "-Wl,-rpath-link,../lib,../lib/xxxx.so" # 告诉链接器去 "../lib" 目录查找动态库
)
解释:
-
INSTALL_RPATH "../lib"
-
设置
test
运行时的 RPATH,让它自动从../lib
目录查找xxxxx.so
和xxxx.so
,避免ldd
查找失败。
-
-
CMAKE_BUILD_WITH_INSTALL_RPATH TRUE
-
让 CMake 在编译时就使用
INSTALL_RPATH
,避免找不到共享库的问题。
-
-
-Wl,-rpath-link,../lib,../lib/xxxxx.so
-
-Wl
让 CMake 直接传递参数给链接器ld
。 -
-rpath-link,../lib
让ld
在编译时就能找到xxxxx.so
。 -
../lib/libeasymedia.so
确保ld
也能解析libeasymedia.so
的依赖
-
如何检查是否生效?
1️⃣ 检查 librk_mpi.so
是否在 ../lib/
目录下
ls -l ../lib/
2️⃣ 检查 dms_test
是否正确链接动态库
ldd test
如果输出中动态库都正确解析,说明 RPATH 设置正确。
3️⃣ 确保 CMake
生成的 test
包含 rpath
readelf -d test | grep RPATH
如果输出包含 ../lib
,说明 RPATH
设置成功
总结
如果你的 CMake 编译时报 undefined reference
,并且你确定动态库存在,那么很可能是 RPATH 配置问题。
✅ 解决方案:
-
使用
INSTALL_RPATH
让程序运行时正确找到动态库。 -
使用
-Wl,-rpath-link
让链接器在编译时找到动态库。 -
检查
ls -l ../lib/
、ldd test
和readelf -d test
确保路径正确。