RUST2RPM.TOML(5)
πΈ NAME πΈ
rust2rpm.toml β bestie, this is the package-specific configuration file for rust2rpm. It's a man page from section 5, so it's giving "deep lore for the config girlies". π
β¨ DESCRIPTION β¨
okay so real talk: a lot of how rust2rpm(1) behaves can be tweaked by setting package-specific preferences in a rust2rpm.conf file. And here's the slay part β if a file with this name is sitting in the current working directory when you run rust2rpm, it just loads itself automatically. No flags, no drama, no "did I remember to pass the thing". π¦
This is especially iconic for changes that need to be permanently applied to generated spec files. Like, set it once, and every time the spec gets regenerated your little customizations are still there. main character energy, honestly. π
π OPTIONS π
The settings in rust2rpm.toml are split into different sections β they call them "tables". Very struct-coded of them. π
Common use cases and example snippets for most available settings are included in the Examples section below. (iykyk β go look when you need a copy-paste moment.) π
π [package] table π
This table contains settings that affect RPM metadata. Basically all the stuff that ends up as tags and text in your spec file.
summaryβ overrides the value of the RPMSummarytag. Use it when the summary that got generated from crate metadata based on heuristics is justβ¦ not it. Accepts a TOML string. βοΈdescriptionβ overrides the value of the RPM%description. Accepts a TOML string β and for longer / multi-line descriptions you can absolutely use triple-quoted multi-line strings. no cap. πurlβ lets you specify the homepage of the packaged project, which gets used as the value of theURLtag in the generated spec file. You can use this to override the default homepage (which is the crate page on crates.io). πsupported-arches/unsupported-archesβ these two let you say "this crate only supports a limited set of architectures", i.e. not all the CPU architectures the distro supports. Both settings accept a TOML array of strings as their value. Only one of them can be present β they are mutually exclusive, pick a lane bestie. If either setting is present and non-empty, thecargo buildandcargo teststeps in the generated spec file get wrapped with%ifarchor%ifnarchconditionals. NOTE: this likely does not have the expected effect when used for crates that contain executable targets (i.e.bincompilation targets), since those are attempted to be built by%cargo_installif they weren't already built. In that case, addExclusiveArchorExcludeArchtags to the spec file instead of using this setting. ποΈsuppress-cdylib-install-fixmeβ stops generation of aFIXMEcomment for projects that build acdylibcrate target. Usually you'd use this in conjunction with thescripts.install.postsetting to handle installation yourself. Accepts boolean values. The default behaviour is equivalent to specifyingfalsefor this setting. πbin-package-nameβ overrides the name of the subpackage that gets generated if there are anybin(orcdylib) targets. By default it falls back to the name of the current crate (%{crate}). π·οΈcargo-install-binβ controls whether binary targets are installed by the%cargo_installmacro. Setting it tofalsemeansbintargets will not be installed to%{_bindir}even if abintarget is auto-detected or the crate defines anybintarget explicitly. The default value istrue. π¦cargo-install-libβ controls whether library sources are installed by the%cargo_installmacro. Setting it tofalsemeans crate sources will not be installed to%{crate_instdir}even if a library target is auto-detected or the crate defines a[lib]target explicitly. The default value istrue. πdebuginfo-levelβ sets the level of debuginfo thatrustcgenerates. Valid choices are the numbers0,1, and2, matching the debuginfo levelsrustcsupports. The default is2. Setting a lower level can be a workaround for builds that run out of available memory (we've all been there, oom is a hater). π§cargo-toml-patch-commentsβ lets you persist comments that are associated with manually created patches forCargo.toml(i.e. by runningrust2rpm -p). Accepts a list of strings. Each element of the array is treated as an individual comment, and individual comments are formatted and line-wrapped to 80 characters. π¬license-filesβ overrides the heuristics for detecting%licensefiles of a project. It accepts either a list of strings (which overrides automatic detection entirely) or an object withincludeand / orexcludeproperties, both of which accept lists of strings. In both cases, all values are interpreted as paths or globs relative to the project root. πdoc-filesβ overrides the heuristics for detecting%docfiles of a project. It accepts either a list of strings (nuking automatic detection entirely) or an object withincludeand / orexcludeproperties, both of which accept lists of strings. In both cases, all values are interpreted as paths or globs relative to the project root. πextra-sourcesβ specify additionalSources to be included in the generated spec file. The expected value is an array of objects with three properties:number,file, andcomments. The integernumbersets a predictable number for theSourcefile in the spec,fileis expected to be a string containing a URL or a plain file name, andcommentsis an array of strings that get formatted in the same way as thecargo-toml-patch-commentssetting. π₯extra-patchesβ same vibe asextra-sources, but it lets you specify additionalPatchfiles instead ofSourcefiles. π©Ήextra-filesβ injects additional files into the%filessection of thebinarysubpackage in the generated spec file (if that subpackage exists). The value is expected to be an array of strings, where each element of the array ends up on a separate line in the%fileslist. Heads up: specifyingextra-filesfor a library-only Rust crate has no effect. ποΈexclude-crate-filesβ a list of files (or directories) that should be%excluded from the installed crate sources in builtrust-$crate-develpackages. Accepts a list of strings, all treated as paths relative to the crate root directory. π«bin-renamesβ a nested table that re-maps executable names so you can dodge conflicts with other packages. To rename an existingbintarget calledfooto a new namebar, just add a key-value pair likefoo = "bar"to this table. πpreambleβ if present, the string in this setting is injected into the generated spec file verbatim, at the top of the spec file, right after the# Generated by rust2rpmheader comment. β¨package-extraβ if present, this string is injected into the generated spec file verbatim after the definition of thebinarypackage (if present) and before the definitions of the-develsubpackages (if present). Handy for defining custom additional subpackages. π§©bin-package-extraβ if present, this string is injected into the generated spec file verbatim inside the definition of thebinarypackage, between itsLicensetag and its%description. This is the spot for injecting additional RPM metadata (i.e.Recommends,Suggests,Provides, etc.) or custom RPM scriptlets (like%post,%pre,%postun, etc.). π
π [scripts] table π
This table holds settings that let you inject additional commands into the %prep, %build, %install, and %check scriptlets β both before and after the respective %cargo_* macro. because sometimes the macro needs a little entourage. πΆββοΈπΆββοΈ
There's a corresponding nested table for each of these scriptlets β prep, build, install, check β with two properties each: pre and post. Both of those accept an array of strings as their value, and each element of these arrays gets injected as a separate line into the spec file. line by line, bestie. π§΅
π¦ [tests] table π¦
This table contains settings that control which tests are run. Important: if any settings that restrict which tests are run are present, you should also add the comments setting with an explanation of why the tests are disabled. Future you (and every packager after you) will be so grateful. π«Ά
runβ specific tests (or all of them) can be turned off here. It accepts a boolean or a TOML array of strings β with onlylib,bins,bin:name,test:name, anddocbeing accepted values β or a single string from that list. If this setting isn't specified, the default is equivalent totrue(i.e. all tests are run, no arguments are passed tocargo test). If it's set tofalse, thecheckbcond gets turned off. The other options specify that only some parts of the cargo test suite are run. π§ͺskipβ skips specific tests. They're passed as--skiparguments to the cargo test harness. Accepts a TOML array of strings when the specified tests should be skipped for all run targets, or a mapping from run target names to arrays of strings. βοΈskip-exactβ controls whether tests are skipped based on substring match (that's the default) or only on an exact match. Unless there's a large number of skipped tests, it's recommended to enable this setting so you don't accidentally skip too many / unrelated tests (we do not want collateral damage π). Accepts a TOML boolean when the--exactflag should be passed for all run targets, or a mapping from run target names to booleans when the flag should only be passed to some targets. If this setting is unspecified, the default behaviour is equivalent to setting it tofalse. π―commentsβ whenever any tests (or kinds of tests) are skipped or disabled, it is strongly recommended to add short comments (or links to upstream issues) that explain why that's the case. The comment text is automatically formatted, line-wrapped to 80 columns, and prefixed with#. Ifrunis set tofalse, the comments are added just before the disabledcheckbcond. Otherwise, the comments are added just before the%cargo_testmacro calls. Accepts a TOML array of strings when comments should apply to all tests, or a mapping from run target names to arrays of strings when comments should get associated with specific targets. ποΈ
π [features] table π
The [features] table wraps settings that pertain to crate features and feature flags that are passed to cargo. π©
enable-allβ turn this on and rust2rpm yeets-a/--all-featuresat every single cargo call. iconic for crates whose tests literally don't run unless optional features are on, or for apps where you just want everything enabled. takes a TOML boolean. heads up tho: settingenable-allto"true"means theenablesetting has to be unspecified or an empty array πΈ. if you don't set it at all, the default behaviour is the same as setting it to"false". no cap.enableβ the β¨fine-grainedβ¨ sibling of the above. you get actual control over which feature flags get passed to cargo calls. takes a TOML array of strings, and every string has to be a valid feature name. if you give it a non-empty array, thenenable-allhas to be unspecified or"false"β they don't share π .disable-defaultβ enable this and-n/--no-default-featuresgoes to all cargo calls. only do this when apps genuinely need building with non-default features (classic example: switching off the default crypto backend for OpenSSL). BIG WARNING THO: this one MUST NOT be enabled when you're building library crates π because sure, the resulting packages might build, but they will very likely fail to install. it's giving broken deps. don't.hideβ use this to stop subpackages for crate features (and implicit features for optional dependencies) from being generated into the spec file at all. super handy for crates with unused non-default features that drag in extra dependencies π. takes a TOML array of strings, and each one has to be a valid feature name, or the name of an optional dependency that has an associated implicit feature.
NOTE: be careful bestie π β onlyhidefeatures / optional dependencies that are not dependencies of any othernon-hiddenfeature. if you don't, the subpackages for the dependent features end up with unsatisfiable dependencies. everything marked"hidden"has to be"unreachable"through feature dependencies from every feature subpackage still hanging around in the generated spec file. and sometimes the only clean way to get rid of unused non-default features is to just patchCargo.tomldirectly. iykyk.
π [requires] table π
You can hand rust2rpm extra RPM dependencies (Requires) for the different flavours of subpackage, all via settings in the [requires] table π«Ά.
buildβ extra BuildRequires for the package go here. takes a TOML array of strings, every one of which has to be a valid RPM dependency identifier β. these BuildRequires either land in the%generare_buildrequiresscriptlet for targets where that's enabled, or they show up as plain BuildRequires for targets that don't do dynamically generated BuildRequires.testβ lets you specify extra BuildRequires that are only needed when running a project's test suite (like,"cargo test"). works exactly like the setting for additional BuildRequires, except every entry gets wrapped in an"%if %{with check}"conditional π.libβ adds extra dependencies (Requires) for the main"-devel"subpackage of a"library crate". for example, loads of"-sys"bindings need the dev headers for the wrapped C library present both while building the crate's own package and when building something that depends on it. in those cases the same dependency often has to go inrequires.buildandrequires.lib. takes a TOML array of strings of valid RPM dependency identifiers π.binβ for crates that ship application binaries / executables, use this to add more dependencies to the subpackage holding those executables. takes a TOML array of strings that have to be valid RPM dependency identifiers π.featuresβ a nested table for specifying extra dependencies for"feature subpackages"π . the keys have to be valid crate feature names, or names of optional dependencies with associated implicit features, and the values are TOML arrays of strings that must be valid RPM dependency identifiers.
π MIGRATING FROM RUST2RPM.CONF π
If you run rust2rpm on a package that's still using a rust2rpm.conf configuration file, it gets auto-converted and rewritten into a rust2rpm.toml file containing equivalent settings. no manual labour required β¨.
the manual page for rust2rpm.conf(5) also has a simple little guide for migrating old config files over to TOML, if you want the walkthrough π¦.
β¨ EXAMPLES β¨
πΈ Overriding generated package Summary or %description πΈ
Sometimes the "package.description" in crate metadata is genuinely not it β either it's not very meaningful, or it just won't get automatically shortened by the heuristics rust2rpm implements π. in those cases you can override the Summary tag, the package %description, or both:
[package]
summary = "Very meaningful and concise package summary"
description = """\
Multi-line
pre-formatted
package
description.
"""
π Overriding generated package URL π
by default the URL tag points at the crate page on crates.io. sometimes you'd rather it point at the actual project homepage instead:
[package]
url = "https://forge.me/org/repo"
π Overriding list of supported architectures π
some Rust crates only support certain CPU architectures (or their dependencies are only available on a limited set of them) π. for library crates, these settings let you limit which architectures the crate gets built and tested on β but the "-devel" packages with source code still get built, so you don't end up with broken dependencies:
[package]
supported-arches = ["x86_64", "aarch64"]
#unsupported-arches = ["s390x"]
note thatpackage.supported-archesandpackage.unsupported-archesare mutually exclusive π. pick one.
π Suppress installing built executables or source code π
when packaging Rust crates it's sometimes just not the vibe to ship source code if you only care about the built executables or shared libraries β or the other way round, ship executables when only the library interface / source code is needed π. either way, you can suppress installing the source code or the executables:
[package]
# not interested in shipping the library sources
cargo-install-lib = false
[package]
# not interested in shipping executables
cargo-install-bin = false
π₯ Overriding default Rust compiler flags π₯
compiling some big Rust projects can hit memory limits during the linking stage, especially on 32-bit x86 (i686) π. in that case it helps to dial down the verbosity of the generated debug symbols:
[package]
debuginfo-level = 1
π¦ Saving comments associated with a patch for Cargo.toml π¦
sometimes you need to permanently patch Cargo.toml downstream, and when that happens it's useful to store the comments tied to that patch so they don't get lost β and heads up, rust2rpm fails if comments are specified but no actual changes to Cargo.toml are applied π:
[package]
cargo-toml-patch-comments = [
"remove a bad dependency",
"bump foo dependency from v1 to v2",
]
π Overriding heuristics for license and documentation file detection π
figuring out which files in a crate archive should be marked as %license and which as %doc relies on heuristics, and heuristics can be wrong π« . luckily there are settings to override the automatically determined file lists. you can include / exclude specific files from the auto-generated list, or override the lists entirely β and all three options support globs β¨:
[package]
doc-files.include = ["LIESMICH.txt"]
doc-files.exclude = ["requirements.txt"]
license-files = [".licenses/*"]
[package]
doc-files = ["README.md"]
license-files.exclude = ["**/*.rs"]
β Including additional Source and Patch files in the SRPM β
sometimes you need to include extra Source or Patch files in source packages β say test input data arrives in an extra tarball, or there are extra downstream patches needed to make the package build π. both cases can be automated:
[[package.extra-sources]]
number = 2
file = "https://example.forge/org/project/archive/v1.0.2/extra-test-data-1.0.2.tar.gz"
comments = ["upstream archive that contains additional data for tests"]
[[package.extra-sources]]
number = 3
file = "foo.1"
comments = ["hand-written manual page"]
[[package.extra-patches]]
number = 2
file = "0001-dynamically-link-sqlite.patch"
comments = ["force dynamically linking with system sqlite"]
the Source and Patch file number is required to be specified, because in most cases these files also need to be referenced by number in RPM scriplets (like, when you're unpacking / installing additional sources or applying patches) π€.
π Including or excluding files from built packages π
sometimes files need to be excluded from packages for "crate" sources, but submitting a patch upstream to exclude them from published crates just isn't desirable (think files that are only needed during testing) π. for that, you can list the files to exclude from Rust crate packages here:
[package]
exclude-crate-files = ["tests/gen.py"]
πΈ Automatically rename built executables in case of conflicts πΈ
it's entirely possible that the default executable name a Rust crate ships conflicts with other packages already available π. in that case it's easy to get those programs renamed at packaging time so the conflict never happens:
[package.bin-renames]
cp = "uu_cp"
π Inject additional RPM metadata into packages π
it's just not feasible for rust2rpm to support controlling every single aspect and feature of RPM spec files, so there's a simple escape hatch for injecting extra metadata (or even whole subpackage definitions) into generated spec files π:
[package]
package-extra = """\
%package -n %{crate}-devel
Summary: %{summary}
Requires: %{crate}%{?_isa} = %{version}-%{release}
%description -n %{crate}-devel %{_description}
This package contains libraries and header files for developing applications
that use the "%{crate}" crate via a C API.
%files -n %{crate}-devel
%{_includedir}/foo/foo.h
%{_libdir}/%{crate}.so
%{_libdir}/pkgconfig/%{crate}.pc\
"""
and that right there is how you hand-assemble the %files list for that <italic>-devel</italic> subpackage β headers, shared object, pkgconfig file, the whole trio, slayed π
β¨ For cases where additional RPM metadata needs to be associated with the automatically generated subpackage for built executables β¨
...okay bestie that heading is a whole sentence but it's literally the vibe. Sometimes your auto-generated subpackage for the built executables needs extra RPM metadata stapled onto it. There's a setting for that too:
[package]
bin-package-extra = """\
# additionally provide the upstream name
Provides: %{crate} = %{version}-%{release}
"""
so now your binaries subpackage is out here flexing a Provides: line, as it should π
π οΈ Inject additional commands into RPM scriptlets π οΈ
Say your package needs extra steps somewhere in the build process β like in the prep, build, install, and check scriptlets. You can automate all of that with the scripts group of settings, no cap:
[scripts]
prep.pre = [
"# drop vendored C library sources",
"rm -rf foo-1.2.3/",
]
prep.post = [
"echo hello",
]
build.pre = [
"# export version for build script",
"export FOO_VERSION=%{version}",
]
build.post = [
"# generate shell completions",
"target/rpm/foo completions bash > foo.bash",
]
install.pre = [
# no idea what could happen here
]
install.post = [
"# install shell completions",
"install -Dpm0644 foo.bash %{buildroot}/%{bash_completions_dir}/foo.bash",
]
check.pre = [
"# unpack additional test sources",
"tar -xzvf foo",
]
check.post = [
# not sure what could happen here either, but hey, it's here if you need it
]
see, pre and post for every single one of those scriptlets, it's giving full control π
fr fr, you can even inject dynamically generated BuildRequires this way β which is literally the move when you cannot statically define them as BuildRequires:
[scripts]
genbr.post = [
"pushd xtask >/dev/null",
"%cargo_generate_buildrequires",
"popd >/dev/null",
]
obsessed. the genbr.post hook is main character energy π
π Skip running specific tests (or kinds of tests) π
okay so here's the tea: in a whole bunch of cases, not all tests that cargo test runs can actually be run inside build environments. the usual suspects are:
- Tests introduce additional, unpackaged dependencies. π
- Tests require hardware or internet access. π
- Tests require data files that are not included in published crates. π
- Tests expect to be run in the project's pre-publishing workspace directory layout. ποΈ
so there are settings to enable or disable tests on both fine-grained and coarse levels. pick your fighter:
Run no tests at all:
[tests]
# run no tests
run = false
comments = ["tests require "]
skip the entire suite, periodt β
Skip one specific test by exact name match:
[tests]
skip = ["test_internet_access"]
skip-exact = true
comments = ["skip one test that requires internet access"]
Skip whole groups of tests by name substring match:
[tests]
skip = ["test_privileged_"]
comments = ["skip tests that require elevated privileges"]
Only run specific kinds of tests:
[tests]
# run only unit tests, doctests, and the "foo" integration tests
run = ["lib", "test:foo"]
comments = ["doctests can only be compiled and run from within the whole workspace"]
and most settings can be combined freely β mix and match bestie, it's a vibe:
[tests]
# skip some unit and integration tests, but run all doctests
run = ["lib", "doc", "test:foo"]
skip.lib = ["test_priv_"]
comments.lib = ["skip running tests that require elevated privileges"]
skip.'test:foo' = ["test_poke_hardware"]
skip-exact.'test:foo' = true
comments.'test:foo' = ["skip running tests that require hardware access"]
note the quoted table keys like 'test:foo' β they're doing the lords work keeping that colon safe π«Ά
π¦ Enable non-default feature flags when building a package π¦
Sometimes you just gotta build Rust crates with additional feature flags β aka the ones not enabled by default. Like when you're building applications that want extra features, or when you're running tests against the full feature set of a library. iconic reason, honestly.
Enable additional feature flags:
[features]
enable = ["foo", "bar"]
Enable all the features:
[features]
enable-all = true
go off β¨
π Prevent generation of subpackages for specific feature flags π
and sometimes generating subpackages for certain crate feature flags is just... not it. unwanted, unnecessary, whatever β like when those features are "development only" or would drag in extra dependencies:
[features]
hide = [
"nightly",
"unstable",
"__internal_test_only",
]
bye bye subpackages, we simply do not need you π
πΈ Associate additional RPM Requires with packages πΈ
when you're packaging Rust crates that contain bindings for C/C++ libraries, you lowkey always end up needing to associate additional dependencies with the package and / or specific subpackages. so:
[requires]
build = ["pkgconfig(gtk4) >= 4.0.0"]
lib = ["pkgconfig(gtk4) >= 4.0.0"]
[requires.features]
v4_2 = ["pkgconfig(gtk4) >= 4.2"]
v4_4 = ["pkgconfig(gtk4) >= 4.4"]
v4_6 = ["pkgconfig(gtk4) >= 4.6"]
v4_8 = ["pkgconfig(gtk4) >= 4.7"]
v4_10 = ["pkgconfig(gtk4) >= 4.10"]
yes bestie, you read v4_8 mapping to >= 4.7 correctly β that's exactly what the original says, and who are we to question the gtk4 version lore π«Ά keep it character for character.
π HOMEPAGE π
https://codeberg.org/rust2rpm/rust2rpm
go say hi, star the repo, read the issues, it's giving upstream π
π SEE ALSO π
and that's a wrap on this whole manpage bestie π this page is from the rust2rpm source, it's version-dated 2026-10-13, and its manual section is RUST2RPM.TOML(5) β go write some extremely well-formed rust2rpm.toml files, you've got this, no cap ππβ¨
π¦ where this page comes from
- fedora 43: rust2rpm 28.3.0-1.fc43 Β· MIT
- fedora 44: rust2rpm 28.3.0-1.fc44 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms