How to build a crate multiple times for different versions of a dependency?

I want to build a crate multiple times for different versions of a dependency.

The first idea I had was defining an optional dependency for each version in Cargo.toml, e.g:

[dependencies]
pulldown-cmark_0_9_2 = { package = "pulldown-cmark", version = "=0.9.2", optional=true }
pulldown-cmark_0_8_0 = { package = "pulldown-cmark", version = "=0.8.0", optional=true }

There are several things I dislike about this approach:

  1. It requires me to define imports as follows (which is just cumbersome and not DRY):

    #[cfg(any(feature = "pulldown-cmark_0_8_0"))]
    use pulldown_cmark_0_8_0 as pulldown_cmark;
    #[cfg(any(feature = "pulldown-cmark_0_9_2"))]
    use pulldown_cmark_0_9_2 as pulldown_cmark;
    
  2. If the API changes between versions the cfg attributes become very cumbersome ... ideally I could just define something like #[cfg(dep_version(pulldown_cmark >= "0.8.0"))].

  3. For some reason cargo cannot handle multiple dependencies on different minor versions of a crate?
    The following fails with error: failed to select a version for `pulldown-cmark` for me:

    [dependencies]
    pulldown-cmark_0_9_2 = { package = "pulldown-cmark", version = "=0.9.2", optional=true }
    pulldown-cmark_0_9_1 = { package = "pulldown-cmark", version = "=0.9.1", optional=true }
    

So I am starting to think it might make more sense to automate this with an external build script that runs cargo add but that does feel like a hack. This seems like a problem somebody would have already solved but the search engines are failing me. Do you have an idea? Ideally the build artifact names would contain the version number of the dependency.

Some more context might help. For example, it sounds like your crate is a binary crate, not a library crate, but it would be helpful if you clarify this.

And you don't provide any reason as to why you want to build the crate multiple times, using different versions of dependencies. Doing so could be useful to motivate people to put more effort into figuring out an answer/solution, since they could understand how what's being asked for actually is a sensible thing in the first place. And also it can help to avoid any XY problem, or it could potentially allow alternative solutions that somehow approach the problem at a higher level.

4 Likes

I want to provide a website where you can test out various Rust libraries in your browser ... the libraries are compiled to WASM by wrapping them in some library crates I define myself. The website will be similar to the Rust Playground but instead of inputting Rust code you'll provide the inputs for a function of the library. Like the Rust Playground links will also be sharable ... to make the links link to reproducible results I want to encode the version of the library used in the URL.

Supporting multiple versions for a library would require me to build my library crate multiple times against different versions of the dependency.