Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Colcon Compatibility

ROC's workspace build system is designed as a comprehensive drop-in replacement for colcon. This chapter details the compatibility features, command-line argument mapping, and behavioral equivalences that make ROC a seamless replacement for existing ROS2 workflows.

Command-Line Compatibility

Build Command Mapping

ROC provides full compatibility with colcon's most commonly used build options:

Colcon CommandROC EquivalentDescription
colcon buildroc work buildBuild all packages in workspace
colcon build --packages-select pkg1 pkg2roc work build --packages-select pkg1 pkg2Build only specified packages
colcon build --packages-ignore pkg1roc work build --packages-ignore pkg1Skip specified packages
colcon build --packages-up-to pkg1roc work build --packages-up-to pkg1Build dependencies up to package
colcon build --parallel-workers 4roc work build --parallel-workers 4Set number of parallel workers
colcon build --merge-installroc work build --merge-installUse merged install directory
colcon build --symlink-installroc work build --symlink-installUse symlinks for installation
colcon build --continue-on-errorroc work build --continue-on-errorContinue building after failures
colcon build --cmake-args -DCMAKE_BUILD_TYPE=Debugroc work build --cmake-args -DCMAKE_BUILD_TYPE=DebugPass arguments to CMake

Argument Processing

ROC's argument processing mirrors colcon's behavior:

#![allow(unused)]
fn main() {
// Parse command line arguments
if let Some(base_paths) = matches.get_many::<String>("base_paths") {
    config.base_paths = base_paths.map(PathBuf::from).collect();
}

if let Some(packages) = matches.get_many::<String>("packages_select") {
    config.packages_select = Some(packages.map(|s| s.to_string()).collect());
}

if let Some(packages) = matches.get_many::<String>("packages_ignore") {
    config.packages_ignore = Some(packages.map(|s| s.to_string()).collect());
}

if let Some(packages) = matches.get_many::<String>("packages_up_to") {
    config.packages_up_to = Some(packages.map(|s| s.to_string()).collect());
}

if let Some(workers) = matches.get_one::<u32>("parallel_workers") {
    config.parallel_workers = *workers;
}

config.merge_install = matches.get_flag("merge_install");
config.symlink_install = matches.get_flag("symlink_install");
config.continue_on_error = matches.get_flag("continue_on_error");

if let Some(cmake_args) = matches.get_many::<String>("cmake_args") {
    config.cmake_args = cmake_args.map(|s| s.to_string()).collect();
}
}

Workspace Structure Compatibility

Directory Layout

ROC maintains the same workspace structure as colcon:

workspace/
├── src/                    # Source packages (default discovery path)
│   ├── package1/
│   │   ├── package.xml
│   │   └── CMakeLists.txt
│   └── package2/
│       ├── package.xml
│       └── setup.py
├── build/                  # Build artifacts (created by ROC)
│   ├── package1/
│   └── package2/
├── install/                # Install artifacts (created by ROC)
│   ├── package1/          # Isolated install (default)
│   ├── package2/
│   └── setup.bash         # Workspace setup script
└── log/                    # Build logs (created by ROC)
    └── latest/
        ├── package1/
        └── package2/

Install Space Modes

ROC supports both colcon install modes:

Isolated Install (Default)

#![allow(unused)]
fn main() {
let install_prefix = if config.merge_install {
    config.workspace_root.join("install")
} else {
    config.workspace_root.join("install").join(&package.name)
};
}

Isolated Structure:

install/
├── package1/
│   ├── bin/
│   ├── lib/
│   └── share/
├── package2/
│   ├── bin/
│   ├── lib/
│   └── share/
└── setup.bash

Merged Install (--merge-install)

Merged Structure:

install/
├── bin/          # All executables
├── lib/          # All libraries  
├── share/        # All shared resources
└── setup.bash

Package Format Compatibility

Package.xml Support

ROC supports the same package.xml formats as colcon:

Format 2 (REP 140)

