如何在ROS2的CMakeList中正确链接c文件和头文件?[副本]

hfyxw5xn  于 2023-05-16  发布在  其他
关注(0)|答案(2)|浏览(177)

此问题已在此处有答案

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.hrpi_i2c.hbmi088.h
bmi08x.h包括bmi08x_defs.h,但不包括任何内容
rpi_i2c.c包含rpi_i2c.h,它不包含任何内容
bmi088.h还包括bmi08x_defs.h
bmi088.c包括bmi08x.hbmi088.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

所以现在我又毫无头绪了

arknldoa

arknldoa1#

你的库文件是C文件,你的imu_data_reader是C++。当在C++文件中包含C文件的头时,我认为这可以解决您的问题:

extern "C" 
{
    #include "package_name/rpi_bmi088.h"
}

你可能对什么是“链接”有错误的理解。链接与头文件没有太大关系。链接是(简化的)将已编译的代码组合成单个程序。

hyrbngr7

hyrbngr72#

什么解决了这个问题:

# Adding libraries:
add_library(rpi_bmi088 STATIC src/rpi_bmi088.c)
add_library(bmi088 STATIC src/bmi088.c)
add_library(rpi_i2c STATIC src/rpi_i2c.c)

# Linking libraries:
target_link_libraries(rpi_bmi088 rpi_i2c bmi088)
target_link_libraries(imu_data_reader rpi_bmi088)

# Install CPP executables:
install(TARGETS
  imu_data_reader
  rpi_bmi088
  bmi088
  rpi_i2c
  DESTINATION lib/${PROJECT_NAME}
)

相关问题