ROS2包中如何正确包含HPP与CPP文件?解决未定义引用错误
问题解决:ROS2包中undefined reference错误处理
问题场景
我正在开发一个ROS2包,src目录下的I2C_driver.cpp需要引用同目录下的SerialPort.hpp和SerialPort.cpp。不包含该文件时colcon build可正常执行,但一旦包含后就出现**undefined reference to '引入的命名空间'**错误。
当前CMakeLists.txt代码
cmake_minimum_required(VERSION 3.5) project(rover2-1_ros) # Default to C99 if(NOT CMAKE_C_STANDARD) set(CMAKE_C_STANDARD 99) endif() # Default to C++14 if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif() 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) # uncomment the following section in order to fill in # further dependencies manually. # find_package(<dependency> REQUIRED) if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) find_package(sensor_msgs REQUIRED) add_executable(gamepad src/joystick_rover_control.cpp) add_executable(i2c_driver src/I2C_driver.cpp) ament_target_dependencies(gamepad rclcpp std_msgs sensor_msgs) ament_target_dependencies(i2c_driver rclcpp std_msgs sensor_msgs) ament_lint_auto_find_test_dependencies() endif() install(DIRECTORY launch DESTINATION share/${PROJECT_NAME} ) install(TARGETS gamepad i2c_driver DESTINATION lib/${PROJECT_NAME}) ament_package()
错误原因
核心问题有两个:
- 仅在
I2C_driver.cpp中包含了SerialPort.hpp头文件,但未将SerialPort.cpp的实现代码编译进i2c_driver可执行文件,导致链接器找不到对应函数/命名空间的定义。 - 依赖包的
find_package被放在了BUILD_TESTING条件块内,正常编译(非测试模式)时不会加载这些依赖,可能引发额外编译问题。
修改后的CMakeLists.txt
cmake_minimum_required(VERSION 3.5) project(rover2-1_ros) # Default to C99 if(NOT CMAKE_C_STANDARD) set(CMAKE_C_STANDARD 99) endif() # Default to C++14 if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif() if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies - 移到BUILD_TESTING外,确保正常编译时加载 find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) find_package(sensor_msgs REQUIRED) # 编译可执行文件 - 添加SerialPort.cpp到i2c_driver的源文件列表 add_executable(gamepad src/joystick_rover_control.cpp) add_executable(i2c_driver src/I2C_driver.cpp src/SerialPort.cpp) ament_target_dependencies(gamepad rclcpp std_msgs sensor_msgs) ament_target_dependencies(i2c_driver rclcpp std_msgs sensor_msgs) if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) ament_lint_auto_find_test_dependencies() endif() install(DIRECTORY launch DESTINATION share/${PROJECT_NAME} ) install(TARGETS gamepad i2c_driver DESTINATION lib/${PROJECT_NAME}) ament_package()
关键修改点
- 将
rclcpp、std_msgs等依赖的find_package移到BUILD_TESTING条件块外部,确保正常编译流程能加载这些依赖。 - 在
add_executable(i2c_driver ...)中添加src/SerialPort.cpp,让编译器将该文件的代码编译并链接到i2c_driver可执行文件中。
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

