Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions anneal/v2/exocrate/README.md
Comment thread
mdittmer marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Exocrate: An exoskeleton for your crate

Exocrate is a manager for rust crate dependencies which are not managed by the `cargo` tool itself, such as external toolchains, large binary files, etc.

<img src="diagram2.png" width="100%">

See [crate documentation](src/lib.rs) for details.

<!-- FIXME: Inline crate documentation using `cargo-readme` or similar -->
139 changes: 138 additions & 1 deletion anneal/v2/exocrate/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,144 @@
//! Exocrate: An exoskeleton for your crate.
//!
//! Exocrate is a manager for crate dependencies which are not managed by Cargo
//! itself. This might include external toolchains, large binary files, etc.
//! itself such as external toolchains, large binary files, etc.
//!
//! Exocrate *assumes*:
//!
//! - An external mechanism that packages external dependencies into a single archive.
//!
//! Exocrate *supports*:
//!
//! - Remote archives loaded by URL and verified by checksum;
//! - Local archives designated by file path.
//!
//! Exocrate *provides* mechanisms to:
//!
//! - Install external dependencies:
//! - Download and extract an archive;
//! - Fix up archive artifacts that depend on the installed environment (e.g., rewriting absolute
//! paths in dependency files);
//! - Install archive contents in a versioned filesystem location.
//! - Access extracted external dependencies:
//! - Resolve current installation location.
//!
//! # How exocrate installations are versioned
//!
//! ## Platform + versioned files list
//!
//! The simplest way to auto-version your installations is using macros that tie your installation
//! platform (i.e., `std::env::consts::OS` and `std::env::consts::ARCH` values) and versioning
//! files that will change anytime your external dependencies might. Here is an example of
//! realizing this versioning strategy using the macros exported by `exocrate`:
//!
//! ```rust
//! exocrate::config! {
//! const CONFIG: Config = Config {
//! // Path components that are joined to establish the base directory for all exocrate
//! // installations.
//! //
//! // For `my-tool` developers: `<my-tool-root>/target/.my-tool/exocrate/<version>`
//! // For `my-tool` users: `~/.my-tool/exocrate/<version>`
//! rel_dir_path: [".my-tool", "exocrate"],
//! // Since the definition of platform-specific exocrate releases for `my-tool` will be
//! // specified in its `Cargo.toml` file (see below), we use that file as a "change
//! // detector" to change the version whenever `Cargo.toml` changes.
//! //
//! // This is an over-approximation: unrelated changes to `Cargo.toml` (e.g., change in
//! // crate dependencies, shipping an exocrate release for some other platform, etc.) will
//! // also change the exocrate version. This is generally not a problem because only
//! // developers of `my-tool` itself need to deal with noisy exocrate version changes;
//! // users will only install versions associated with less frequent releases of
//! // `my-tool`.
//! versioned_files: &["../Cargo.toml"],
//! };
//! }
//!
//! exocrate::parse_remote_archive! {
//! const REMOTE: RemoteArchive = "Cargo.toml" [
//! // `(std::env::consts::OS, std::env::consts::ARCH)` pairs you support.
//! (linux, x86_64),
//! (macos, x86_64),
//! (linux, aarch64),
//! (macos, aarch64),
//! ];
//! }
//!
//!
//! // FIXME: Detect whether running in tool-installed or tool-development environment. The typical
//! // pattern would be:
//! // - tool-installed => use `exocrate::Location::UserGlobal`,
//! // - tool-development => use `exocrate::Location::Local`.
//! let location: exocrate::Location = exocrate::Location::Local;
//!
//! // FIXME: Use environment detection here too. The typical pattern would be:
//! // - tool-installed => use `exocrate::Source::Remote(REMOTE)`,
//! // - tool-development => use
//! // `exocrate::Source::Local("/path/to/dep-archive-builder-output.tar.zst".into())`.
//! let source: exocrate::Source = exocrate::Source::Local("tests/my-tool-deps.tar.zst".into());
//!
//! // Check whether `source` archive is already installed at `location`, and if not, install it.
//! let installed_exocrate_dir = CONFIG.resolve_installation_dir_or_install(location, source)
//! .expect("failed to resolve or install my-tool's exocrate");
//!
//! // Invoke tool installed from `tests/my-tool-deps.tar.zst` extracted to versioned exocrate
//! // directory.
//! let tool_status = std::process::Command::new(installed_exocrate_dir.join("bin").join("tool"))
//! .status()
//! .expect("failed to start external dependency located at `bin/tool`");
//! assert!(tool_status.success());
//! ```
//!
//! And in your `Cargo.toml`:
//!
//! ```toml
//! #
//! # Prepares `REMOTE = exocrate::RemoteArchive { sha256, url }` according to compile-time machine
//! # `std::env::consts::OS . std::env::consts::ARCH` listed as supported in your invocation of
//! # `exocrate::parse_remote_archive`.
//! #
//! [package.metadata.exocrate.linux.x86_64]
//! # FIXME: Replace `sha256` with actual linux-x86_64.tar.zst checksum.
//! sha256 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
//! url = "https://example.com/linux-x86_64.tar.zst"
//!
//! [package.metadata.exocrate.macos.x86_64]
//! # FIXME: Replace `sha256` with actual macos-x86_64.tar.zst checksum.
//! sha256 = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
//! url = "https://example.com/macos-x86_64.tar.zst"
//!
//! [package.metadata.exocrate.linux.aarch64]
//! # FIXME: Replace `sha256` with actual linux-aarch64.tar.zst checksum.
//! sha256 = "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
//! url = "https://example.com/linux-aarch64.tar.zst"
//!
//! [package.metadata.exocrate.macos.aarch64]
//! # FIXME: Replace `sha256` with actual macos-aarch64.tar.zst checksum.
//! sha256 = "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
//! url = "https://example.com/macos-aarch64.tar.zst"
//! ```
//!
//! ### Limitations
//!
//! This versioning strategy does not distinguish between changes to `package.metadata.exocrate` and
//! other changes to `Cargo.toml`. This can result in proliferation of distinct exocrate versions
//! that developers need to clear out if your exocrate is particularly large. This cleanup can be
//! achieved using `cargo clean`.
//!
//! ## Custom versioning
//!
//! Manually constructing an [`exocrate::Config`] offers you full control over the base directory
//! (relative to one or another `exocrate::Location` for installation) and version string that is
//! used to construct this `Config`'s version of the exocrate. By using this pattern, you take
//! responsbility for determining what version of your exocrate corresponds with the code consuming
//! the `exocrate` library.
//!
//! # Limitations
//!
//! Exocrate does not currently support any helpers for cleaning up old versions of your exocrate
//! installations. All installed versions will be stored somewhere inside the directories designated
//! by one of the [`exocrate::Location`] variants, but there are no other guarantees about how these
//! directory trees are managed at this time.

mod sync;

Expand Down
Binary file added anneal/v2/exocrate/tests/my-tool-deps.tar.zst
Binary file not shown.
Loading