Exclusion of binary targets during the construction process of a Rust project

Hello my dears,
I have been fighting with the developers of my favourite framework ROS2 for some time now, explicitly here the people who provide the ROS2 RUST api. For some reason, a method that is supposed to create a ros2 builtin_interfaces/msg/Time object stopped working some time ago. This is because the pointer arithmetic under the bonnet of the library is spinning around and constantly renaming dependencies during compilation. To test the whole thing, I built a sample application that calls exactly the method that is supposed to create the object mentioned above.

/// Creates a SimplePublisherNode, initializes a node and publisher, and provides
/// methods to publish a simple "Hello World" message on a loop in separate threads.

/// Imports the Arc type from std::sync, used for thread-safe reference counting pointers,
/// and the StringMsg message type from std_msgs for publishing string messages.
use std::{sync::Arc,time::Duration};
use std_msgs::msg::Header;
// / SimplePublisherNode struct contains node and publisher members.
// / Used to initialize a ROS 2 node and publisher, and publish messages.
struct SimplePublisherNode {
    node: Arc<rclrs::Node>,
    _publisher: Arc<rclrs::Publisher<Header>>,
}
/// Creates a new SimplePublisherNode by initializing a node and publisher.
///
/// The `new` function takes a context and returns a Result containing the
/// initialized SimplePublisherNode or an error. It creates a node with the
/// given name and creates a publisher on the "publish_hello" topic.
///
/// The SimplePublisherNode contains the node and publisher members.
impl SimplePublisherNode {
    /// Creates a new SimplePublisherNode by initializing a node and publisher.
    ///
    /// This function takes a context and returns a Result containing the
    /// initialized SimplePublisherNode or an error. It creates a node with the
    /// given name and creates a publisher on the "publish_hello" topic.
    ///
    /// The SimplePublisherNode contains the node and publisher members.
    fn new(context: &rclrs::Context) -> Result<Self, rclrs::RclrsError> {
        let node = rclrs::create_node(context, "simple_publisher").unwrap();
        let _publisher = node
            .create_publisher("publish_hello", rclrs::QOS_PROFILE_DEFAULT)
            .unwrap();
        Ok(Self { node, _publisher })
    }

    /// Publishes a "Hello World" message on the publisher.
    ///
    /// Creates a StringMsg with "Hello World" as the data, publishes it on
    /// the `_publisher`, and returns a Result. This allows regularly publishing
    /// a simple message on a loop.
    fn publish_data(&self) -> Result<(), rclrs::RclrsError> {
        let msg: Header = Header {
            frame_id: "Hello World".to_string(),
            stamp: self.node.get_clock().now().to_ros_msg(),
        };
        self._publisher.publish(msg).unwrap();
        Ok(())
    }
}

/// The main function initializes a ROS 2 context, node and publisher,
/// spawns a thread to publish messages repeatedly, and spins the node
/// to receive callbacks.
/// 
/// It creates a context, initializes a SimplePublisherNode which creates
/// a node and publisher, clones the publisher to pass to the thread,  
/// spawns a thread to publish "Hello World" messages repeatedly, and
/// calls spin() on the node to receive callbacks. This allows publishing
/// messages asynchronously while spinning the node.
fn main() -> Result<(), rclrs::RclrsError> {
    let context = rclrs::Context::new(std::env::args()).unwrap();
    let publisher = Arc::new(SimplePublisherNode::new(&context).unwrap());
    let publisher_other_thread = Arc::clone(&publisher);
    std::thread::spawn(move || -> () {
        std::iter::repeat(()).for_each(|()| {
            std::thread::sleep(Duration::from_millis(1000));
            publisher_other_thread.publish_data().unwrap()
        });
    });
    rclrs::spin(publisher.node.clone())
}

This application is called up within the packet via a binary target in Cargo.toml:

[package]
name = "simple_ros_rs"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rclrs = "*"
std_msgs = "*"
geometry_msgs="*"
console = "0.15.8"

[[bin]]
name="simple_publisher"
path="src/simple_publisher.rs"

[[bin]]
name="teleop"
path="src/teleop.rs"

[[bin]]
name="header_pub"
path="src/header_pub.rs"

The application is called header_pub. Is there a way to exclude this binary when building the package? In this case, the package must be built via colcon or cargo-ament-build. I know that both also accept cargo arguments. I would hate to move a single binary target to another git branch just to make the package build properly.

If you add an optional Cargo feature and use the required-features field:

[features]
enable_header_pub = []

[[bin]]
name = "header_pub"
path = "src/header_pub.rs"
required-features = ["enable_header_pub"]

then the binary will only be built when you pass the --features enable_header_pub option to Cargo.

Thanks. I'll do it.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.