<?xml version="1.0"?>
<package format="2">
  <name>my_package</name>
  <version>1.0.0</version>
  <description>Package description</description>
  <maintainer email="maintainer@example.com">Maintainer Name</maintainer>
  <license>Apache-2.0</license>
  
  <buildtool_depend>ament_cmake</buildtool_depend>
  <build_depend>rclcpp</build_depend>
  <exec_depend>rclcpp</exec_depend>
  
  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>

Format 3 (REP 149)

<?xml version="1.0"?>
<package format="3">
  <name>my_package</name>
  <version>1.0.0</version>
  <description>Package description</description>
  <maintainer email="maintainer@example.com">Maintainer Name</maintainer>
  <license>Apache-2.0</license>
  
  <depend>rclcpp</depend>
  <build_depend condition="$ROS_VERSION == 2">ros2_specific_dep</build_depend>
  
  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>

Build Type Support

ROC supports all major build types used in ROS2:

#![allow(unused)]
fn main() {
#[derive(Debug, Clone, PartialEq)]
pub enum BuildType {
    AmentCmake,           // Standard C++ packages
    AmentPython,          // Pure Python packages
    Cmake,                // Plain CMake packages
    Other(String),        // Extensible for future types
}

impl From<&str> for BuildType {
    fn from(s: &str) -> Self {
        match s {
            "ament_cmake" => BuildType::AmentCmake,
            "ament_python" => BuildType::AmentPython,
            "cmake" => BuildType::Cmake,
            other => BuildType::Other(other.to_string()),
        }
    }
}
}

Build Process Compatibility

Build System Integration

ROC uses the same build system invocations as colcon:

CMake Packages

#![allow(unused)]
fn main() {
// Configure phase
let mut configure_cmd = Command::new("cmake");
configure_cmd
    .arg("-S").arg(&package.path)
    .arg("-B").arg(&build_dir)
    .arg(format!("-DCMAKE_INSTALL_PREFIX={}", install_prefix.display()));

// Build and install phase
let mut build_cmd = Command::new("cmake");
build_cmd
    .arg("--build").arg(&build_dir)
    .arg("--target").arg("install")
    .arg("--")
    .arg(format!("-j{}", config.parallel_workers));
}

Python Packages

#![allow(unused)]
fn main() {
// Build phase
Command::new("python3")
    .arg("setup.py")
    .arg("build")
    .arg("--build-base").arg(&build_dir)
    .current_dir(&package.path)

// Install phase
Command::new("python3")
    .arg("setup.py")
    .arg("install")
    .arg("--prefix").arg("")
    .arg("--root").arg(&install_prefix)
    .current_dir(&package.path)
}

Environment Setup

ROC generates the same environment setup scripts as colcon:

Setup Script Structure

#!/bin/bash
# Generated by roc workspace build tool (colcon compatible)

# Source any parent workspaces
if [ -n "$COLCON_CURRENT_PREFIX" ]; then
    _colcon_current_prefix="$COLCON_CURRENT_PREFIX"
fi
export COLCON_CURRENT_PREFIX="{}"

# Add this workspace to environment
export CMAKE_PREFIX_PATH="$COLCON_CURRENT_PREFIX:${CMAKE_PREFIX_PATH}"
export AMENT_PREFIX_PATH="$COLCON_CURRENT_PREFIX:${AMENT_PREFIX_PATH}"

# Standard paths
if [ -d "$COLCON_CURRENT_PREFIX/bin" ]; then
    export PATH="$COLCON_CURRENT_PREFIX/bin:${PATH}"
fi

if [ -d "$COLCON_CURRENT_PREFIX/lib" ]; then
    export LD_LIBRARY_PATH="$COLCON_CURRENT_PREFIX/lib:${LD_LIBRARY_PATH}"
fi

# Python paths
if [ -d "$COLCON_CURRENT_PREFIX/lib/python3.10/site-packages" ]; then
    export PYTHONPATH="$COLCON_CURRENT_PREFIX/lib/python3.10/site-packages:${PYTHONPATH}"
fi

# Restore previous prefix
if [ -n "$_colcon_current_prefix" ]; then
    export COLCON_CURRENT_PREFIX="$_colcon_current_prefix"
    unset _colcon_current_prefix
