Building a ROS Package
This guide shows how to build a ROS package into a conda package with Pixi using the pixi-build-ros backend.
To understand the build feature, start with the general Build Getting Started guide. For ROS without Pixi building (not packaging), see the ROS 2 tutorial. You may also want to read the backend documentation for pixi-build-ros.
Warning
pixi-build is a preview feature and may change before stabilization.
Expect rough edges; please report issues so we can improve it.
Create a Pixi workspace#
Initialize a new workspace and install the ROS 2 CLI so you can scaffold packages via the ros2 cli.
pixi init ros_ws --channel https://prefix.dev/robostack-jazzy --channel https://prefix.dev/conda-forge
cd ros_ws
pixi add ros-jazzy-ros2run
This adds the ros2 cli command to your Pixi environment.
In all examples below, ensure the build preview is enabled in your workspace manifest:
Resulting workspace manifest:
[workspace]
channels = [
"https://prefix.dev/robostack-jazzy",
"https://prefix.dev/conda-forge",
]
platforms = [
"osx-arm64",
"win-64",
"linux-64",
] # Your platform here, e.g. "linux-64", "osx-arm64", "win-64"
preview = ["pixi-build"]
[dependencies]
ros-jazzy-ros2run = ">=0.32.4,<0.33"
Creating a Python ROS package#
We'll be creating a normal ROS2 package using ament_python and then adding Pixi support to it.
Most of the logic is done by the ROS2 CLI, so you can follow normal ROS 2 package creation steps.
Initialize a ROS package#
Use the ROS CLI to generate an ament_python package skeleton within the workspace.
pixi run ros2 pkg create --build-type ament_python --destination-directory src --node-name my_python_node my_python_ros_pkg
You should now have something like:
ros_ws/
├── pixi.toml
└── src/
└── my_python_ros_pkg/
├── package.xml
├── resource/
├── setup.cfg
├── setup.py
├── test/
└── my_python_ros_pkg/
├── __init__.py
└── my_python_node.py
Add Pixi package info to the new package#
Create a pixi.toml inside src/my_python_ros_pkg so Pixi can build it using the ROS backend. The backend reads most metadata from package.xml, so you only need to specify the backend and distro.
[package.build.backend]
channels = [
"https://prefix.dev/pixi-build-backends",
"https://prefix.dev/conda-forge",
]
name = "pixi-build-ros"
version = "*"
[package.build.config]
distro = "jazzy"
Notes:
- When
package.build.config.distrois set, the produced package name is prefixed likeros-<distro>-<name>. - The backend automatically reads
package.xml(name, version, license, maintainers, URLs, dependencies). Any explicitly set fields inpixi.tomloverridepackage.xml. - Dependencies in
package.xmlare mapped to conda packages via RoboStack (for examplestd_msgs→ros-<distro>-std-msgs). Unknown deps pass through unchanged.
Add the package to the pixi workspace#
Tell the root workspace to depend on the package via a path dependency that matches the ROS-prefixed name:
[dependencies]
ros-jazzy-ros2run = ">=0.32.4,<0.33"
ros-jazzy-my-python-ros-pkg = { path = "src/my_python_ros_pkg" }
Testing your package#
Now install and run:
Outputs:Create a CMake ROS package#
Creating a C++ or mixed package using ament_cmake.
Scaffold a C++ package:#
pixi run ros2 pkg create --build-type ament_cmake --destination-directory src --node-name my_cmake_node my_cmake_ros_pkg
Add the pixi package info#
Create a pixi.toml inside src/my_cmake_ros_pkg so Pixi can build it using the ROS backend.
The backend reads most metadata from package.xml, so you only need to specify the backend and distro.
[package.build.backend]
channels = [
"https://prefix.dev/pixi-build-backends",
"https://prefix.dev/conda-forge",
]
name = "pixi-build-ros"
version = "*"
[package.build.config]
distro = "jazzy"
Add the package to the pixi workspace#
Tell the root workspace to depend on the package via a path dependency that matches the ROS-prefixed name:
[dependencies]
ros-jazzy-ros2run = ">=0.32.4,<0.33"
ros-jazzy-my-python-ros-pkg = { path = "src/my_python_ros_pkg" }
ros-jazzy-my-cmake-ros-pkg = { path = "src/my_cmake_ros_pkg" }
Testing your package#
Now install and run:
Outputs:Building a ROS conda package#
With the package(s) added to the workspace, you can now build them.
You can now upload these artifacts to a conda channel and depend on them from other Pixi workspaces.
Tips and gotchas#
- ROS distro and platform: pick the correct RoboStack channel (e.g.
robostack-humble,robostack-jazzy) and ensure your platform is supported. - Keep
package.xmlaccurate: name, version, license, maintainers, URLs, and dependencies are read automatically; but you can override them in the pixi manifest. - Backend docs: see the pixi-build-ros documentation for configuration details like
env,distroandextra-input-globs. - Colcon vs pixi build: you don’t need
colconwhen usingpixi; the backend invokes the right build flow. But since you don't have to change your package structure, you can still usecolconif you want. - Not all ROS packages are available in RoboStack. If you depend on a package not in RoboStack, you can:
- Recommended: Contribute to RoboStack to add it; see the RoboStack Contributing page
- Package it yourself with Pixi in a separate workspace and upload it to your own conda channel.
- Optionally, this could use an out of tree package definition to build the package without changing its source code.
Conclusion#
You can package ROS projects as conda packages with Pixi using the pixi-build-ros backend.
Start simple, keep package.xml truthful, add ROS dependencies as needed, and iterate with the preview build feature.
Once built, you can upload artifacts to a conda channel and depend on them from other Pixi workspaces.