ROS2 Foxy下编译livox_ros_driver出现-fPIC问题的解决办法
按照github上LIVOX-SDK官网的流程编译Livox-SDK和livox_ros_driver时出现如下错误:/usr/bin/ld: /usr/local/lib/liblivox_sdk_static.a(device_discovery.cpp.o): relocation R_X86_64_TPOFF32 against symbol `_ZGVZN6spdlog7details2
按照github上LIVOX-SDK官网的流程编译Livox-SDK和livox_ros_driver时出现如下错误:
/usr/bin/ld: /usr/local/lib/liblivox_sdk_static.a(device_discovery.cpp.o): relocation R_X86_64_TPOFF32 against symbol `_ZGVZN6spdlog7details2os9thread_idEvE3tid' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/local/lib/liblivox_sdk_static.a(livox_sdk.cpp.o): relocation R_X86_64_PC32 against symbol `stderr@@GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/livox_ros2_driver.dir/build.make:462:liblivox_ros2_driver.so] 错误 1
make[1]: *** [CMakeFiles/Makefile2:80:CMakeFiles/livox_ros2_driver.dir/all] 错误 2
make: *** [Makefile:141:all] 错误 2
---
Failed <<< livox_ros2_driver [10.3s, exited with code 2]
这个错误的核心原因是:你正在尝试将 静态库(liblivox_sdk_static.a)链接到一个共享库(.so),但该静态库的目标文件(.o)没有使用 -fPIC 编译,导致无法生成位置无关的代码(Position-Independent Code),而共享库必须依赖位置无关代码才能正常链接。
可以这样解决,先打开Livox-SDK中sdk_core中的CMakeLists.txt文件,然后有两种解决方法,选择一种即可:
1)在第四行add_library之前加上一行
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
2)或在第四行add_library之后加上一行
target_compile_options(${SDK_LIBRARY} PRIVATE -fPIC)
1. CMAKE_POSITION_INDEPENDENT_CODE 生效的前提:必须在目标定义前设置
CMAKE_POSITION_INDEPENDENT_CODE 是一个 “全局 / 目标级” 的开关,它的作用范围是在它被设置之后定义的目标。如果你的 CMakeLists.txt 中,add_library(${SDK_LIBRARY} STATIC ...) 这行代码写在 set(CMAKE_POSITION_INDEPENDENT_CODE ON) 之前,那么这个全局开关对 SDK_LIBRARY 目标是无效的(因为目标已经被定义了,CMake 不会回溯应用配置)。
而 target_compile_options(${SDK_LIBRARY} PRIVATE -fPIC) 是直接针对已定义的目标添加编译选项,无论目标是在之前还是之后定义(只要在编译前执行),都会生效。这也是它更 “可靠” 的原因之一。
2. CMake 对静态库的 PIC 处理有默认差异
CMake 中,CMAKE_POSITION_INDEPENDENT_CODE 的默认行为因目标类型和平台而异:
- 对于共享库(SHARED),CMake 会默认启用
PIC(等价于隐式设置了-fPIC),因为共享库必须依赖位置无关代码。 - 对于静态库(STATIC),CMake 默认不启用
PIC(除非平台强制要求,比如某些嵌入式系统),因为静态库本身被链接到可执行文件时,不需要位置无关代码。
当你手动设置 CMAKE_POSITION_INDEPENDENT_CODE ON 时,理论上会强制所有后续目标(包括静态库)启用 PIC,但如果你的项目中存在其他配置(比如某些第三方模块、工具链文件)显式覆盖了这个开关(例如 set(CMAKE_POSITION_INDEPENDENT_CODE OFF)),就可能导致全局设置失效。
而 target_compile_options 是目标级别的显式配置,优先级高于全局开关,因此即使有其他全局配置冲突,也能保证 -fPIC 被应用到 SDK_LIBRARY 目标上。
3. 总结:为什么 target_compile_options 更有效?
- 它直接作用于目标,不受 “设置时机”(目标定义前后)的影响;
- 目标级配置优先级高于全局配置,能避免被其他隐式设置覆盖;
- 对于静态库,CMake 对全局
PIC开关的处理更 “保守”,显式添加-fPIC更直接可靠。
如果后续需要调整,建议保持 target_compile_options(${SDK_LIBRARY} PRIVATE -fPIC) 的写法,同时确保它在 add_library(${SDK_LIBRARY} ...) 之后调用(虽然 CMake 允许在目标定义前用 target_* 命令,但习惯上在目标定义后写更清晰)。
更多推荐


所有评论(0)