Skip to content

fix(generator): do not register generated crates in the rust_packages - #37

Open
azerupi wants to merge 1 commit into
ros2-rust:mainfrom
azerupi:fix/skip-rust-packages-marker-for-ros-env
Open

fix(generator): do not register generated crates in the rust_packages#37
azerupi wants to merge 1 commit into
ros2-rust:mainfrom
azerupi:fix/skip-rust-packages-marker-for-ros-env

Conversation

@azerupi

@azerupi azerupi commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Problem

The rust_packages ament index resource exists so that colcon-ros-cargo can inject a [patch.crates-io.<pkg>] entry pointing at an installed crate's source. Since #21, generated interface crates use ros-env by adding [package.metadata.ros-env] include = true in resource/Cargo.toml. Such crates should be used through ros-env instead of being added as a cargo dependency and patched.

Creating the marker file anyway means colcon-ros-cargo emits a patch that nothing uses, and Cargo records every unused patch as a [[patch.unused]] block in the consumer's Cargo.lock. The lockfile therefore depends on which interface packages happen to be present on the prefix, not on what the crate actually depends on. The consequence is that locks differ between machines, workspaces and branches and therefore result in constant merge conflicts. This is the issue that I reported in colcon/colcon-ros-cargo#37

cargo-ament-build PR #35 already fixed exactly this for ament_cargo packages, it skips the rust_packages marker when the manifest opts into ros-env. But interface packages are ament_cmake and their marker is written by this repo's CMake, unconditionally

Reproduction

Here is a minimal reproduction to test. Create a a two-package workspace.

Setup used to reproduce

  • Ubuntu 24.04
  • ROS 2 Jazzy
  • rustc 1.86
  • cargo-ament-build 0.1.11
  • colcon-ros-cargo 0.2.0
  • ros-env 0.2.0
  • rosidl_runtime_rs 0.6.0.

src/mre_msgs

# CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(mre_msgs)
find_package(ament_cmake REQUIRED)
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME} "msg/Foo.msg")
ament_package()
# msg/Foo.msg
int32 value

with <build_type>ament_cmake</build_type>, <buildtool_depend>rosidl_default_generators</buildtool_depend> and <member_of_group>rosidl_interface_packages</member_of_group> in package.xml.

src/mre_node

# Cargo.toml
[package]
name = "mre_node"
version = "0.0.1"
edition = "2021"

[dependencies]
ros-env = "0.2.0"
// src/main.rs
use ros_env::mre_msgs::msg::Foo;
fn main() { let f = Foo::default(); println!("{}", f.value); }

package.xml declares <build_type>ament_cargo</build_type> and <depend>mre_msgs</depend>.

Then:

$ colcon build --packages-up-to mre_node

mre_msgs is not a Cargo dependency of anything, yet all three of these appear:

  1. the marker file at install/mre_msgs/share/ament_index/resource_index/rust_packages/mre_msgs
  2. the patch colcon-ros-cargo derives from it in .cargo/config.toml
[patch.crates-io.mre_msgs]
path = ".../install/mre_msgs/share/mre_msgs/rust"
  1. The [[patch.unused]] in the Cargo.lock file
[[patch.unused]]
name = "mre_msgs"
version = "0.0.1"

Fix

We stop generating the marker file. We don't need to do this conditionally because resource/Cargo.toml.em emits the ros-env opt-in unconditionally.

Rollout impact

When this generator change reaches the ROS buildfarm, any user of rclrs that still declares a generated interface crate as a direct Cargo dependency (std_msgs = "*", sensor_msgs = "*", …) and relies on colcon-ros-cargo patching instead of using rosenv will start to see their builds fail after updating their ROS apt packages.

… index

Generated interface crates opt into `ros-env` by default since ros2-rust#21
(`[package.metadata.ros-env] include = true` in the Cargo.toml template),
which means they are `include!()`d from the source installed to
`share/<pkg>/rust` rather than resolved as Cargo dependencies.

The `rust_packages` ament index resource exists only so that
`colcon-ros-cargo` can emit a `[patch.crates-io.<pkg>]` entry for packages
that *are* real Cargo dependencies. Registering generated crates therefore
produces a patch that nothing in the dependency graph uses, and Cargo
records those as `[[patch.unused]]` in every consumer's `Cargo.lock`. That
makes the lockfile depend on whichever interface packages happen to be
present on the prefix: locks differ between machines and `--locked` builds
fail on any extra patched crate.

Stop registering the resource. The `install(DIRECTORY ...)` of the crate
source is kept, since that is what `ros-env` reads from `AMENT_PREFIX_PATH`.

This is the generator-side counterpart of cargo-ament-build PR ros2-rust#35, which
already skips the same marker for `ament_cargo` packages that opt into
`ros-env`.

Verified with a two-package workspace (an `ament_cmake` interface package
plus an `ament_cargo` node consuming it through `ros-env`) built with
cargo-ament-build 0.1.11 and colcon-ros-cargo 0.2.0. Before the change the
marker file, the `[patch.crates-io]` entry and a `[[patch.unused]]` block
for the interface package are all present; after it all three are gone and
the node still compiles and links.

Note this is a behaviour change for consumers that still declare generated
interface crates as direct Cargo dependencies: those relied on
`colcon-ros-cargo` patching them in and should migrate to `ros-env`.
@maspe36

maspe36 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Thank you for noticing this and putting up the fix @azerupi! Regarding the roll out impact, I believe this is inevitable unfortunately. End users can buy time by pinning to an older rosidl_generator_rs if they want. The generated crates can also still be consumed as independent crates with manually curated patches, but we will just no longer be automatically generating the patches (for generated interfaces specifically) via colcon-ros-cargo.

We will need to make sure a new version of rclrs is released as well around this time.

cc: @esteve @cottsay
Anything else I'm missing here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants