cargo-local-install

Wraps cargo install for better local, non-conflicting installation

GitHub crates.io docs.rs %23![forbid(unsafe_code)] rust: stable License

Want to script cargo install cargo-web --version 0.6 --root my-project to avoid version conflicts with other projects?
Hate having a million copies of cargo-web 0.6.26 and waiting for it to build if you go down that route?
cargo-local-install now has your back, and will create symlinks into a global cache of reusable bins:

Quickstart

```sh

no dependencies, builds in < 3 seconds on my machine

cargo install cargo-local-install --no-default-features

slow first builds that create new exes

cargo local-install --locked cargo-web --version "^0.6" --root project-a # symlinks project-a/bin/cargo-web.exe cargo local-install --locked cargo-web --version "^0.5" --root project-b # symlinks project-b/bin/cargo-web.exe

fast cached builds that reuse existing exes

cargo local-install --locked cargo-web --version "^0.6" --root project-c # symlinks project-c/bin/cargo-web.exe cargo local-install --locked cargo-web --version "^0.6" # symlinks bin/cargo-web.exe

Adds Cargo.toml metadata support, < 30 seconds

cargo install cargo-local-install ```

Options are broadly similar to cargo install, with a few caveats: * --locked is strongly encouraged (warns by default unless it or --unlocked is used) * --list, --no-track, --features, --bin, and --example are not supported * --frozen and --offline are not supported (don't think they worked for cargo install either though!) * -Z <FLAG> is not supported

Alternatively, you can specify workspace or package metadata in your Cargo.toml, similar to [dependencies], which will be installed by cargo local-install:

``toml [workspace.metadata.local-install] cargo-web = "0.6" # == "^0.6" - includes "0.6.26" - locked by default cargo-web = { version = "0.6", registry = "crates.io", locked = false } #locked = false` ignores cargo-web's Cargo.lock cargo-web = { path = "../cargo-web" } cargo-web = { git = "https://github.com/koute/cargo-web" } cargo-web = { git = "https://github.com/koute/cargo-web", branch = "master" } cargo-web = { git = "https://github.com/koute/cargo-web", rev = "a9895bf536e8ac6a0806382886b7be90138f01f3" }

not (yet?) implemented:

features = [...]

default-features = false

optional = true

```

What? Why?

cargo install is great but suffers a few drawbacks: * The global ~/.cargo/bin directory can contain only a single installed version of a package at a time - if you've got one project relying on cargo web 0.5 and another prjoect relying on cargo web 0.6, you're SOL. * Forcing local installs with --root my/project to avoid global version conflicts means you must rebuild the entire dependency for each project, even when you use the exact same version for 100 other projects before. * When building similar binaries, the lack of target directory caching means the entire dependency tree must still be rebuilt from scratch.

cargo local-install attempts to solve these problems: * (Ab)uses --target-dir to share built dependencies. * Creates a global cache of binaries, but installs a symlink (or copy if that fails) in ./bin by default.

Alternative: sccache

Some concrete numbers from some local testing with a global .cargo/config rustc-wrapper configured

| with sccache configured for local disk | time | notes | | ----------------------------------------- | ------ | ----- | | cargo install cargo-web --root a | 3m 38s | cleanish cache, no downloads | cargo install cargo-web --root a | ~ 1 s | noop by cargo install | cargo install cargo-web --root b | 1m 21s | many cache failures based on lurching progress speed?

| with local-install (no sccache) | time | notes | | ----------------------------------------- | ------ | ----- | | cargo local-install cargo-web --root c | 3m 03s | clean cache, no downloads of deps | cargo local-install cargo-web --root c | ~ 1 s | noop by cargo install | cargo local-install cargo-web --root d | ~ 1 s | trivial cache hit by cargo local-install

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.