Plugin for cargo
to run commands against selected combinations of features.
brew install romnn/tap/cargo-fc
# or install from source
cargo install cargo-feature-combinations
In most cases, just use the command as if it was cargo
:
cargo fc check
cargo fc test
cargo fc build
In addition, there are a few optional flags and the matrix
subcommand.
To get an idea, consider these examples:
# run tests and fail on the first failing combination of features
cargo fc --fail-fast test
# silence output and only show final summary
cargo fc --silent build
# print all combinations of features in JSON (useful for usage in github actions)
cargo fc matrix --pretty
For details, please refer to --help
:
$ cargo fc --help
USAGE:
cargo [+toolchain] [SUBCOMMAND] [SUBCOMMAND_OPTIONS]
cargo [+toolchain] [OPTIONS] [CARGO_OPTIONS] [CARGO_SUBCOMMAND]
SUBCOMMAND:
matrix Print JSON feature combination matrix to stdout
--pretty Print pretty JSON
OPTIONS:
--help Print help information
--silent Hide cargo output and only show summary
--fail-fast Fail fast on the first bad feature combination
--exclude-package Exclude a package from feature combinations
--only-packages-with-lib-target
Only consider packages with a library target
--errors-only Allow all warnings, show errors only (-Awarnings)
--pedantic Treat warnings like errors in summary and
when using --fail-fast
In your Cargo.toml
, you can configure the feature combination matrix:
[package.metadata.cargo-feature-combinations]
# When at least one isolated feature set is configured, stop taking all project
# features as a whole, and instead take them in these isolated sets. Build a
# sub-matrix for each isolated set, then merge sub-matrices into the overall
# feature matrix. If any two isolated sets produce an identical feature
# combination, such combination will be included in the overall matrix only once.
#
# This feature is intended for projects with large number of features, sub-sets
# of which are completely independent, and thus don’t need cross-play.
#
# Non-existent features are ignored. Other configuration options are still
# respected.
isolated_feature_sets = [
["foo-a", "foo-b", "foo-c"],
["bar-a", "bar-b"],
["other-a", "other-b", "other-c"],
]
# Exclude groupings of features that are incompatible or do not make sense
exclude_feature_sets = [ ["foo", "bar"], ] # formerly "skip_feature_sets"
# Exclude features from the feature combination matrix
exclude_features = ["default", "full"] # formerly "denylist"
# When using a cargo workspace, you can exclude packages in the *root* `Cargo.toml`
exclude_packages = ["package-a", "package-b"]
# In the end, always add these exact combinations to the overall feature matrix,
# unless one is already present there.
#
# Non-existent features are ignored. Other configuration options are ignored.
include_feature_sets = [
["foo-a", "bar-a", "other-a"],
] # formerly "exact_combinations"
The github-actions matrix feature can be used together with cargo fc
to more efficiently test combinations of features in CI.
First, add a workflow feature-matrix.yaml
that computes the feature matrix for your project.
We will re-use this workflow in our build.yaml
workflow.
# .github/workflows/feature-matrix.yaml
name: feature-matrix
on:
workflow_call:
outputs:
matrix:
description: "feature matrix"
value: ${{ jobs.matrix.outputs.matrix }}
jobs:
matrix:
name: Generate feature matrix
runs-on: ubuntu-24.04
outputs:
matrix: ${{ steps.compute-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v4
- uses: romnn/cargo-feature-combinations@main
- name: Compute feature matrix
id: compute-matrix
run: |-
MATRIX="$(cargo fc matrix)"
echo "${MATRIX}"
echo "matrix=${MATRIX}" >> "$GITHUB_OUTPUT"
Now, we can use the feature-matrix.yaml
workflow result to dynamically create jobs that build each combination of features in parallel.
# .github/workflows/build.yaml
name: build
on:
push: {}
pull_request: {}
jobs:
feature-matrix:
uses: ./.github/workflows/feature-matrix.yaml
build:
name: build ${{ matrix.package.name }} (${{ matrix.os }}, features ${{ matrix.package.features }})
runs-on: ${{ matrix.os }}
needs: [feature-matrix]
strategy:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-24.04]
package: ${{ fromJson(needs.feature-matrix.outputs.matrix) }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Build
# prettier-ignore
run: >-
cargo build
--package "${{ matrix.package.name }}"
--features "${{ matrix.package.features }}"
--all-targets
Of course you can also apply the same approach for your test.yaml
or lint.yaml
workflows!
Per job, up to 256 feature sets can be processed in parallel.
For local development and testing, you can point cargo fc
to another project using
the --manifest-path
flag.
cargo run -- cargo check --manifest-path ../path/to/Cargo.toml
cargo run -- cargo matrix --manifest-path ../path/to/Cargo.toml --pretty
The cargo-all-features
crate is similar yet offers more complex configuration and is lacking a summary.