Support different versions of the same dependency within a workspace #13594
Description
Problem
My Cargo workspace has multiple entry points that compile to executable/bin or dylib targets. Currently, when placed within a workspace, Cargo will attempt to combine their dependencies where they share the same "compatible" versions of a dependency.
The problem is that these project consume third party dependencies that have conflicting versions - either because library maintainers don't adhere to semver correctly or because library maintainers choose to specify exact versions of a dependency (e.g. =0.0.40
).
My projects can be compiled on their own without issue however, if they share a workspace, cargo build
will fail because Cargo tries/fails to resolve these conflicting dependencies.
Example Case
I have a workspace that has three packages
/crates-main
/project-bin
Cargo.toml
/project-types
Cargo.toml
/crates-plugins
/plugin-dynamic-lib
Cargo.toml
Cargo.toml
crates-main/project-bin
This is the main entrypoint for my application which compiles to an executable. This program is able to consume dynamic libraries using the libloading
crate.
crates-main/project-types
This is a shared library compiled as a lib
that has no external dependencies, only exporting types to be used by both the "plugins" and the main executable (a.k.a. the "contract").
crates-plugins/plugin-dynamic-lib
This is a library that is compiled to a dylib. It depends on
project-typesfor the types required to initialize a plugin and will be consumed by the executable produced by
project-bin`
Note that this package could also be an executable, I am using a dylib
in my example because that's my current use case
In summary we have 2 packages that compile to binaries (./project-bin
and ./plugin-dynamic-lib.so
) and one shared library that is statically linked within those two crates.
Problem
As an example, assume project-bin
consumes log = "=0.4.20"
and plugin-dynamic-lib
consumes log = 0.4.21
(indirectly via a third party dependency external to the workspace).
In a combined workspace, cargo build
will error saying that it cannot resolve a compatible version between the two specified.
In reality, these packages will compile to separate binaries so version conflicts of dependencies would not result in a material conflict at runtime.
Current Solution
To get around this today, I simply avoid using a Cargo workspace and compile the projects independently of each other from a build script where shared dependencies are referenced via my_pkg = { path = "../path/to/pkg" }
.
The issue with this approach is that rust-analyzer is unable to provide suggestions for the packages when the top level folder is open in the editor - resulting in a less than ideal development experience
Proposed Solution
A few possible solutions to this:
Option 1
Allow for multiple incompatible dependencies to coexist within a workspace if their versions cannot be combined and their consumers are of crate-type
bin
or dylib
e.g. a package in crates.io with the latest version of 0.4.21
Consumer A
[bin]
[dependencies]
dependency = `^0.4.0`
Consumer B
[bin]
[dependencies]
dependency = `=0.4.20`
Consumer A would get 0.4.21
Consumer B would get 0.4.20
Option 2
Devise a way for rust-analyzer to work with multiple nested projects within a parent directory
Option 3
Perhaps some kind of support for workspaces, isolating dependencies between the workspaces
Notes
No response
Activity