Mixed python/cpp Ament package

Hello all,

I have yet to see a mixed python/cpp ament package. Does anyone have an example or documentation to point to?

Thanks.

2 Likes

catkin provided a CMake function to introspect a setup.py and for a subset of the possible content do “the right thing”.

In ament the package ament_cmake_python provides two functions:

Those should cover the major need to install Python packages or individual modules. At the moment there is no support for additional features provided by setuptools like entry points.

How would a cpp file be integrated into a pakage within the setup.py? Would it be defined as an external module?

Python packages with a setup.py file are processed in a standard way. So you can do whatever you like in there which works for python setup.py install, e.g. C++ extensions.

That works if my cpp file is not a ros2 node and a generic cpp file. But if it were to be a ros2 node, how would I define that in my setup.py? Is there a way to do this?

We have never tried that. CMake and ament_cmake provide a lot of features to handle dependencies and build libraries and executables from C++ code. I would assume it is a lot of effort trying to mimic this within a setup.py file.

Maybe the other way around makes more sense: using more Python specific features by calling out to Python from CMake.

Does that mean including ament_python in the CMakeLists.txt file and compiling my python node?

If I were to do this, how would I go about it? It’d be really helpful if you could give me a general sense of direction…

We don’t have many examples of this but I think rclpy[1] can give you an idea. It is an ament_cmake package[2] that compiles C code into a library and install it[3]. I also installs python modules[4] for the user to interact with. The difference here is that the libraries are installed in the python install directories (because they are python extensions) but you can install them where C++ libraries should go.

Hope this helps

[1]https://github.com/ros2/rclpy
[2]https://github.com/ros2/rclpy/blob/a8253b7b6538a25162f5abfba45dfebe2e7d3186/rclpy/package.xml#L27
[3]https://github.com/ros2/rclpy/blob/a8253b7b6538a25162f5abfba45dfebe2e7d3186/rclpy/CMakeLists.txt#L79
[4]https://github.com/ros2/rclpy/blob/a8253b7b6538a25162f5abfba45dfebe2e7d3186/rclpy/CMakeLists.txt#L27

Okay, this is what I have right now. My package has the following structure -

- my_pkg
    - CMakeLists.txt
    - package.xml
    - src
        - talker.cpp
    - my_pkg
        - __init__.py
        - listener.py
    - setup.py

My CMakeLists.txt looks like this -

cmake_minimum_required(VERSION 3.5)

project(my_pkg)

if(NOT WIN32)
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -Wextra -Wpedantic")
endif()

find_package(ament_cmake REQUIRED)
find_package(ament_cmake_python REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(python_cmake_module REQUIRED)
find_package(PythonExtra MODULE)

ament_python_install_package(${PROJECT_NAME})

add_executable(${PROJECT_NAME}_talker src/talker.cpp)
ament_target_dependencies(${PROJECT_NAME}_talker rclcpp std_msgs)

install(TARGETS
  ${PROJECT_NAME}_talker
  DESTINATION bin
)

ament_package()

My setup.py looks like this -
from setuptools import setup, Extension

setup(
    name='my_pkg',
    version='0.0.0',
    packages=[],
    py_modules=[
        'my_pkg.listener',],
    install_requires=['setuptools'],
    author='user',
    author_email='user@gmail.com',
    maintainer='user
    maintainer_email='user@gmail.com',
    keywords=['ROS'],
    classifiers=[
        'Intended Audience :: Developers',
        'License :: OSI Approved :: Apache Software License',
        'Programming Language :: Python',
        'Topic :: Software Development',
    ],
    description='Mixed Ament package  for python and cpp files.',
    license='Apache License, Version 2.0',
    test_suite='test',
    entry_points={
        'console_scripts': [
            'my_pkg_listener = my_pkg.listener:main',
        ],
    },
)

I am able to compile the package, and generate an executable for my_pkg_talker.
However ament fails to recognize the setup.py and install a target for the python node. Is there something else I need to do specifically for ament to recognize the existence of a setup.py and run it?

It looks like you’re mixing CMake (you have a CMakeLists.txt) and Python’s setuptools (you have a full setup.py file as well). Our build tool doesn’t support dual build system packages like this. When building your package it will either run cmake or python setup.py ... but not both.

If you need both then another solution will need to be found. Perhaps calling the setup.py from the CMakeLists.txt or replacing the functionality of the setup.py with just cmake code or replacing the functionality of the CMake code within setup.py using C++ Extensions, which @dirk-thomas linked to before.

We don’t currently have such an example as you’ve setup here. Specifically something that contains non-trivial CMake code (which would not easily be replicated with Python’s C++ Extensions) as well as a setup.py file which uses entry_points . Unfortunately, all I can say is that we don’t have a solution for this yet and I don’t know what the best strategy forward is at the moment.

1 Like

Ah okay. Thanks. I will try experimenting a little on my own and see if I can come up with something. If I’m successful I can create a new post and share my experience.

As suggested by @dirk-thomas, using CMake to call the setup.py would be the easier option. Is there any resources that you’d be aware of that could help me to proceed in this direction?

The closest thing I know of is how catkin from ROS 1 combines CMake and Python:

@srsidd, did you make any progress with this? I’m struggling with the same issue right now.

Just chiming in to say I also have the same package layload as @srsidd exemplified above, and would also be interested in how to get around this.

Wrt. ros2 packages using both C++ and Python with CMake and entry_points, is this still the case?

Nobody has worked on that and afaik nobody is planning to do so. So the state is still the same.