# cargo-parcel **Note: this project is at an early stage. While all documented functionality is actually implemented, the featureset is still quite limited. It may still be considered good enough for a MVP.** While `cargo install` is a convenient way to install binaries provided by crates onto your system, it falls short if the crates need additional resources to be installed, such man pages, icons, sound files, etc. Additionally, there seems to be no established convention in the Rust ecosystem to allow access to resources installed along the application, regardless of where they are installed. `cargo-parcel` is actually an application of the [`xtask` pattern], which, when I stumbled upon it gave rise to the idea of `cargo-parcel`. While `cargo-xtask` is "a way to add free-form automation to a Rust project, ...", `cargo-parcel` is a specific implementation of that idea, taking away the "free-form" part, instead focusing on application installation and distribution, and on defining a declarative way to describe those. ## The pitch - Install additional resources alongside your binaries. - Render Unix man pages from markdown sources, before installing the rendered version. - Allow compiling the installation location into your binaries, so they can find resources installed alongside themselves. ## An example use-case As a motivating example, let's say you are developing a crate that provides a `frobnitz` binary that plays sound samples, and you want to include some sample sounds with your program. Furthermore, you want to be a good citizen of the *nix ecosystem and provide man pages that describe `frobnitz` in excessive detail. Furthermore, you want to make it easy for Linux distributions and similar efforts to package `frobnitz` for their respective package systems. This means in practice that you want to be able to meet the following requirements: - Installing `frobnitz`, along with documentation and other resources below an arbitrary location provided by the user. On Unix systems the default locations are conventionally below `/usr/local` for system-wide locations, and `~/.local` for per-user installations. The `~/.local` directory is a convention described by the [XDG Base Directory Specification]. The installation target root directory is usually referred to as the *installation prefix*. - The installation prefix can be, if needed, compiled into `frobnitz`, so it can locate installed resources without the user needing to specify their location, regardless of the chosen installation prefix. - It should be possible to relocate the installation by specifying an additional path to be prepended to the chosen installation prefix. This path is only relevant at installation time, and must *not* be compiled into or otherwise referenced by the installed executable or resources. This path is referred to as [`DESTDIR`] in the autotools world. It is especially useful for distribution packaging tools, which need to be able to operate without root privileges, and must not write to the location the built package will eventually be installed in. ## What it does for you `cargo-parcel` is an attempt to allow binary crate authors easily meet the requirements described above. It also allows integrating common tasks, such as building man pages, into the installation process. Furthermore, it provides a way to create simple binary distribution archives, which come in handy in case you want to provide distribution-independent binary packages for your users, or for deployment to a different system from source. You can make use of `cargo-parcel` in your own crate with by adding a bit of metadata to the `Cargo.toml` file, specifically the `package.metadata.parcel` table, which is described below. As the metadata format is expected to evolve, there is currently no `cargo-parcel` cargo plugin, and you must add some additional boilerplate to tie your code to a specific version of `cargo-parcel`, effectively defining the `cargo parcel` command in your own crate. ## Usage There are two sides to using `cargo-parcel`; application crate authors will want to have a look at [how to integrate](./docs/integration.md) it into their crate, while users of crates employing `cargo-parcel` may be more interested in the [CLI guide](./docs/cli-guide.md). The behavior of `cargo-parcel` is configured by the `package.metadata.parcel` table in `Cargo.toml`. The available settings are described the [metadata reference](./docs/metadata.md). A short overview over the available commands and their most important options is provided below. For a complete account see the CLI guide or the built-in command-line interface help. - `cargo parcel install [--prefix DIR] [--dest-dir DIR]` Install the parcel contents into the given `--prefix` directory (`~/.local` by default), optionally relocating the installation to the given `--dest-dir` directory. - `cargo parcel uninstall [--prefix DIR] [--dest-dir DIR]` Counteract the actions of an equivalent `install` commend; i.e. uninstall the package contents. - `cargo parcel bundle [-o FILE] [--prefix DIR] [--root DIR]` Produce a distribution "bundle"; currently TAR archives are supported by calling out to GNU tar. ## Related software To understand the goals of `cargo-parcel`, it is helpful to contrast it with a generic task runner like [`cargo-make`]: - With `cargo-make`, you can define arbitrary tasks, while `cargo-parcel` defines a few fixed commands focused on application installation and distribution. - `cargo-parcel` tries to be declarative, describing the "what", not the how. Other tools should be able to make use of the `parcel` metadata, without having to run `cargo-parcel`, or partially re-implement it. There are some crates that provide functionality overlapping with `cargo-parcel`; after a casual search, I found the following ones. If you know of others, please file an issue, and I'll add them to the list. - The cargo extension [`cargo-deb`] creates binary Debian packages based on `Cargo.toml`, and can be configured by a `deb` metadata section. - [`cargo-rpm`], which is differs from `cargo-deb` (besides producing .rpm instead of .deb packages, of course) in not using `Cargo.toml` for its metadata. - [`debcargo`], which clearly separates the packager and upstream roles, by generating a template Debian source package from a "pristine" crate source. So how does `cargo-parcel` relate to these tools? Creating actual distribution packages is out of scope for `cargo-parcel`, instead it intends to let you describe your application crates contents, so it can be easily installed directly from source, and a simple, distribution-agnostic binary package can be built for distribution. ## Future directions Besides hopefully reducing the overhead of packaging "Rust applications", having the `cargo-parcel` metadata available would also allow building other potentially cool stuff. One idea would be a web site focused on Rust applications (both CLI and GUI) which could: - Provide man page contents and other documentation, similar to `docs.rs`, but for end-user documentation, not API docs. - Show a list of files that would be installed by that crate. Thinking about this also raised the question of "what's the scope of cargo and `crates.io`" in my mind. I feel that dealing with platform idiosyncrasies, such as the mere existence of man pages, is out of cargo's scope. So if we accept that cargo will not deal with such things as rendering and installing man pages, does that leave a gap for a tool that does? `cargo-parcel` is an experiment in filling that gap, currently tailored to the need of its author's CLI crates, but intended to be useful for others as well. If a tool similar to `cargo-parcel`, a `cargo install` tailored towards applications written in Rust, were to take off, that would mean binary crates will become (more) commonplace where running `cargo install` will not be sufficient to (fully) install them. In that hypothetical future, it might even make sense to think about providing such crates via a channel separate from `crates.io`. [`xtask` pattern]: https://github.com/matklad/cargo-xtask [XDG Base Directory Specification]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html [`DESTDIR`]: https://www.gnu.org/software/automake/manual/html_node/DESTDIR.html [`cargo-make`]: https://crates.io/crates/cargo-make [`cargo-deb`]: https://crates.io/crates/cargo-deb [`cargo-rpm`]: https://crates.io/crates/cargo-rpm [`debcargo`]: https://crates.io/crates/debcargo ## License The code and documentation in this crate is [free software](https://www.gnu.org/philosophy/free-sw.html), dual-licensed under the [MIT](./LICENSE-MIT) or [Apache-2.0](./LICENSE-APACHE) license, at your choosing. The contents of the `templates` and `examples` directories are intended for free copying and adaption, for any use, without any obligations. The author considers these to be too trivial to fall under copyright anyway.