else
    unset COLCON_CURRENT_PREFIX
fi

Output and Logging Compatibility

Console Output Format

ROC matches colcon's console output format:

🔧 Building ROS2 workspace with roc (colcon replacement)
Workspace: /home/user/workspace

Discovered 3 packages
  - my_cpp_package (AmentCmake)
  - my_py_package (AmentPython)
  - my_msgs (AmentCmake)

Build order:
  my_msgs
  my_cpp_package
  my_py_package

Starting >>> my_msgs (AmentCmake)
  Configuring with CMake...
  ✅ CMake configure succeeded
  Building and installing...
  ✅ Build and install succeeded
Finished <<< my_msgs [2.34s]

Starting >>> my_cpp_package (AmentCmake)
  Configuring with CMake...
  ✅ CMake configure succeeded
  Building and installing...
  ✅ Build and install succeeded
Finished <<< my_cpp_package [4.12s]

Starting >>> my_py_package (AmentPython)
  Building and installing...
  ✅ Build and install succeeded
Finished <<< my_py_package [1.23s]

Build Summary:
  3 packages succeeded

✅ Build completed successfully!
To use the workspace, run:
  source install/setup.bash

Log Directory Structure

ROC maintains the same logging structure as colcon:

log/
├── latest/                 # Symlink to most recent build
│   ├── build.log          # Overall build log
│   ├── my_msgs/
│   │   └── stdout_stderr.log
│   ├── my_cpp_package/
│   │   └── stdout_stderr.log
│   └── my_py_package/
│       └── stdout_stderr.log
└── 2025-06-19_14-30-15/   # Timestamped build logs
    └── ...

Migration Guide

Switching from Colcon

For existing ROS2 projects, switching to ROC is straightforward:

1. Install ROC

# From source
git clone https://github.com/your-org/roc.git
cd roc
cargo build --release

# Or from crates.io
cargo install rocc

2. Update Build Scripts

Replace colcon commands in scripts:

Before:

#!/bin/bash
source /opt/ros/humble/setup.bash
cd /path/to/workspace
colcon build --parallel-workers 4 --cmake-args -DCMAKE_BUILD_TYPE=Release
source install/setup.bash

After:

#!/bin/bash
source /opt/ros/humble/setup.bash
cd /path/to/workspace
roc work build --parallel-workers 4 --cmake-args -DCMAKE_BUILD_TYPE=Release
source install/setup.bash

3. CI/CD Integration

Update continuous integration scripts:

GitHub Actions Example:

- name: Build workspace
  run: |
    source /opt/ros/humble/setup.bash
    roc work build --parallel-workers 2
    source install/setup.bash

Docker Example:

RUN source /opt/ros/humble/setup.bash && \
    roc work build --parallel-workers $(nproc) && \
    source install/setup.bash

Behavioral Differences

While ROC maintains high compatibility, there are some differences:

Performance Improvements

  • Faster startup: Native binary vs Python interpreter
  • Better parallelization: More efficient worker management
  • Memory efficiency: Lower memory usage during builds

Enhanced Error Handling

  • More detailed error messages: Better context and suggestions
  • Cleaner error output: Structured error reporting
  • Recovery suggestions: Actionable advice for common issues

Environment Management

  • Cleaner environments: Better isolation prevents contamination
  • Filtered variables: Only ROS-relevant variables in setup scripts
  • Windows support: Better cross-platform environment handling

Future Compatibility

Planned Features

ROC's roadmap includes additional colcon compatibility features:

Advanced Options

  • --event-handlers: Custom build event processing
  • --executor: Different parallel execution strategies
  • --log-base: Custom log directory locations
  • --install-base: Custom install directory locations

Extensions

  • Plugin system for custom build types
  • Custom event handlers
  • Advanced dependency resolution strategies

API Compatibility

ROC is designed to maintain API compatibility with colcon's extension points, enabling future integration with existing colcon plugins and extensions where appropriate.

The colcon compatibility layer ensures that ROC can serve as a drop-in replacement for colcon in virtually all ROS2 development workflows, while providing superior performance and enhanced features that improve the developer experience.