此问题已在此处有答案:
What is an undefined reference/unresolved external symbol error and how do I fix it?(39个答案)
6天前关闭。
这篇文章是编辑并提交审查5天前.
我是ROS2的新手,对Cmake没有任何先验知识。
我有一个ROS2包,看起来像这样:
├── CMakeLists.txt
├── include
│ └── package_name
│ ├── bmi088.h
│ ├── bmi08x_defs.h
│ ├── bmi08x.h
│ ├── rpi_bmi088.h
│ └── rpi_i2c.h
├── package.xml
├── scripts
├── src
│ ├── bmi088.c
│ ├── imu_data_reader.cpp
│ ├── rpi_bmi088.c
│ └── rpi_i2c.c
└── package_name
└── __init__.py
我从github repo中获得了传感器驱动程序,并通过运行repo中包含的makefile来测试代码。代码运行得很好,但在ROS2中实现时,我在使用colcon构建时遇到了以下错误:
Starting >>> package_name
--- stderr: package_name
/usr/bin/ld: CMakeFiles/imu_data_reader.dir/src/imu_data_reader.cpp.o: in function `main':
imu_data_reader.cpp:(.text+0x12a): undefined reference to `rpi_bmi088_init(rpi_bmi088_t*, char const*, int, int, bmi08x_cfg const*, bmi08x_cfg const*)'
/usr/bin/ld: imu_data_reader.cpp:(.text+0x139): undefined reference to `rpi_bmi088_get_sensor_time(rpi_bmi088_t*)'
/usr/bin/ld: imu_data_reader.cpp:(.text+0x17f): undefined reference to `rpi_bmi088_get_accel(rpi_bmi088_t*, double*, double*, double*)'
/usr/bin/ld: imu_data_reader.cpp:(.text+0x1db): undefined reference to `rpi_bmi088_get_gyro(rpi_bmi088_t*, double*, double*, double*)'
collect2: error: ld returned 1 exit status
gmake[2]: *** [CMakeFiles/imu_data_reader.dir/build.make:154: imu_data_reader] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:148: CMakeFiles/imu_data_reader.dir/all] Error 2
gmake[1]: *** Waiting for unfinished jobs....
gmake: *** [Makefile:146: all] Error 2
---
Failed <<< package_name [0.42s, exited with code 2]
Summary: 0 packages finished [0.70s]
1 package failed: package_name
1 package had stderr output: package_name
我知道这个错误来自没有声明依赖项或错误编译,所以我可能搞砸了CMakeLists文件:
cmake_minimum_required(VERSION 3.8)
project(package_name)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# find dependencies
find_package(ament_cmake REQUIRED)
find_package(ament_cmake_python REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclpy REQUIRED)
# include directories
include_directories(include)
# CPP Nodes:
add_executable(imu_data_reader src/imu_data_reader.cpp)
ament_target_dependencies(imu_data_reader rclcpp)
# Link libraries:
add_library(rpi_bmi088 src/rpi_bmi088.c)
add_library(bmi088 src/bmi088.c)
add_library(rpi_i2c src/rpi_i2c.c)
target_link_libraries(imu_data_reader rpi_bmi088 bmi088 rpi_i2c)
install(TARGETS
imu_data_reader
DESTINATION lib/${PROJECT_NAME}
)
# Install Python modules
ament_python_install_package(${PROJECT_NAME})
# Install Python executables
install(PROGRAMS
DESTINATION lib/${PROJECT_NAME}
)
ament_package()
我的问题是:如何正确地编译头文件与它们对应的.c文件?
在我的源文件中,我包含了声明函数的头文件#include "package_name/rpi_bmi088.h"
,但它们没有链接到相应的.c文件(在本例中为src/rpi_bmi088.c
,函数在此实现)。
如果它也很重要,我将包含我的package.xml文件:
...package_info...
<buildtool_depend>ament_cmake</buildtool_depend>
<buildtool_depend>ament_cmake_python</buildtool_depend>
<depend>rclcpp</depend>
<depend>rclpy</depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
更新1:
在实施了迈克尔的回答之后:
extern "C"
{
#include "package_name/rpi_bmi088.h"
}
我现在得到一个不同但类似的错误:
Starting >>> package_name
--- stderr: package_name
/usr/bin/ld: libbmi088.a(bmi088.c.o): warning: relocation against `bmi08x_config_file' in read-only section `.text'
/usr/bin/ld: librpi_bmi088.a(rpi_bmi088.c.o): in function `rpi_bmi088_init':
rpi_bmi088.c:(.text+0x119): undefined reference to `bmi08a_get_regs'
/usr/bin/ld: rpi_bmi088.c:(.text+0x14c): undefined reference to `bmi08g_get_regs'
/usr/bin/ld: rpi_bmi088.c:(.text+0x183): undefined reference to `bmi08a_set_power_mode'
/usr/bin/ld: rpi_bmi088.c:(.text+0x195): undefined reference to `bmi08a_set_meas_conf'
/usr/bin/ld: rpi_bmi088.c:(.text+0x1a7): undefined reference to `bmi08a_get_power_mode'
/usr/bin/ld: rpi_bmi088.c:(.text+0x200): undefined reference to `bmi08g_set_power_mode'
/usr/bin/ld: rpi_bmi088.c:(.text+0x212): undefined reference to `bmi08g_set_meas_conf'
/usr/bin/ld: librpi_bmi088.a(rpi_bmi088.c.o): in function `rpi_bmi088_get_accel':
rpi_bmi088.c:(.text+0x2a0): undefined reference to `bmi08a_get_data'
/usr/bin/ld: librpi_bmi088.a(rpi_bmi088.c.o): in function `rpi_bmi088_get_gyro':
rpi_bmi088.c:(.text+0x384): undefined reference to `bmi08g_get_data'
/usr/bin/ld: librpi_bmi088.a(rpi_bmi088.c.o): in function `rpi_bmi088_get_sensor_time':
rpi_bmi088.c:(.text+0x46e): undefined reference to `bmi08a_get_sensor_time'
/usr/bin/ld: libbmi088.a(bmi088.c.o): in function `bmi088_init':
bmi088.c:(.text+0x18): undefined reference to `bmi08a_init'
/usr/bin/ld: bmi088.c:(.text+0x2d): undefined reference to `bmi08g_init'
/usr/bin/ld: libbmi088.a(bmi088.c.o): in function `bmi088_apply_config_file':
bmi088.c:(.text+0x66): undefined reference to `bmi08x_config_file'
/usr/bin/ld: bmi088.c:(.text+0x76): undefined reference to `bmi08a_write_config_file'
/usr/bin/ld: libbmi088.a(bmi088.c.o): in function `bmi088_configure_data_synchronization':
bmi088.c:(.text+0x14b): undefined reference to `bmi08a_set_meas_conf'
/usr/bin/ld: bmi088.c:(.text+0x166): undefined reference to `bmi08g_set_meas_conf'
/usr/bin/ld: bmi088.c:(.text+0x1a0): undefined reference to `bmi08a_write_feature_config'
/usr/bin/ld: libbmi088.a(bmi088.c.o): in function `bmi088_configure_anymotion':
bmi088.c:(.text+0x29a): undefined reference to `bmi08a_write_feature_config'
/usr/bin/ld: libbmi088.a(bmi088.c.o): in function `bmi088_get_synchronized_data':
bmi088.c:(.text+0x32c): undefined reference to `bmi08a_get_regs'
/usr/bin/ld: bmi088.c:(.text+0x35c): undefined reference to `bmi08a_get_regs'
/usr/bin/ld: bmi088.c:(.text+0x402): undefined reference to `bmi08g_get_data'
/usr/bin/ld: libbmi088.a(bmi088.c.o): in function `bmi088_set_data_sync_int_config':
bmi088.c:(.text+0x44f): undefined reference to `bmi08a_set_int_config'
/usr/bin/ld: bmi088.c:(.text+0x475): undefined reference to `bmi08a_set_int_config'
/usr/bin/ld: bmi088.c:(.text+0x49b): undefined reference to `bmi08g_set_int_config'
/usr/bin/ld: bmi088.c:(.text+0x4c1): undefined reference to `bmi08g_set_int_config'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status
gmake[2]: *** [CMakeFiles/imu_data_reader.dir/build.make:154: imu_data_reader] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:148: CMakeFiles/imu_data_reader.dir/all] Error 2
gmake[1]: *** Waiting for unfinished jobs....
gmake: *** [Makefile:146: all] Error 2
---
Failed <<< package_name [0.23s, exited with code 2]
Summary: 0 packages finished [0.34s]
1 package failed: package_name
1 package had stderr output: package_name
请注意:imu_data_reader.cpp
仅包含rpi_bmi088.h
rpi_bmi088.h
包括bmi08x.h
rpi_bmi088.c
包括rpi_bmi088.h
、rpi_i2c.h
和bmi088.h
bmi08x.h
包括bmi08x_defs.h
,但不包括任何内容rpi_i2c.c
包含rpi_i2c.h
,它不包含任何内容bmi088.h
还包括bmi08x_defs.h
bmi088.c
包括bmi08x.h
和bmi088.h
也许这是一个依赖性的问题。
更新二:
我最终通过对CMakeLists.txt文件的以下更改解决了我的问题:
# Add and link libraries:
add_library(rpi_bmi088 SHARED src/rpi_bmi088.c)
add_library(bmi088 SHARED src/bmi088.c)
add_library(rpi_i2c SHARED src/rpi_i2c.c)
target_link_libraries(imu_data_reader rpi_bmi088 rpi_i2c bmi088)
所以我走在正确的道路上,但我需要添加SHARED关键字。
更新3:
实际上只有'colcon build'工作,但运行我得到的节点:
colcon_ws/install/package_name/lib/package_name/imu_data_reader: error while loading shared libraries: librpi_bmi088.so: cannot open shared object file: No such file or directory
[ros2run]: Process exited with failure 127
所以现在我又毫无头绪了
2条答案
按热度按时间arknldoa1#
你的库文件是C文件,你的imu_data_reader是C++。当在C++文件中包含C文件的头时,我认为这可以解决您的问题:
你可能对什么是“链接”有错误的理解。链接与头文件没有太大关系。链接是(简化的)将已编译的代码组合成单个程序。
hyrbngr72#
什么解决了这个问题: