Currently, to the best of my knowledge, cargo component generates a src/bindings.rs file using a version of wit-bindgen baked directly into the executable cargo-component itself. Running cargo component new generates a project that depends on wit-bindgen-rt at a matching version of what cargo-component has baked in to itself.
This is problematic to the development of wit-bindgen, unfortunately, because the generated code using wit-bindgen 0.A.0 generally requires wit-bindgen-rt 0.A.0 as well, and you can't mix and match versions. Mismatched versions can arise relatively easily with cargo-component in two situations:
- An older project might update to using a newer
cargo-component executable, meaning that the Cargo.toml depends on an older wit-bindgen-rt while the executable generates bindings with a newer wit-bindgen version.
- An older project might update
wit-bindgen-rt but fail to update cargo-component, producing the inverse problem where an older wit-bindgen is used with a newer wit-bindgen-rt.
This is coming up as I'm doing refactoring in wit-bindgen and shuffling things around, and ideally I'd prefer to not break cargo component users because at this time if anything is added to wit-bindgen-rt then users will break.
As an alternative, what I might recommend is to instead have cargo component manage WIT, not generated source code. The basic idea is that cargo component would generate-and-manage src/bindings.wit instead of src/bindings.rs. The template for cargo component new would add a dependency on wit-bindgen but critically wouldn't actually generate any code. For example the generated file might look like:
wit_bindgen::generate!("./src/bindings.wit");
fn main() {
println!("hello!");
}
This should be more idiomatic in terms of wit-bindgen usage where it's "just" a call to the generate! macro with various options. The key difference is that the input *.wit is completely managed by cargo component and handles things like dependencies and such which wit-bindgen otherwise doesn't do.
My hope is that this wouldn't break things like IDE integration workflows as they in theory already need to work with procedural macros. The upside though is that the cargo component executable wouldn't even need to depend on wit-bindgen itself because it doesn't generate any Rust code. Instead it only generates a reference to wit-bindgen and then a macro invocation. The WIT management all remains in cargo component, however.
This would additionally solve the problem of updating/changing wit-bindgen as, after inception, it's a per-project decision of when to update wit-bindgen which is orthogonal from using cargo component as a build tool.
Currently, to the best of my knowledge,
cargo componentgenerates asrc/bindings.rsfile using a version ofwit-bindgenbaked directly into the executablecargo-componentitself. Runningcargo component newgenerates a project that depends onwit-bindgen-rtat a matching version of whatcargo-componenthas baked in to itself.This is problematic to the development of
wit-bindgen, unfortunately, because the generated code usingwit-bindgen 0.A.0generally requireswit-bindgen-rt 0.A.0as well, and you can't mix and match versions. Mismatched versions can arise relatively easily withcargo-componentin two situations:cargo-componentexecutable, meaning that theCargo.tomldepends on an olderwit-bindgen-rtwhile the executable generates bindings with a newerwit-bindgenversion.wit-bindgen-rtbut fail to updatecargo-component, producing the inverse problem where an olderwit-bindgenis used with a newerwit-bindgen-rt.This is coming up as I'm doing refactoring in
wit-bindgenand shuffling things around, and ideally I'd prefer to not breakcargo componentusers because at this time if anything is added towit-bindgen-rtthen users will break.As an alternative, what I might recommend is to instead have
cargo componentmanage WIT, not generated source code. The basic idea is thatcargo componentwould generate-and-managesrc/bindings.witinstead ofsrc/bindings.rs. The template forcargo component newwould add a dependency onwit-bindgenbut critically wouldn't actually generate any code. For example the generated file might look like:This should be more idiomatic in terms of
wit-bindgenusage where it's "just" a call to thegenerate!macro with various options. The key difference is that the input*.witis completely managed bycargo componentand handles things like dependencies and such whichwit-bindgenotherwise doesn't do.My hope is that this wouldn't break things like IDE integration workflows as they in theory already need to work with procedural macros. The upside though is that the
cargo componentexecutable wouldn't even need to depend onwit-bindgenitself because it doesn't generate any Rust code. Instead it only generates a reference towit-bindgenand then a macro invocation. The WIT management all remains incargo component, however.This would additionally solve the problem of updating/changing
wit-bindgenas, after inception, it's a per-project decision of when to updatewit-bindgenwhich is orthogonal from usingcargo componentas a build tool.