Skip to content

Duplicate extern declarations causing clashing_extern_declarations warnings #559

@gsokoll

Description

@gsokoll

Description

When building rclrs, the compiler emits warnings about rosidl_typesupport_c__get_* functions being declared with different signatures. This occurs because the same C functions are declared in two places with different Rust return types.

Example warning

warning: `rosidl_typesupport_c__get_message_type_support_handle__action_msgs__srv__CancelGoal_Response` redeclared with a different signature
    --> rclrs/src/rcl_bindings_generated_jazzy.rs:8579:5
     |
8579 | /     pub fn rosidl_typesupport_c__get_message_type_support_handle__action_msgs__srv__CancelGoal_Response(
8580 | |     ) -> *const rosidl_message_type_support_t;
     | |______________________________________________^ this signature doesn't match the previous declaration
     |
    ::: rclrs/src/vendor/action_msgs/srv.rs:244:9
     |
 244 | /         fn rosidl_typesupport_c__get_message_type_support_handle__action_msgs__srv__CancelGoal_Response(
 245 | |         ) -> *const std::ffi::c_void;
     | |_____________________________________- previously declared here
     |
     = note: expected `unsafe extern "C" fn() -> *const c_void`
                found `unsafe extern "C" fn() -> *const rosidl_message_type_support_t`

Affected functions (6 instances)

  • rosidl_typesupport_c__get_message_type_support_handle__action_msgs__msg__GoalInfo
  • rosidl_typesupport_c__get_message_type_support_handle__action_msgs__msg__GoalStatus
  • rosidl_typesupport_c__get_message_type_support_handle__action_msgs__msg__GoalStatusArray
  • rosidl_typesupport_c__get_message_type_support_handle__action_msgs__srv__CancelGoal_Request
  • rosidl_typesupport_c__get_message_type_support_handle__action_msgs__srv__CancelGoal_Response
  • rosidl_typesupport_c__get_service_type_support_handle__action_msgs__srv__CancelGoal

Root cause

The same rosidl_typesupport_c__get_* functions are being declared in two places:

  1. rosidl_generator_rs generates extern declarations in the vendored message crates (e.g. vendor/action_msgs/srv.rs) with return type *const std::ffi::c_void
  2. bindgen generates extern declarations in rcl_bindings_generated_*.rs with return type *const rosidl_message_type_support_t (or rosidl_service_type_support_t)

Both declarations are ABI-compatible at runtime (the pointer types have identical representation), but Rust's clashing_extern_declarations lint correctly flags the type-level inconsistency.

Proposed fix

Add blocklist patterns to the bindgen configuration in rclrs/build.rs to prevent bindgen from generating declarations for typesupport functions that are already provided by rosidl_generator_rs:

let bindings = bindgen::Builder::default()
    .header("src/rcl_wrapper.h")
    // ... existing configuration ...
    .blocklist_function("rosidl_typesupport_.*__get_message_type_support_handle.*")
    .blocklist_function("rosidl_typesupport_.*__get_service_type_support_handle.*")
    .blocklist_function("rosidl_typesupport_.*__get_action_type_support_handle.*")
    // ... rest of builder ...

This approach:

  • Keeps typesupport declarations with their respective message crates where they semantically belong
  • Prevents bindgen from duplicating them as a side effect of rcl headers including rosidl headers
  • Uses regex patterns to avoid playing whack-a-mole as new message types are added

Pre-implementation checklist

  • Verify rclrs doesn't directly call any bindgen-generated typesupport functions (should be going through message crate APIs)
  • Grep for affected function names in rclrs source to confirm no direct usage

Testing

  • Verify clean build with no clashing_extern_declarations warnings on Humble, Jazzy, and Rolling
  • Run existing test suite to confirm no regressions

I'm happy to develop and submit a PR for this fix if it helps.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions