Best Practices for setup.py and CMakeLists.txt in ROS2

In ROS2, both setup.py and CMakeLists.txt can be used simultaneously, but specific integration guidelines must be followed. For projects that contain a mix of Python and C++ code, the best practices are as follows:

1. Implementation of Mixed Builds

1. CMake as the Primary Build System (Recommended)

Integrate Python modules in CMake using the ament_cmake_python extension, without using setup.py separately. Example CMakeLists.txt configuration:

cmake_minimum_required(VERSION 3.5)
project(ros2_demo)

# C++ node compilation
add_executable(cpp_node src/cpp_node.cpp)
ament_target_dependencies(cpp_node rclcpp)
install(TARGETS cpp_node DESTINATION lib/${PROJECT_NAME})

# Python module integration
find_package(ament_cmake_python REQUIRED)
ament_python_install_package(${PROJECT_NAME} SCRIPTS_DESTINATION lib/${PROJECT_NAME})

# Python node installation
install(PROGRAMS
  ros2_demo/new_python_node.py
  DESTINATION lib/${PROJECT_NAME}
)

ament_package()

2. Coexistence but Manual Conflict Avoidance

If setup.py must be retained, the build type must be explicitly specified in package.xml:

<export>
  <build_type>ament_cmake</build_type> <!-- or ament_python -->
</export>

⚠️ Note: ROS2 does not recommend using both build systems simultaneously, as it may lead to abnormal environment variable registration (such as the previous issue of needing to manually source local_setup.bash within the package).

2. Best Practices for Mixed Code Projects

1. Directory Structure Specification

ros2_demo/
├── include/ros2_demo/       # C++ header files
├── src/                     # C++ source files
│   └── cpp_node.cpp
├── ros2_demo/               # Python package directory
│   ├── __init__.py
│   └── new_python_node.py
├── CMakeLists.txt           # Main build script
├── package.xml              # Dependency declaration
└── setup.cfg                # Python installation configuration (if needed)

2. Dependency Management

  • Declare all dependencies uniformly in package.xml:
<depend>rclcpp</depend>    <!-- C++ dependency -->
<depend>rclpy</depend>     <!-- Python dependency -->
  • Link C++ dependencies in CMake using ament_target_dependencies
  • Manage Python dependencies through setup.cfg or requirements.txt

3. Compilation and Installation

# Single command to compile all code
colcon build --packages-select ros2_demo

# Automatically generate unified environment variables
source install/local_setup.bash

4. Node Naming and Communication

  • C++ and Python nodes should use different names (e.g., cpp_publisher and py_subscriber)
  • Achieve cross-language communication through a unified topic name (e.g., echo_test_msg)
  • Use ROS2 Interface Definition Language (IDL) to ensure message format consistency

3. Common Problem Solutions

  1. Environment variables not automatically registered: Ensure that ament_package() is included in CMakeLists.txt, and that the <build_type> in package.xml matches the actual build system.
  2. Python module import errors: Add the following to setup.cfg:
[develop]
script-dir=$base/lib/ros2_demo
[install]
install-scripts=$base/lib/ros2_demo
  1. Debugging Mixed Code
  • C++: Use gdb ./install/ros2_demo/lib/ros2_demo/cpp_node
  • Python: Directly use python3 -m pdb install/ros2_demo/lib/ros2_demo/new_python_node.py

Leave a Comment