What is the intended/planned way of configuring/installing software that uses Rust Cargo as build system?

cargo install

As of Rust 1.5 you can use cargo install to install binary crates onto your system. You can install crates from:

  • crates.io (the default), using cargo install crate_name
  • any git repository, using cargo install --git repository_url
  • any directory, using cargo install --path /path/to/crate

The first two have additional options you can specify:

  • With crates.io, you can use --vers to specify the crate version.
  • With git repositories, you can use --branch to set the branch to install from, --tag to specify the tagged release to use, and --rev to build from a specific commit.

Installation location:

cargo install can be configured to install in a custom directory through the following methods, in order of precedence (highest first):

  • By passing --root /path/to/directory (this path can be relative)
  • By setting the $CARGO_INSTALL_ROOT environment variable
  • By setting the install.root configuration key
  • By setting the $CARGO_HOME environment variable (which will affect more than the installation directory of cargo install)

If none of the above are present, cargo will install the crates in ~/.cargo/bin.

In all of the above cases, the output files will actually be placed in the bin subdirectory (e.g. --root /path/to/directory will actually place ouput in /path/to/directory/bin).

Uninstallation

cargo uninstall can be used to remove previously-installed crates. If you have multiple crates with the same name installed, you can specify --root to only remove the version in that directory.

Example: I want to use rustfmt:

I can use the version on crates.io:

  • cargo install rustfmt

I like using original releases:

  • cargo install rustfmt --vers 0.0.1

I want it installed in /opt/rust_crates:

  • cargo install rustfmt --root /opt/rust_crates

I really need to use the bleeding-edge version:

  • cargo install --git https://github.com/rust-lang-nursery/rustfmt.git

The latest commit has a bug in it!

  • cargo install --git https://github.com/rust-lang-nursery/rustfmt.git --rev f5bd7b76e0185e8dd37ae6b1b5fb5e11187f0b8c

I truly desire the version that uses git submodules for its dependencies:

  • cargo install --git https://github.com/rust-lang-nursery/rustfmt.git --branch submods

I've cloned it and made some edits:

  • cargo install --path ~/my_rustfmt

Actually, I insist on doing my formatting entirely manually:

  • cargo uninstall rustfmt

(This answer is intended for developers who want to distribute their own programs, not users who have received a Cargo project and need to install it on their own system; That's the domain of Toby's answer).

In addition to Toby's Answer:

Cargo's install feature is not meant to be the primary way to distribute Rust programs. It's designed to be used only for distribution to other Rust developers. There's several drawbacks to using this feature:

  • Cargo requires end-users to install the entire Rust toolchain first.
  • Users will have to build the program locally, which can be slow, especially in Rust.
  • There's no support for upgrading programs once they're installed (without an additional tool).
  • There's (currently) no way to include assets, such as documentation.
  • The packages will be installed only for the current user unless flags are passed to cargo install.

In other words, cargo install is the make && sudo make install of Cargo programs; It's not the ideal way to distribute a Rust program, unless it's intended primarily for Rust programmers.

So what is the correct way?

Let's look at the alternatives.

Manually distribute a tarball/zip

You can replicate the effects of cargo install by simply using cargo build --release. This will place a (mostly, see the drawbacks below) statically linked crate binary in target/release/crate_name, and this can be repackaged into a .tar.gz or .zip and given out to other users.

Pros:

  • Doesn't require users to install Rust or build the program themselves.
  • Allows developers to copy assets into the tarball/zip and distribute them along with the program itself.

Cons:

  • Installing a .tar.gz/.zip is nonstandard and generally not considered ideal for most users.
  • If the crate needs any system dependencies beyond libc, it will fail to load them with a difficult to understand error.
  • This requires a developer to manually build a package to release for each version and platform combination.

Use a CI service to build releases

It's possible to recreate any of these methods using a cloud-based CI service. For example, using Travis CI, you can use the Trust project to automatically deploy in much the same way that you would from a tarball, but automatically with only a tag being required.

Pros:

(All of the advantages of a tarball, plus)

  • The developers don't have to manually release the program, they just need to tag a release.
  • As a side effect, it's possible to build for every package the program supports at once.

Cons:

  • The process can be frustrating to debug if it doesn't work correctly, because there's limited control over the server.
  • The build process is tied to a service, which means releases can be missed if the service is down when they are released.
  • With Trust or similar tools, you're still ultimately distributing a .tar.gz/.zip, which means there's still inconvenience for users and a lack of system dependency management.

In addition to Travis, see Appveyor and GitHub Actions as possible build platforms.

Provide a package

This is considered the ideal method for many end users, and is the standard way to distribute any program, not just Cargo programs. This alleviates almost every issue with the tarball approach, though not without some problems of its own.

Pros:

  • Included in the system like any other program.
  • Can be submitted to Linux distribution repositories to allow programs to be installed in only one command.
  • Allows updating, removal, and asset inclusion.
  • Tracks system dependencies, which is especially helpful for GUI apps.

Cons:

  • By far the most complex of these options.
  • Requires building a package separately for every supported platform (this can be alleviated with CI, but it will be even more complex to setup this way.)

This approach is best handled with additional tools:

  • cargo-deb: Build a package for Debian and Ubuntu.
  • cargo-rpm: Build a package for Fedora, Red Hat, and CentOS.
  • cargo-aur: Build a package for Arch Linux.
  • cargo-wix: Make a Windows Installer package.

These usually are tools that are meant to be run by developers, to create the files that are used to generate packages. See their own documentation for more information.

Source: https://rust-cli.github.io/book/tutorial/packaging.html