RepoPilotOpen in app →

cross-rs/cross

“Zero setup” cross compilation and “cross testing” of Rust crates

Healthy

Healthy across the board

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 2w ago
  • 27+ active contributors
  • Apache-2.0 licensed
Show all 6 evidence items →
  • CI configured
  • Tests present
  • Concentrated ownership — top contributor handles 50% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/cross-rs/cross)](https://repopilot.app/r/cross-rs/cross)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/cross-rs/cross on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: cross-rs/cross

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/cross-rs/cross shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 2w ago
  • 27+ active contributors
  • Apache-2.0 licensed
  • CI configured
  • Tests present
  • ⚠ Concentrated ownership — top contributor handles 50% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live cross-rs/cross repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/cross-rs/cross.

What it runs against: a local clone of cross-rs/cross — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in cross-rs/cross | Confirms the artifact applies here, not a fork | | 2 | License is still Apache-2.0 | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 45 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>cross-rs/cross</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of cross-rs/cross. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/cross-rs/cross.git
#   cd cross
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of cross-rs/cross and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "cross-rs/cross(\\.git)?\\b" \\
  && ok "origin remote is cross-rs/cross" \\
  || miss "origin remote is not cross-rs/cross (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
  && ok "license is Apache-2.0" \\
  || miss "license drift — was Apache-2.0 at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "src/main.rs" \\
  && ok "src/main.rs" \\
  || miss "missing critical file: src/main.rs"
test -f "src/build.rs" \\
  && ok "src/build.rs" \\
  || miss "missing critical file: src/build.rs"
test -f "Cargo.toml" \\
  && ok "Cargo.toml" \\
  || miss "missing critical file: Cargo.toml"
test -f ".cargo/config.toml" \\
  && ok ".cargo/config.toml" \\
  || miss "missing critical file: .cargo/config.toml"
test -f ".changes" \\
  && ok ".changes" \\
  || miss "missing critical file: .changes"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 45 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~15d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/cross-rs/cross"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

cross is a Rust tool that enables zero-setup cross-compilation and cross-testing of Rust crates across different target architectures using Docker or Podman containers. It abstracts away the complexity of setting up cross-compilation toolchains by providing pre-configured container images with all necessary compilers, libraries, and tools, allowing developers to run cross build --target aarch64-unknown-linux-gnu with the same ease as native compilation. Single-crate Rust binary with a workspace member (xtask/) for build automation. The main src/ contains the CLI argument parsing (via clap), container orchestration logic, and cross-compilation target definitions. Build scripts (src/build.rs) generate embedded assets. Shell scripts and Dockerfiles (108KB across the repo) define container images for each target architecture. The .changes/ directory tracks changelog entries per PR for semantic versioning.

👥Who it's for

Rust developers and library maintainers who need to compile and test crates for non-native architectures (ARM, MIPS, PowerPC, etc.) without manually configuring toolchains. Systems programmers, embedded Rust developers, and CI/CD engineers who want to verify their crates work across multiple target platforms with minimal setup.

🌱Maturity & risk

Actively developed and production-ready. The project is maintained by the cross-rs team (successor to the Rust Embedded Working Group), has a robust CI pipeline, uses semantic versioning (currently v0.2.5), and includes comprehensive changelog tracking via .changes/ directory with 50+ tracked PRs. Recent commits and active issue management indicate healthy ongoing development.

Low risk for core use cases, but moderate infrastructure dependency: the tool relies entirely on Docker/Podman being available and properly configured, creating a hard external dependency. Container image maintenance is critical—if images become stale or unavailable, the tool fails silently. The relatively small maintainer team and reliance on container registry availability are potential vulnerability points, though community engagement via Matrix is active.

Active areas of work

The project is actively addressing cross-compilation edge cases and container image updates. Recent changes tracked in .changes/ (up to PR #1483) suggest work on compiler version compatibility, target architecture support expansion, and containerization improvements. The 0.2.5 release cycle is active with pre-release automation configured in Cargo.toml metadata.

🚀Get running

git clone https://github.com/cross-rs/cross.git
cd cross
cargo install --path .
# Requires: Docker (v20.10+) or Podman (v3.4.0+) and rustup
sudo systemctl start docker  # on Linux
cross build --target aarch64-unknown-linux-gnu

Daily commands:

# Development build
cargo build
# Run tests
cargo test
# Run with a test target
./target/debug/cross build --target aarch64-unknown-linux-gnu
# For xtask changelog generation
cargo xtask changelog build

🗺️Map of the codebase

  • src/main.rs — Entry point for the cross CLI tool; defines command structure and routing for all subcommands (build, test, run)
  • src/build.rs — Build script that handles compilation metadata and version info; critical for reproducible builds
  • Cargo.toml — Project manifest with all dependencies (clap, color-eyre, thiserror); defines MSRV 1.85.0 and workspace structure
  • .cargo/config.toml — Cargo configuration for workspace-level settings and build behavior defaults
  • .changes — Changelog directory tracking all feature changes and bug fixes; essential for understanding project evolution

🧩Components & responsibilities

  • CLI Parser (clap) (clap 4.1.4 with derive macros) — Validates user input, maps arguments to handler functions, enforces required flags
    • Failure mode: Invalid target triple or missing required args → error message and help text
  • Build Orchestrator (Rust std::process, Docker API) — Coordinates Cargo invocation, container setup, and compilation flow
    • Failure mode: Cargo compilation failure → propagate compiler error; container unavailable → fallback or fail
  • Error Formatter (color-eyre, thiserror) — Converts Rust errors to user-friendly messages with colors and context
    • Failure mode: Panic during error formatting → raw backtrace (fallback)
  • Target Registry (TOML config parsing) — Maps target triples to container images and toolchain configurations
    • Failure mode: Unknown target triple → error with list of supported targets

🔀Data flow

  • Developer CLI inputclap argument parser — Command line arguments (cross build --target x86_64-unknown-linux-musl) are parsed and validated
  • clap parserBuild orchestrator — Parsed args routed to appropriate handler function (e.g., build, test, run)
  • Build orchestratorCargo.toml / target registry — Maps target triple to container image, cross-compiler flags, and environment setup
  • OrchestratorDocker/Container runtime — Spawns container with cross-compiler toolchain and mounts project source
  • ContainerCargo (inside container) — Runs cargo build/test with target-specific flags and toolchain
  • Cargo outputError formatter (color-eyre) — Compiler diagnostics and build failures formatted for terminal display
  • Formatted errors/artifactsDeveloper terminal — Colored output and build artifacts returned to user

🛠️How to make changes

Add a new cross-compilation target

  1. Define target architecture in a new configuration file under a target-specific module (src/main.rs)
  2. Add target metadata (triple, toolchain requirements) to a targets registry (src/main.rs)
  3. Register new target in CLI argument parser using clap derive macros (src/main.rs)

Add a new CLI subcommand

  1. Define new subcommand struct with clap attributes in main.rs (src/main.rs)
  2. Add handler function that processes the subcommand arguments (src/main.rs)
  3. Wire subcommand into main match statement for execution (src/main.rs)

Document a breaking change or feature

  1. Create new JSON file in .changes/ directory with issue number and description (.changes/template/940.json)
  2. Follow template structure (kind, body, references) for changelog generation (.changes/template)
  3. Regenerate CHANGELOG.md using changelog tooling before release (.changes/README.md)

Update project dependencies

  1. Modify dependency versions in [dependencies] section (Cargo.toml)
  2. Verify MSRV compatibility (currently 1.85.0) with new transitive dependencies (Cargo.toml)
  3. Run full test suite to ensure compatibility (src/main.rs)

🔧Why these technologies

  • Clap 4.1.4 (derive macros) — Declarative CLI parsing with minimal boilerplate; strong type safety for arguments and subcommands
  • Color-eyre + thiserror — Consistent error formatting with colors and context; ergonomic error type definitions with Display impl
  • Docker/OCI containers — Provides isolated, reproducible cross-compilation environments without modifying host system
  • TOML for configuration — Human-readable config format for targets and toolchains; matches Rust ecosystem conventions (Cargo.toml)
  • Rust 1.85.0 MSRV — Ensures portability across older stable Rust versions; balances latest features with broad compatibility

⚖️Trade-offs already made

  • Zero-setup via containerization vs. native toolchain installation

    • Why: Eliminates need for manual toolchain setup while maintaining reproducibility
    • Consequence: Requires Docker/container runtime; slower initial cross-target builds but faster subsequent invocations
  • CLI-only interface (no library API)

    • Why: Simpler project scope; clear separation of concerns as a tool rather than library
    • Consequence: Limited reusability in Rust scripts; users must shell out or parse CLI output
  • Support for multiple target architectures vs. single-target focus

    • Why: Addresses embedded, ARM, RISC-V ecosystems with one tool
    • Consequence: Higher maintenance burden; more container images to maintain and test

🚫Non-goals (don't propose these)

  • Does not replace or wrap Cargo entirely; only supplements cross-compilation features
  • Not a package manager; assumes Cargo.toml and dependencies are already configured
  • Does not handle target-specific code generation at Rust source level (preprocessor-like features)
  • Not a CI/CD system; focuses on local development workflow, not multi-platform release pipelines

⚠️Anti-patterns to avoid

  • Large monolithic main.rs (Medium)src/main.rs: All CLI logic, subcommand handling, and build orchestration likely concentrated in a single file; no visible module organization from file list
  • Hardcoded container image references (Medium)src/main.rs (inferred): Container images for targets may be hardcoded rather than externalized to config; complicates target additions
  • Generic error types without context (Low)Cargo.toml (thiserror usage): If thiserror is underutilized, errors may lose context during propagation through the build pipeline

🔥Performance hotspots

  • Docker image pull and startup (I/O latency) — Cold-start latency when cross-compiler image not cached; can be 30+ seconds for first invocation per target
  • Cargo dependency resolution + compilation (Computational latency) — For large projects with many dependencies, compilation inside container may exceed local native compilation time
  • Build artifact extraction from (undefined) — undefined

🪤Traps & gotchas

  1. Container engine must be running: cross silently fails if Docker daemon isn't started; no fallback to native compilation. 2. binfmt_misc requirement for testing: cross test only works on Linux kernels with binfmt_misc support—fails on macOS/Windows even with Docker. 3. MSRV is strict: rust-version = "1.85.0" is a hard floor; dev machines must have at least that rustup toolchain. 4. Container image pull on first run: First invocation per target downloads a large image; network and registry availability are implicit dependencies. 5. Mount path assumptions: cross assumes standard /tmp and home directory structure; custom Docker daemon configs may break mount points.

🏗️Architecture

💡Concepts to learn

  • binfmt_misc (binary format miscellaneous) — cross test requires kernel support for binfmt_misc to execute foreign architecture binaries; this Linux-kernel-only feature is why cross testing is unavailable on macOS/Windows despite Docker support.
  • Cross-compilation toolchains (sysroot + linker + stdlib) — cross abstracts away the complexity of setting up target-specific toolchains; understanding what's in a toolchain (gcc, binutils, libc for the target arch) helps debug linking failures.
  • Container image layering and build caching — cross ships pre-built Docker images per target; understanding Dockerfile layer caching and registry pulling helps optimize CI pipeline speed and diagnose stale-image bugs.
  • Rustup target triple (target-os-arch-abi) — cross uses Rust's target triple syntax (e.g., aarch64-unknown-linux-gnu) to map to specific container images and rustc configurations; mismatches between target triples cause subtle incompatibilities.
  • Container volume mounting and bind mounts — cross mounts the host's source code and Cargo cache into containers; understanding mount points and permission mapping is critical for debugging file access errors in containerized builds.
  • QEMU user-mode emulation — cross test uses QEMU to emulate non-native architectures when binfmt_misc + QEMU are configured; understanding QEMU's performance limitations explains why cross test is slow for some targets.
  • Semantic versioning and changelog fragments — cross uses a fragment-based changelog system (.changes/{pr}.json) to auto-generate release notes; contributors must follow this pattern to ensure proper version bumping and documentation.
  • rust-lang/rustup — Required dependency for toolchain management; cross builds on top of rustup's target installation system
  • moby/moby — Docker engine that powers cross's containerization; understanding Docker volumes and networking is essential for debugging mount issues
  • rust-embedded/cargo-binutils — Companion tool for embedded Rust; users of cross often also use cargo-binutils for inspecting cross-compiled binaries
  • containers/podman — Alternative container runtime that cross supports as a Docker replacement; shares same API surface but different daemon behavior
  • rust-lang/cargo — Core dependency and design inspiration; cross mirrors Cargo's CLI interface exactly to feel native to Rust developers

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Consolidate changelog entries into CHANGELOG.md automation

The .changes/ directory contains 50+ individual JSON changelog fragments (e.g., 1006.json, 1018.json, etc.). Currently, the release process has a pre-release hook that runs cargo xtask changelog build to consolidate these. However, there's no validation that these fragments conform to a schema, no pre-commit hook to catch malformed entries, and no GitHub Action to automatically validate changelog entries on PRs. This prevents contributor mistakes and ensures release automation doesn't fail.

  • [ ] Create a JSON schema file (e.g., schemas/changelog-entry.json) that defines required fields for .changes/*.json entries
  • [ ] Add a validation script in xtask/src/main.rs to validate all .changes/*.json files against this schema
  • [ ] Create a GitHub Action workflow (.github/workflows/changelog-validate.yml) that runs this validation on every PR
  • [ ] Update CONTRIBUTING.md to document the changelog entry format and validation process

Add integration tests for cross-compilation targets

The repo targets multiple architectures (aarch64, armv7, x86_64, etc.) but the dev-dependencies only include basic testing utilities (regex, once_cell, ignore). There are no visible integration tests validating that cross build and cross test actually work for specific targets. Adding target-specific integration tests (even if they only run on CI with docker/qemu available) would catch regressions early and document expected behavior.

  • [ ] Create tests/integration/ directory with a module per target architecture (e.g., aarch64.rs, armv7.rs)
  • [ ] Add a simple test crate in tests/fixtures/ that can be compiled for multiple targets
  • [ ] Write integration tests that invoke cross build --target <target> and validate output
  • [ ] Add a CI matrix in .github/workflows/ci.yml to run these tests for at least 3-5 different target triples

Add Windows-specific cross-compilation tests and documentation

The codebase has platform-specific dependencies for Windows (winapi, dunce) but there's no dedicated Windows CI or documentation explaining which cross-compilation targets are supported on Windows. The README's feature showcase image shows Linux testing only. This creates uncertainty for Windows users about what works.

  • [ ] Add a WINDOWS_SUPPORT.md file documenting which targets are testable/compilable on Windows and any known limitations
  • [ ] Add a Windows-specific GitHub Action job (.github/workflows/ci.yml) that runs cross build for at least 2-3 targets on windows-latest
  • [ ] Add platform-specific unit tests in src/ that validate Windows-only code paths (e.g., dunce path handling) with #[cfg(windows)] tests
  • [ ] Update .cargo/config.toml documentation comments to explain Windows-specific settings if any exist

🌿Good first issues

  • Add integration tests for the aarch64-unknown-linux-gnu target in tests/ directory to verify the full cross build → cross test → binary execution pipeline; currently only unit tests exist for config parsing.
  • Write docs/target-matrix.md documenting officially supported target architectures, their corresponding Dockerfile locations, and any platform-specific quirks (e.g., which targets support cross test vs. cross build only).
  • Implement --dry-run flag in CLI (src/main.rs) to print the exact Docker/Podman command that would be invoked without actually running containers; helpful for debugging and CI integration.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 65fe72b — Define cargo aliases as a strings instead of lists (#1772) (Emilgardis)
  • 5fa6464 — Define cargo aliases as a strings instead of lists (legeana)
  • f86fd03 — fix: lower MSRV to 1.85 (#1762) (Emilgardis)
  • fa944e6 — fix(clippy): needless_lifetimes (xtqqczze)
  • 9274943 — fix: lower MSRV to 1.85 (xtqqczze)
  • 588b3c9 — Fix again FreeBSD image build (#1752) (Emilgardis)
  • ca70711 — Fix again FreeBSD image build (ydirson)
  • 19bc73f — improve /ci try (#1748) (Emilgardis)
  • 81608e1 — make it possible to pass CROSS_DEBUG=true (Emilgardis)
  • 8ce6a3b — add reason for failure in output (Emilgardis)

🔒Security observations

The cross-rs project demonstrates a reasonably secure dependency profile with generally well-maintained crates. The main areas of concern are: (1) potential for shell injection through shell execution helpers if user input is not properly validated, (2) lack of exact version pinning for some dependencies which could introduce unexpected updates, and (3) the importance of regular security audits given the tool's role in compilation workflows where arbitrary code execution is inherent. The project uses reputable security-focused libraries (color-eyre, thiserror, signal-hook) which is positive. No obvious hardcoded credentials, secrets, or SQL/XSS injection risks were identified in the provided materials. Overall security posture is good with minor improvements recommended.

  • Medium · Outdated Rust Version Requirement — Cargo.toml - rust-version field. The project specifies rust-version = '1.85.0' which may contain known vulnerabilities. While this is not critical, it's important to regularly update to the latest stable Rust version to receive security patches. Fix: Regularly review and update the minimum Rust version to ensure security patches are included. Monitor Rust security advisories at https://rustsec.org/
  • Low · Multiple Dependency Versions Not Pinned — Cargo.toml - [dependencies] section. Several dependencies use loose version specifications (e.g., 'which = "8.0"', 'home = "0.5.4"') which can introduce minor/patch updates with potential breaking changes or vulnerabilities. While semantic versioning should prevent major breaking changes, pinning to exact versions provides more control. Fix: Consider using exact version pinning (e.g., '=0.5.4') for critical dependencies or enable auditing with 'cargo audit' to detect known vulnerabilities.
  • Low · Signal Handler Library Usage — Cargo.toml - signal-hook dependency. The dependency 'signal-hook = "0.4"' is used without version pinning. Signal handling can be security-sensitive when dealing with process termination and cleanup. Fix: Pin the exact version and regularly audit this dependency for security updates. Ensure signal handlers properly cleanup resources and don't introduce race conditions.
  • Low · Shell Execution Dependencies — Cargo.toml - shell-escape and shell-words dependencies. The project uses 'shell-escape = "0.1.5"' and 'shell-words = "1.1.0"' for shell command construction. While these are safety-oriented libraries, shell execution always carries risk of injection if not properly validated. Fix: Validate all user inputs before passing to shell execution. Use the shell-escape and shell-words libraries correctly to prevent shell injection attacks. Prefer native APIs over shell invocation when possible.
  • Low · Unrestricted Walk Directory Operations — Cargo.toml - walkdir optional dependency. The 'walkdir' dependency is included as optional but could be used for recursive directory traversal without clear safeguards visible in dependency list. Fix: Ensure walkdir usage includes proper symlink handling (use 'follow_links(false)' by default) to prevent directory traversal attacks. Validate user-provided paths.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · cross-rs/cross — RepoPilot