You're reading the documentation for a version of ROS 2 that has reached its EOL (end-of-life), and is no longer officially supported. If you want up-to-date information, please have a look at Iron.

ament_cmake_python user documentation

ament_cmake_python is a package that provides CMake functions for packages of the ament_cmake build type that contain Python code. See the ament_cmake user documentation for more information.


Pure Python packages should use the ament_python build type in most cases. To create an ament_python package, see Creating your first ROS 2 package. ament_cmake_python should only be used in cases where that is not possible, like when mixing C/C++ and Python code.


Basic project outline

The outline of a package called “my_project” with the ament_cmake build type that uses ament_cmake_python looks like:

└── my_project
    ├── CMakeLists.txt
    ├── package.xml
    └── my_project

The file can be empty, but it is needed to make Python treat the directory containing it as a package. There can also be a src or include directory alongside the CMakeLists.txt which holds C/C++ code.

Using ament_cmake_python

The package must declare a dependency on ament_cmake_python in its package.xml.


The CMakeLists.txt should contain:

find_package(ament_cmake_python REQUIRED)
# ...

The argument to ament_python_install_package() is the name of the directory alongside the CMakeLists.txt that contains the Python file. In this case, it is my_project, or ${PROJECT_NAME}.


Calling rosidl_generate_interfaces and ament_python_install_package in the same CMake project does not work. See this Github issue for more info. It is best practice to instead separate out the message generation into a separate package.

Then, another Python package that correctly depends on my_project can use it as a normal Python module:

from my_project.my_script import my_function

Assuming contains a function called my_function().

Using ament_cmake_pytest

The package ament_cmake_pytest is used to make tests discoverable to cmake. The package must declare a test dependency on ament_cmake_pytest in its package.xml.


Say the package has a file structure like below, with tests in the tests folder.

├── CMakeLists.txt
├── my_project
│   └──
├── package.xml
└── tests

The CMakeLists.txt should contain:

  find_package(ament_cmake_pytest REQUIRED)
    # Add other test files here
  foreach(_test_path ${_pytest_tests})
    get_filename_component(_test_name ${_test_path} NAME_WE)
    ament_add_pytest_test(${_test_name} ${_test_path}
      TIMEOUT 60

Compared to the usage of ament_python, which supports automatic test discovery, ament_cmake_pytest must be called with the path to each test file. The timeout can be reduced as needed.

Now, you can invoke your tests with the standard colcon testing commands.