bytecodealliance / bytecodealliance/cargo-component
Generate WIT, not Rust source code
- Dominant language
- Rust
- Stars
- 593
- Forks
- 68
- PR merge metrics
- No merged PRs in 30d
Description
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:
1. 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.
2. 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:
```rust
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.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.