Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cargo install --name: install with a renamed executable #12366

Open
philpax opened this issue Jul 17, 2023 · 11 comments
Open

cargo install --name: install with a renamed executable #12366

philpax opened this issue Jul 17, 2023 · 11 comments
Labels
C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` Command-install E-medium Experience: Medium S-needs-design Status: Needs someone to work further on the design for the feature or fix. NOT YET accepted.

Comments

@philpax
Copy link
Contributor

philpax commented Jul 17, 2023

Problem

I'm working on a platform where users may be on different versions at a time. To help test with these versions, I'd like to install multiple versions of the binary with cargo install with different names specified at install-time, so that I can use them separately.

Unfortunately, cargo install does not support this at present - the only name configuration can be done in the manifests, which means there's no way to install a different version of the application with a different name.

Aside from the multi-version scheme I've described, it would also be useful for having binaries with different features installed. I work on another project that builds with and without GPU support as a compile-time feature; I'd like to make sure that both versions work equivalently for users without overriding them each time I install.

Proposed Solution

I'd like a --name parameter to be added, so that the resulting binary can be renamed:

cargo install --path cli --name ambient
cargo install --git https://github.com/AmbientRun/Ambient.git --tag v0.2.1 --name ambient-0.2.1
cargo install --git https://github.com/AmbientRun/Ambient.git --rev 123abcdef --name ambient-123abcdef
# ...

where each binary would have the name specified.


I've implemented a hacky version of this in our internal development tool by cargo install-ing to a temporary directory, and then moving the resulting binary into CARGO_HOME/bin with its resulting name: https://github.com/AmbientRun/Ambient/blob/0e3fa3dbc923d4b010a524d9e78a5aa204c79b7c/campfire/src/install.rs#L17-L66

This works, but it's not particularly clean: cargo install warns about the temp directory not being in the PATH, as well as it replacing the existing binary). Official support would make this much nicer.

Notes

This is a successor issue to #11413, as suggested by @weihanglo.

@philpax philpax added C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-triage Status: This issue is waiting on initial triage. labels Jul 17, 2023
@weihanglo
Copy link
Member

Thank you for filing this issue and the use cases. Look like a useful feature!

There are some open design questions we need to decide (probably more but I am forgetting):

  • The way cargo install finding available binaries is a bit weirder than we thought — It tries to install all [bin] targets if nothing specified, so cargo install --git <url> --name <name> won't work if there are more than one binary in that package. I don't know if it is ergonomic enough.

  • Flag name bikeshedding: --name, --rename, or a magic --bin oldname:newname. I don't like the last one with magic string, but it is indeed a way to avoid writing lengthy --bin oldname --name newname. For example

  • The current installed binary tracker uses the package ID internal representation to record what have been installed (code lives here). For example, this is what you gets after cargo install cargo-update --bin cargo-install-update.

    {
      "installs": {
        "cargo-update 13.0.4 (registry+https://github.com/rust-lang/crates.io-index)": {
          "version_req": null,
          "bins": [
            "cargo-install-update",
          ],
          "features": [],
          "all_features": false,
          "no_default_features": false,
          "profile": "release",
          "target": "aarch64-apple-darwin",
          "rustc": "rustc 1.73.0-nightly ..."
        }
      }
    }

    If you then run cargo install cargo-update --bin cargo-install-update-config, the new binary will be appended to "bins" array:

    {
      "installs": {
        "cargo-update 13.0.4 (registry+https://github.com/rust-lang/crates.io-index)": {
          "version_req": null,
          "bins": [
            "cargo-install-update",
    +       "cargo-install-update-config",
          ],
          ...
       }
    }

    How are we going to track the renamed information with the current tracker structure? Without thinking about it too much, I feel like aforementioned magic strings could work, though I really hate the idea 😂. We've also stored all unrecognized fields in other so we can also explore extending the structure.

A side note: if you run cargo +stable install pkg --bin bin_one then cargo +nightly install pkg --bin bin_two. The rustc fields would be overwritten. I personally think the current tracker format is already a bit broken 😞.

@weihanglo
Copy link
Member

weihanglo commented Jul 17, 2023

Note that this is not accepted by the Cargo team. We generally discuss the design first, and if we are happy with it then we do an FCP to solicit feedback from the team and the community.

@rustbot label +S-needs-design +E-medium +Command-install -S-triage

@rustbot rustbot added Command-install E-medium Experience: Medium S-needs-design Status: Needs someone to work further on the design for the feature or fix. NOT YET accepted. and removed S-triage Status: This issue is waiting on initial triage. labels Jul 17, 2023
@philpax
Copy link
Contributor Author

philpax commented Jul 17, 2023

Oh wow, yeah - I imagined there might be additional bits of complexity along the way, but you never know just how much!

  • The way cargo install finding available binaries is a bit weirder than we thought — It tries to install all [bin] targets if nothing specified, so cargo install --git <url> --name <name> won't work if there are more than one binary in that package. I don't know if it is ergonomic enough.

Yes, good point - there's not always one binary, so a single --name option might not make sense.

  • Flag name bikeshedding: --name, --rename, or a magic --bin oldname:newname. I don't like the last one with magic string, but it is indeed a way to avoid writing lengthy --bin oldname --name newname. For example

Perhaps --rename oldname:newname, with oldname being optional if there's only one binary selected for build?

That seems to strike a good balance between clarity and ease of use. (Is there any precedent for this kind of map-one-target-to-another in the ecosystem?)

  • How are we going to track the renamed information with the current tracker structure? Without thinking about it too much, I feel like aforementioned magic strings could work, though I really hate the idea 😂. We've also stored all unrecognized fields in other so we can also explore extending the structure.

Yeah, it seems like extending the format in the long-term is the right call, especially with what you mentioned in the side note. In the short-term, the magic strings could work (ambient:ambient-v0.2.1, ambient:ambient-v0.3.0), but that does have the unfortunate side-effect of being stringly-typed.

Cargo internals are a bit of a mystery to me (which I consider to be a good thing - the abstraction holds up!), so I probably can't suggest anything else for this in particular.

@weihanglo
Copy link
Member

--rename oldname:newname

Unfortunately it may come into conflict with the other unstable feature -Zdifferent-binary-name, so probably this is a dead end.

We may need to come up with a better design, however, if someone is willing to drive it. My current focus is not on this but feel free to have higher level design discussions here :)

@blyxyas
Copy link
Member

blyxyas commented Nov 17, 2023

Maybe, if creating a whole new flag is too complex, having the option to use env. variables like CARGO_PKG_NAME, CARGO_BIN_NAME is easier and more approachable. If this approach is good enough (at least for a first draft), I could take a go at making just that.

@weihanglo
Copy link
Member

@blyxyas, thanks for looking into this. Could you elaborate how a new env can fix the issue?

I feel like even using env instead of CLI flag, we still need to figure out these open design issues:

  • How to choose which bin target we're going to rename.
  • How this rename feature works and interacts with -Zdifferent-binary-name.
  • How to track the installed binary in Cargo's installed binary tracker.

To me, the format of the current installed binary tracker is broken, and may be a blocker. We probably need a way to coordinate with it before moving on.

@blyxyas
Copy link
Member

blyxyas commented Nov 22, 2023

Without thinking about it too much, I feel like aforementioned magic strings could work, though I really hate the idea

I feel like a format like "oldname:newname" or similar is just what we need in this situation! Adding another field would mean more parsing and more storage, not ideal. Whereas a format like "oldname:newname", or even a human-readable format like "oldname as newname" is as simple as getting the two variables with a regex or a .split(...), no more JSON parsing than necessary.

While using oldname:newname on a CLI isn't the prettiest thing, it wouldn't be used very often, excusing its clunky-ness with a technical reason.


On the topic of -Zdifferent-binary-name, I've investigated what crates.io and cargo install do, and I think that we can ignore it. The filename produced and the binary name are different things, so they should remain separated.

@allsey87
Copy link

Since renaming has a couple gotchas when there are multiple binaries, perhaps simply a --postfix-name or a --prefix-name would be sufficient?

@allsey87
Copy link

Perhaps an even better solution (inspired by shared libraries on Linux), what if every binary was installed with its version/rev number postfixed, with a symbolic link pointing to the most recent (released) version?

@mat813
Copy link

mat813 commented Nov 23, 2024

The --prefix-name (and/or --suffix-name) would be great, we have some internal crates and sometime the names are quite common like "clean" or "rename" and while those names are ok when running in an container via automation, they can be a bit of a pain when they need to be run manually on a live system.

@dmgolembiowski
Copy link

Suggestions proposed earlier would be helpful for scenarios I encounter, where projects require specific CLIs at outdated versions to build properly (i.e. wasm-pack, cargo-xtask, wasm-bindgen-cli, etc.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` Command-install E-medium Experience: Medium S-needs-design Status: Needs someone to work further on the design for the feature or fix. NOT YET accepted.
Projects
None yet
Development

No branches or pull requests

7 participants