Expand description
featurecomb allows you to define groups of Cargo features and define different kinds of relations between features and these feature groups from your crate’s manifest, and enforce them at compile time.
§Installation
Simply add featurecomb
as a dependency to your crate.
§Usage
Define feature groups and feature relations in your manifest metadata
table
as explained below, and use the #[featurecomb::comb]
attribute macro in
your crate top module to have these checked automatically at compile time.
§How it works
featurecomb generates compile-time checks using #[cfg]
-gated compile_error!
statements
so that the requirements defined are checked by the compiler.
§Feature groups
Feature groups are defined in the [package.metadata.feature-groups]
table.
They do not live in the same namespace as features, i.e., feature groups can be named the same
as existing features and will not conflict with them.
§Marking features as mutually exclusive: $group.xor
Features of a group can be marked as mutually exclusive using the xor
table:
[package.metadata.feature-groups]
openssl.xor = { features = ["native-openssl", "vendored-openssl"] }
Performance note: the number of generated checks increases quadratically with the number of features in the group.
§Requiring exactly one feature: $group.exactly-one
When features of a group are mutually exclusive but one must always be enabled, the
exactly-one
table is to be used instead:
[package.metadata.feature-groups]
llvm-version.exactly-one = { features = ["llvm-16", "llvm-17", "llvm-18"] }
Performance note: the number of generated checks increases quadratically with the number of features in the group.
§Defining a feature group with no relations
A feature group can also be defined without enforcing any relations between the features of that group:
[package.metadata.feature-groups]
ip-version = { features = ["ipv4", "ipv6"] }
This is useful so that the group can be required by a feature, to express an “at least one” relation.
§Features
Feature relations are defined in the [package.metadata.feature-groups.features]
table.
They define relations for features already existing in the standard
[features]
table.
§Requiring groups and features: $feature.requires
The requires
table on a feature requires that the features and features groups listed be
enabled when that feature is enabled:
[package.metadata.feature-groups.features]
tls.requires = { groups = ["openssl", "tls-version"] }
[package.metadata.feature-groups.features]
usb-hid.requires = { features = ["usb"] }
It is possible to use the groups
and features
keys at the same time, in which case all
features and feature groups listed are required.
§Example
See the examples
directory in the repository, which contains a playground to try out the
following example:
[package.metadata.feature-groups]
ip-version = { features = ["ipv4", "ipv6"] }
llvm-version.exactly-one = { features = ["llvm-16", "llvm-17", "llvm-18"] }
openssl.xor = { features = ["native-openssl", "vendored-openssl"] }
tls-version = { features = ["tls-12", "tls-13"] }
[package.metadata.feature-groups.features]
tls.requires = { groups = ["openssl", "tls-version"] }
usb-hid.requires = { features = ["usb"] }
[features]
ipv4 = []
ipv6 = []
llvm-16 = []
llvm-17 = []
llvm-18 = []
usb = []
usb-hid = []
tls = []
tls-12 = []
tls-13 = []
native-openssl = []
vendored-openssl = []
§Compatibility
The error messages generated by this crate should not be considered stable.
Attribute Macros§
- comb
- This macro reads the feature groups and the feature relations defined in your crate’s manifest, and enforces them at compile time.