Skip to content

Support runtime executable dependencies. #7971

Open
@nathan-at-least

Description

Describe the problem you are trying to solve

Base Problem Statement:

Some executables depend on the presence of other executables at "installed runtime", so that they can execute these "executable dependencies" as separate subprocesses. That dependency is an API that needs versioning for effective deployment/installation.

As a contrived example, imagine a commandline rust refactoring tool requires being able to execute cargo-config.

Variant 1:

In addition to the Base Problem Statement, the user must be able to execute the dependency executable directly.

Example: Whenever a user installs cargo install cargo-super-audit-helper they are guaranteed to be able to run cargo-audit after that, since cargo-super-audit-helper has an "executable dependency" on cargo-audit.

Variant 2:

In addition to the Base Problem Statement it's important to not expose the user to the dependency executables for hygiene / clean interfaces / clean separation of concerns.

Describe the solution you'd like

My personal preference is to solve Variant 1 along these lines:

  • Introduce a new Cargo.toml section [executable-dependencies] whose entries are similar to [dependencies] entries.
  • If crate A has B = <v1spec> in [executable-dependencies] then cargo install A behaves the same as running cargo install --version <v1spec> B && cargo install A.

Note that final && command is intended to be precise when it comes to name/version collisions, so if there's a name/version collision with B = <v1spec> that will behave exactly the same as if the user executed cargo install --version <v1spec> B directly (and no attempt to install A is attempted). This might make name/version collisions cumbersome for the user, but my intuition is at the very least it will be easy for all cargo users to understand what's happening and why.

I prefer this approach because I believe it's relatively simple for all cargo users to understand.

Notes

  • My preferred solution this assumes that if an executable from A is on the executable search $PATH then the executables from B are also, so that the code in A can do something like std::process::Command("B").output() successfully.

  • A solution to Variant 2 might build on my proposed solution by placing the dependency binary in a private location and somehow expose the path to the code in A perhaps an environment variable.

  • Related Tickets: I believe my proposed solution addresses Enable 'cargo install' to install binary-crates according to a spec of dependencies #5120. I don't think it addresses Make commands in dev-dependencies available to run #2267 even though that seems similar. I think the build script approach makes sense for Make commands in dev-dependencies available to run #2267, unless we want to also introduce [dev-executable-dependencies].

  • In all of this discussion of course, I am assuming all dependencies are crates and that executable crates provide 1 or more executables (perhaps transitively). This feature wouldn't facilitate depending on non-cargo binaries as a simplification.

  • Variant 2 seems pretty similar to just having the dependency provide a public API that the crate consumes as a normal library. It's different for two reasons: First, an executable commandline interface is an API. Not every dependency ensures they provide a library whose interface matches the executable perfectly. Second, the process abstraction matters for many reasons: resource management, concurrency, error handling, I/O, etc...

Metadata

Assignees

No one assigned

    Labels

    A-crate-dependenciesArea: [dependencies] of any kindC-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`Command-installS-needs-designStatus: Needs someone to work further on the design for the feature or fix. NOT YET accepted.Z-bindepsNightly: binary artifact dependencies

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions