.__ __
___________|__|/ |_
_/ ___\_ __ \ \ __\
\ \___| | \/ || |
\___ >__| |__||__|
\/
crit automates cross-compiling Rust applications for many different kinds of target platforms.
$ cd example
$ crit
$ ls .crit/bin
aarch64-apple-darwin
aarch64-pc-windows-msvc
aarch64-unknown-linux-gnu
...See crit -h for more options.
cargo install critFor more installation methods, see our install guide.
For more details on developing crit itself, see our development guide.
cargo install --force cross --git https://github.com/cross-rs/cross --rev 4e64366af6095c84fa4f54a0fa5a2ba7d9a271aa- a host capable of running musl/Linux containers (e.g. a GNU/Linux, musl/Linux, macOS, or Windows host)
- a UNIX-like environment (e.g. WSL)
- Docker First Aid Kit
- ~100 GB of disk space allocated to Docker, depending on the breadth of target platforms involved
- Apply
DOCKER_DEFAULT_PLATFORM=linux/amd64environment variable - cargo-cache
- tree
- GNU time
- Amphetamine (macOS), The Caffeine (Windows), Caffeine (Linux) can prevent hibernation during long builds
See CONFIGURATION.md.
Check that your project is able to build with conventional cross or cargo commands against a single target. A project that does not compile against a single target, will naturally have difficulty when attempting to cross-compile for multiple targets.
Note that Rust introduces new, under-supported targets all the time. We try to keep up, but sometimes we miss a few of these. Regardless, you can declare which targets are disabled, by configuring custom patterns.
Some targets may lack stock support for the Rust std library. This is common for bare metal or embedded targets. For these kinds of targets, you have several strategies for resolution:
- Provide a
stdimplementation. Reach out to specialists for the specific target involved. - Avoid using the
stdlibrary, in both your code, as well as the dependency tree. This is actually common practice for many Rust projects, as an proactive stance on embedded development support. - Disable undesired targets.
crit hides a lot of compiler noise. While a target is building, you can use common Docker commands to inspect the compilation process:
docker ps -adocker logs [--follow] <container id>
Yes, it sure is! Almost as slow as using Virtual Machines for cross-compilation.
Rustaceans come to expect that the Rust compiler is analytical, spending more time optimizing programs, so that the final binaries will run safer and faster. The Rust compiler often taking a long time to compile each individual target.
Naturally, when cross-compiling multiple targets, that time multiplies by the number of targets.
Some cross-compilation performance tips:
- Tune your Docker setup (see the Docker First Aid Kit above)
- Reset common Cargo build profile options (
codegen-units,lto,strip, etc.) - Use debug mode (e.g.,
--) - Use fewer dependencies
- Design with the UNIX Philosophy, namely Make each program do one thing well. Not a hundred features poorly.
- Keep the host awake (see Amphetamine / The Caffeine / Caffeine above)
- Reserve cross-compilation as a release-time step, distinct from more rapid development tasks
- Perform cross-compilation in a CI/CD pipeline with more CPU, disk, and RAM resources
- Exclude more targets (e.g. 32 bit targets, GNU targets, or any targets with niche support)
Prior art, personal plugs, and tools for developing portable applications (including non-Rust projects)!
- cross provides the underlying cross-compiler system that powers crit.
- cross-toolchains provisions cross Docker images.
- mcandre/chandler normalizes executable archives.
- mcandre/factorio automates crossplatform ports for Go projects.
- mcandre/rockhopper generates install packages.
- mcandre/tuggy automates multiplatform Docker image builds.
- mcandre/unmake detects quirks in makefiles.
- WASM provides a portable interface for C/C++ code.
- xgo compiles ports for cGo projects.