RUST2RPM.TOML(5)

πŸ“¦
version 28.3.0 Β· 4 versions
, in fedora 43, fedora 44

🌸 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 RPM Summary tag. 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 the URL tag 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, the cargo build and cargo test steps in the generated spec file get wrapped with %ifarch or %ifnarch conditionals. NOTE: this likely does not have the expected effect when used for crates that contain executable targets (i.e. bin compilation targets), since those are attempted to be built by %cargo_install if they weren't already built. In that case, add ExclusiveArch or ExcludeArch tags to the spec file instead of using this setting. πŸ—οΈ
  • suppress-cdylib-install-fixme β€” stops generation of a FIXME comment for projects that build a cdylib crate target. Usually you'd use this in conjunction with the scripts.install.post setting to handle installation yourself. Accepts boolean values. The default behaviour is equivalent to specifying false for this setting. πŸ™ˆ
  • bin-package-name β€” overrides the name of the subpackage that gets generated if there are any bin (or cdylib) 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_install macro. Setting it to false means bin targets will not be installed to %{_bindir} even if a bin target is auto-detected or the crate defines any bin target explicitly. The default value is true. πŸ“¦
  • cargo-install-lib β€” controls whether library sources are installed by the %cargo_install macro. Setting it to false means 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 is true. πŸ“š
  • debuginfo-level β€” sets the level of debuginfo that rustc generates. Valid choices are the numbers 0, 1, and 2, matching the debuginfo levels rustc supports. The default is 2. 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 for Cargo.toml (i.e. by running rust2rpm -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 %license files of a project. It accepts either a list of strings (which overrides automatic detection entirely) or an object with include and / or exclude properties, 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 %doc files of a project. It accepts either a list of strings (nuking automatic detection entirely) or an object with include and / or exclude properties, 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 additional Sources to be included in the generated spec file. The expected value is an array of objects with three properties: number, file, and comments. The integer number sets a predictable number for the Source file in the spec, file is expected to be a string containing a URL or a plain file name, and comments is an array of strings that get formatted in the same way as the cargo-toml-patch-comments setting. πŸ“₯
  • extra-patches β€” same vibe as extra-sources, but it lets you specify additional Patch files instead of Source files. 🩹
  • extra-files β€” injects additional files into the %files section of the binary subpackage 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 %files list. Heads up: specifying extra-files for 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 built rust-$crate-devel packages. 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 existing bin target called foo to a new name bar, just add a key-value pair like foo = "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 rust2rpm header comment. ✨
  • package-extra β€” if present, this string is injected into the generated spec file verbatim after the definition of the binary package (if present) and before the definitions of the -devel subpackages (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 the binary package, between its License tag 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 only lib, bins, bin:name, test:name, and doc being accepted values β€” or a single string from that list. If this setting isn't specified, the default is equivalent to true (i.e. all tests are run, no arguments are passed to cargo test). If it's set to false, the check bcond 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 --skip arguments 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 --exact flag 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 to false. 🎯
  • 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 #. If run is set to false, the comments are added just before the disabled check bcond. Otherwise, the comments are added just before the %cargo_test macro 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-features at 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: setting enable-all to "true" means the enable setting 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, then enable-all has to be unspecified or "false" β€” they don't share πŸ’….
  • disable-default β€” enable this and -n / --no-default-features goes 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 πŸ™ˆ β€” only hide features / optional dependencies that are not dependencies of any other non-hidden feature. 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 patch Cargo.toml directly. 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_buildrequires scriptlet 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 in requires.build and requires.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 that package.supported-arches and package.unsupported-arches are 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