Crates.io | cargo-multivers |
lib.rs | cargo-multivers |
version | 0.9.0 |
source | src |
created_at | 2023-02-09 21:56:13.391865 |
updated_at | 2024-07-26 14:12:51.615014 |
description | Cargo subcommand to build multiple versions of the same binary, each with a different CPU features set, merged into a single portable optimized binary |
homepage | |
repository | https://github.com/ronnychevalier/cargo-multivers |
max_upload_size | |
id | 781158 |
size | 99,871 |
cargo-multivers
Cargo subcommand to build multiple versions of the same binary, each with a different CPU features set, merged into a single portable optimized binary.
cargo-multivers
builds multiple versions of the binary of a Rust package.
Each version is built with a set of CPU features (e.g., +cmpxchg16b,+fxsr,+sse,+sse2,+sse3
) from a CPU (e.g., ivybridge
) supported by the target (e.g., x86_64-pc-windows-msvc
).
By default, it lists the CPUs known to rustc
for a given target, then it fetches each set of CPU features and filters out
the duplicates (i.e., the CPUs that support the same extensions).
You can also add a section to your Cargo.toml
to set the allowed list of CPUs for your package.
For example, for x86_64
you could add:
[package.metadata.multivers.x86_64]
cpus = ["x86-64", "x86-64-v2", "x86-64-v3", "x86-64-v4", "raptorlake"]
After building the different versions, it computes a hash of each version and it filters out the duplicates
(i.e., the compilations that gave the same binaries despite having different CPU features).
Finally, it builds a runner that embeds one version compressed (the source) and the others as compressed binary patches to the source.
For instance, when building for the target x86_64-pc-windows-msvc
, by default 37 different versions
will be built, filtered, compressed, and merged into a single portable binary.
When executed, the runner uncompresses and executes the version that matches the CPU features of the host.
While cargo-multivers
could be used to build any kind of binary from a Rust package,
it is mostly intended for the following use cases:
[!TIP] If you only want to optimize your program for your CPU, do not use
cargo multivers
, you can just use-C target-cpu=native
like this:RUSTFLAGS=-Ctarget-cpu=native cargo build --release
. You will save some CPU cycles :)
This project is tested on Windows and Linux (due to the use of memfd_create
, only Linux >= v3.17 is supported).
In theory the following architectures are supported: x86, x86_64, arm, aarch64, riscv32, riscv64, powerpc, powerpc64, mips, and mips64. But only x86_64 is tested.
cargo install --locked cargo-multivers
cargo +nightly multivers
cargo multivers
uses the release
profile of your package to build the binary ([profile.release]
).
To optimize the size of your binary and to reduce the startup time, it is recommended to enable features that can reduce the size of each build.
For example, you can have the following profile that reduce the size of your binary, while still prioritizing speed optimizations and not increasing significantly the build time:
[profile.release]
strip = "symbols"
panic = "abort"
lto = "thin"
To reduce the total build time, it might be best to limit the set of CPUs for which the project will be built.
For instance, you can add to your Cargo.toml
the following section if you build for x86_64
:
[package.metadata.multivers.x86_64]
cpus = ["x86-64", "x86-64-v2", "x86-64-v3", "x86-64-v4"]
If you want to publish an optimized portable binary built by cargo-multivers
when releasing a new version of your project,
you can use the cargo-multivers
GitHub Action.
To do that you need to have a Rust nightly toolchain
and add a step to your job:
- uses: ronnychevalier/cargo-multivers@main
For example, this can look like:
jobs:
cargo-multivers-build:
name: Build with cargo-multivers
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust nightly
uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly
- uses: ronnychevalier/cargo-multivers@main
with:
manifest_path: path/to-your/Cargo.toml
- name: Upload release archive
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
with:
files: the-name-of-your-binary.exe
... [other config fields]
You can set two types of inputs.
The ones that are related to how cargo-multivers
is installed:
Name | Description | Required | Default |
---|---|---|---|
version | Version of cargo-multivers to use (e.g., 0.7.0) | false | Latest published version on crates.io |
And the ones that are related to the arguments given to cargo multivers
(e.g., target
configures the --target
option):
Name | Description | Required | Default |
---|---|---|---|
manifest_path | Path to Cargo.toml | false | |
target | Build for the target triple | false | |
out_dir | Copy final artifacts to this directory | true | . |
profile | Build artifacts with the specified profile | false | |
runner_version | Specify the version of the runner to use | false | |
other_args | Other arguments given to cargo multivers | false | |
build_args | Arguments given to cargo build | false |
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.