Skip to content

Generate WIT, not Rust source codeΒ #387

@alexcrichton

Description

@alexcrichton

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:

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.

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