What's the most elegant way to implement Cargo plugins?

⚓ Rust    📅 2025-08-08    👤 surdeus    👁️ 6      

surdeus

Currently, I’ve implemented two cargo plugins, ros_new and ros_add. Under the hood, they’re just advanced cargo drivers that add ros2 related package.xml handling. Ok, I’ll show, what I mean. For Example in ros_add, to manipulate the Cargo.toml, I’m doing the following:

    if !(matches.get_flag("no_cargo_toml") || matches.get_flag("buildtool"))
        && Path::new("Cargo.toml").exists()
    {
        println!("Attempting to add '{package_name}' to Cargo.toml...");
        let mut cargo_add = Command::new("cargo");
        cargo_add.arg("add").arg(dependency);
        // Add --color if specified
        if let Some(color) = matches.get_one::<String>("color") {
            cargo_add.args(["--color", color]);
        }

        // Only add --build if the flag was explicitly given
        if matches.get_flag("build") || matches.get_flag("--build-export") {
            cargo_add.arg("--build");
        }

        PathDoc::new("Cargo.toml".to_string(), dependency_type)
            .map(|ok| ok.add_dependency_to_cargo_toml(package_name))
            .unwrap_or_else(|dings| {
                eprintln!("{dings}");
                Err(dings)
            })
            .unwrap_or_else(|dings| println!("{dings}"));
    }

As you can see, the first step is simply to run Cargo with the dependency name and some Cargo flags. Then I need to run my own Cargo.toml editing mechanic because, regardless of why Cargo fails, it sends error 101, which doesn't tell me anything. Now that I’ve implemented them, I’m wondering if there’s a more elegant way of doing things. I mean, Cargo itself is a Rust crate, right? Is it possible to implement a Cargo plugin by using Cargo as a dependency and extending it, rather than running Cargo under the hood? Has anyone done that before?

2 posts - 2 participants

Read full topic

🏷️ Rust_feed