pixi-build-ros#
The pixi-build-ros
backend is designed for building ROS (Robot Operating System) packages using the native ROS build systems.
No more requirement to use colcon
or catkin_tools
to build your ROS packages.
It provides seamless integration with Pixi's package management workflow while supporting ROS1 and ROS2 packages with automatic dependency resolution.
Warning
pixi-build
is a preview feature, and will change until it is stabilized.
This is why we require users to opt in to that feature by adding "pixi-build" to workspace.preview
.
Overview#
This backend automatically generates conda packages from ROS projects by:
- package.xml Integration: Automatically reads package metadata (name, version, description, maintainers, dependencies) from your ROS
package.xml
file - Multi-build system support: Supports ament_cmake, ament_python, catkin, and cmake build types
- ROS Distribution Support: Works with both ROS1 and ROS2 distributions (noetic, humble, jazzy, etc.)
- Cross-platform support: Supports Linux, macOS and Windows
- Automatic dependency mapping: Maps ROS dependencies to conda packages using RoboStack mappings
Basic Usage#
To use the ROS backend in your pixi.toml
, add it to your package's build configuration:
[workspace]
preview = ["pixi-build"]
channels = [
"https://prefix.dev/pixi-build-backends",
"https://prefix.dev/robostack-jazzy", # or robostack-humble, robostack-noetic, etc.
"https://prefix.dev/conda-forge"
]
platforms = ["linux-64", "osx-arm64"]
[package.build]
backend = { name = "pixi-build-ros", version = "*" }
[package.build.config]
distro = "jazzy" # or "humble", "noetic", etc.
Workspace Configuration
The workspace can be defined in the pixi.toml
of the package or in a separate pixi.toml
at the workspace root.
For example, with a workspace structure like this:
Then you can run pixi build
to create conda packages for your ROS packages.
When you want to install it into your environment, you can do so by adding the following to your workspace pixi.toml
:
[dependencies]
ros-jazzy-my-ros-package = { path = "." }
# or if the package is in a separate pixi.toml
# ros-jazzy-my-ros-package = { path = "src/my_ros_package" }
ros-jazzy-
prefix when you use a distro configuration.
Automatic Metadata Detection#
The backend will automatically read metadata from your package.xml
file to populate package information that is not explicitly defined in your pixi.toml
.
This includes:
- Package name and version: Automatically used if not specified in
pixi.toml
- Description: Uses the description from
package.xml
- Maintainers: Extracted from maintainer fields in
package.xml
- Homepage: From URL fields with type "website" in
package.xml
- Repository: From URL fields with type "repository" in
package.xml
For example, if your package.xml
contains:
<package format="3">
<name>my_ros_package</name>
<version>1.0.0</version>
<description>A useful ROS package for navigation</description>
<maintainer email="developer@example.com">John Doe</maintainer>
<url type="website">https://github.com/user/my_ros_package</url>
<url type="repository">https://github.com/user/my_ros_package</url>
</package>
It would be equivalent to the following pixi.toml
:
[package]
name = "my_ros_package"
version = "1.0.0"
description = "A useful ROS package for navigation"
maintainers = ["John Doe <developer@example.com"]
homepage = "https://github.com/user/my_ros_package"
repository = "https://github.com/user/my_ros_package"
The backend will automatically use the metadata from package.xml
to generate a complete conda package named ros-jazzy-my-ros-package
.
The fields in the pixi.toml
will override the values from package.xml
if they are explicitly set.
Automatic Dependency Resolution#
Because the definition of a dependency in a package.xml
file is not similar to a conda package name, the backend needs to map ROS dependencies to conda packages.
- Known dependencies: Mapped using the
robostack.yaml
. - Custom mappings: You can provide additional mappings in your
pixi.toml
under[package.build.config.extra-package-mappings]
- Other packages: Mapped to
ros-<distro>-<package-name>
format.
The <distro>
part of the package name is automatically generated based on the distro
configuration.
Configuration Options#
You can customize the ROS backend behavior using the [package.build.config]
section in your pixi.toml
. The backend supports the following configuration options:
distro
(Required)#
- Type:
String
- Default: Not set (required)
- Target Merge Behavior:
Overwrite
- Platform-specific distro takes precedence over base
The ROS distribution to build for. This affects dependency mapping and build configuration.
If set the package name will be prefixed with ros-<distro>-
automatically, otherwise the package name from pixi.toml
or package.xml
is used.
env
#
- Type:
Map<String, String>
- Default:
{}
- Target Merge Behavior:
Merge
- Platform environment variables override base variables with same name, others are merged
Environment variables to set during the build process. These variables are available during compilation.
Automatically injected environment variables#
The ROS backend keeps the following variables in sync with the selected distro, so you do not need to set them manually in env
:
ROS_DISTRO
— set to the distro name you configure indistro
.ROS_VERSION
— set to"1"
for ROS 1 distros and"2"
for ROS 2 distros.
These values are available both while evaluating package.xml
conditionals and during the generated build script. Any custom entries you provide in env
are merged on top of these defaults.
If you explicitly set ROS_DISTRO
or ROS_VERSION
in env
, your values take precedence over the defaults.
debug-dir
#
- Type:
String
(path) - Default: Not set
- Target Merge Behavior: Not allowed - Cannot have target specific value
If specified, internal build state and debug information will be written to this directory. Useful for troubleshooting build issues.
extra-input-globs
#
- Type:
Array<String>
- Default:
[]
- Target Merge Behavior:
Overwrite
- Platform-specific globs completely replace base globs
Additional glob patterns to include as input files for the build process. These patterns are added to the default input globs that include ROS-specific files.
[package.build.config]
extra-input-globs = [
"launch/**/*.py",
"config/*.yaml",
"msgs/**/*.msg",
"srvs/**/*.srv"
]
Default input globs include:
- Source files: **/*.{c,cpp,h,hpp,rs,sh,py,pyx}
- ROS configuration: package.xml
, setup.py
, setup.cfg
, pyproject.toml
- Build files: CMakeLists.txt
extra-package-mappings
#
- Type:
List<Map<String, Map<String, List<String> | RelativeFileName>>>
- Default:
[]
Additional dependency mappings to apply to the dependency mapping process.
These mappings are used to extend the usage of the dependencies in the package.xml
file.
[package.build.config]
extra-package-mappings = [
{"ros-custom" = { ros = ["ros-custom-msgs"] }},
"mapping.yml"
]
Or using a toml array of tables:
[[package.build.config.extra-package-mappings]]
custom_msgs = { ros = ["custom-messages"] }
Or you can use a file directly in the list:
The mapping file can contain the following:
package_name: # The name of the package in the package.xml
conda: conda-package-name # Maps to a conda package, e.g. from `conda-forge`
package_name2: # The name of the package in the package.xml
conda: [package1, package2] # Maps to a list of conda packages
ros_package: # The name of the package in the package.xml
ros: ros_package # Maps to a RoboStack style package name, e.g. `ros-<distro>-ros-package`
Build Process#
The ROS backend follows this build process:
- Package Detection: Parses
package.xml
to determine build type (ament_cmake
,ament_python
,catkin
) - Dependency Resolution: Maps ROS dependencies to conda packages using RoboStack mappings
- Environment Setup: Configures ROS-specific environment variables
- Build Execution: Uses the appropriate build template based on package type.
- Installation: Installs built artifacts to the conda package prefix
ROS Package Types#
The backend supports different ROS package build types:
ament_cmake (ROS2)#
For C++ packages using ament build system:
ament_python (ROS2)#
For Python packages using ament build system:
catkin (ROS1)#
For ROS1 packages using catkin build system:
Limitations#
- Version constraints: Dependency versions from
package.xml
are currently ignored - Conditional dependencies: Dependencies with conditions are not fully supported yet
- Target-specific dependencies: Platform-specific dependencies in
package.xml
need manual handling
See Also#
- ROS Documentation - Official ROS documentation
- RoboStack - Conda packages for the Robot Operating System
- ament Build System - ROS2 build system
- catkin Build System - ROS1 build system