Bazel-like build system for ROS 2 — resolve, fetch, and build only what your launch file actually needs.
Instead of cloning and building an entire workspace upfront, launch-plus reads a
.repos manifest, generates a lockfile, and resolves a launch file on demand —
fetching only the packages actually referenced, then producing a single flattened
XML that shows every node, parameter, and remap that would be active at runtime.
A typical ROS 2 workspace like Autoware contains 200+ packages across dozens of repositories. The standard workflow requires cloning everything, installing all system dependencies, and building the full workspace before you can launch a single node — even if your launch file only touches 30 of those packages.
# Traditional ROS 2 workflow
vcs import src < autoware.repos # clone ~50 repos
rosdep install --from-paths src # install ALL system deps
colcon build # build ALL ~235 packages (30+ min)
ros2 launch autoware_launch ... # finally launch
This is slow, wasteful, and makes it hard to iterate on a subset of the system.
launch-plus treats launch files as build targets. It parses the launch graph statically, determines exactly which packages are needed, fetches only those via git sparse-checkout, and builds the minimal set:
# launch-plus workflow
launch-plus index autoware.repos # generate lockfile (one-time)
launch-plus build autoware_launch autoware.launch.xml \
sensor_model:=sample_sensor_kit \
vehicle_model:=sample_vehicle \
map_path:=/path/to/map \
--clean --rosdep # fetch + build only what's needed
The resolver also produces a flattened, fully-resolved XML that shows the complete launch graph with all includes inlined, conditionals evaluated, and variables substituted — invaluable for debugging and CI validation.
- Lazy fetching — packages are sparse-checked out on demand; no full clone required
- Minimal builds — only the transitive dependencies of your launch target are built
- Static analysis — resolve launch files without building packages or running ROS nodes
- Python launch support — executes
generate_launch_description()with shimmedlaunch/launch_rosimports; no ROS 2 Python packages needed on the resolver host - OpaqueFunction handling — executes arbitrary Python callables with patched filesystem access, transparently fetching packages as they are accessed
- Portable output — resolved XML uses
$(find-pkg-share pkg)/...paths that work across machines and environments - Lockfile pinning — reproducible builds via commit-SHA-pinned lockfiles
- rosdep integration — automatically installs system dependencies for the packages being built
Current scope: launch-plus is a build-time tool today (resolve + build). Execution support — both a built-in executor and integration with
ros2 launchand third-party launchers — is on the roadmap.
- Rust toolchain — rustup.rs (edition 2024, MSRV 1.85)
- Python 3.10+ in
PATH— used to evaluate Python launch files and$(eval ...)substitutions in XML - Git — for sparse-checkout operations
- ROS 2 — source your ROS 2 environment (
source /opt/ros/<distro>/setup.bash)
git clone https://github.com/paulsohn/launch-plus.git
cd launch-plus
cargo build --bin launch-plus --release
# binary: target/release/launch-plusA pre-generated lockfile for a full Autoware workspace
is included in example/autoware/. You can run the
resolver immediately without writing a manifest or running index first.
# Source ROS 2 first (only needed for --rosdep)
source /opt/ros/humble/setup.bash
cd example/autoware
# Preview-resolve: produces flattened XML without building
cargo run --bin launch-plus -- resolve -d autoware_launch autoware.launch.xml \
sensor_model:=sample_sensor_kit \
vehicle_model:=sample_vehicle \
map_path:="[map_path]" \
--allow-global-arg-cascade \
--apply-launch-arg-defaults \
--apply-opaque-file-access \
--allow-including-unportable-path \
--show-args \
--inline-params \
--rosdep \
--preview \
> resolved.launch.xmlOn first run, the resolver sparse-clones only the packages it needs into
example/autoware/src/ (this may take a few minutes). Subsequent runs reuse
the already-fetched packages and are fast.
The pre-generated output files are included for reference:
To build the resolved packages (requires a sourced ROS 2 environment and colcon):
cargo run --bin launch-plus -- build -d autoware_launch autoware.launch.xml \
sensor_model:=sample_sensor_kit \
vehicle_model:=sample_vehicle \
map_path:="[map_path]" \
--allow-global-arg-cascade \
--apply-launch-arg-defaults \
--apply-opaque-file-access \
--allow-including-unportable-path \
--rosdep \
--colcon-flagfile colcon-flags.txt- Write a
.reposfile listing your repositories (standard vcstool format) - Generate a lockfile:
launch-plus index - Resolve:
launch-plus resolve <pkg> <launcher> [args...] - Build:
launch-plus build <pkg> <launcher> [args...] --clean --rosdep
See the Getting Started guide for a full walkthrough.
| Command | Description |
|---|---|
index |
Parse .repos files and generate a lockfile |
update |
Re-resolve refs and update lockfile SHAs |
resolve |
Resolve and flatten a launch file to XML (no build) |
check |
Like resolve but exits non-zero on warnings/errors |
build |
Resolve, fetch dependencies, and run colcon build |
build-pkg |
Build package(s) by name with transitive dependency fetching |
test |
Like build but includes test_depend packages |
fetch |
Sparse-checkout specific packages from the lockfile |
clean |
Remove fetched packages |
Run launch-plus <command> --help for detailed usage of each command.
Commands that refer to source code support workspace state flags:
| Flag | Short | When to use |
|---|---|---|
--clean |
-c |
CI / reproducible runs — resets repos to lockfile SHAs |
--dirty |
-d |
Local iteration — uses whatever is on disk |
| (default) | Verifies HEAD matches lockfile SHA; errors on mismatch |
| Document | Description |
|---|---|
| Motivation | Why launch-plus exists and what problems it solves |
| Core Concepts | Lockfiles, sparse checkout, portable paths, and more |
| Getting Started | Step-by-step tutorial for your own project |
| Architecture | How the resolver, fetcher, and builder work internally |
| Supported Environments | Platforms, ROS distros, and known limitations |
| FAQ | Common questions and answers |
| Contributing | Development setup and contribution guidelines |
- ROS 2 developers working with large multi-repository workspaces who want faster iteration cycles
- CI/CD pipelines that need to build and test only the packages affected by a launch configuration change
- System integrators who want a clear, auditable view of what a launch file actually does — every node, parameter, and remap in one flat XML
- Anyone tired of waiting 30+ minutes for a full workspace build when they only need a handful of packages
Apache-2.0 — see LICENSE.