RPM-DEPENDENCY-GENERATORS(7)
π RPM-DEPENDENCY-GENERATORS π
okay bestie, welcome to rpm-dependency-generators(7) β Miscellaneous Information Manual energy, but make it cute. this is the page about how RPM clocks file attributes and dependency generators, and yes it's a lot, but we're gonna get through it together β¨
πΈ NAME πΈ
rpm-dependency-generators β the whole RPM file attribute and dependency generator interface, no cap π
π SYNOPSIS π
ποΈ File attributes
%__NAME_path PATH_RE
%__NAME_magic MAGIC_RE
%__NAME_mime MIME_RE
%__NAME_exclude_path PATH_RE
%__NAME_exclude_magic MAGIC_RE
%__NAME_exclude_mime MIME_RE
%__NAME_flags FLAG[,FLAG ...]
%__NAME_exclude_flags FLAG[,FLAG ...]
βοΈ Generators
%__NAME_TYPE COMMAND
%__NAME_TYPE() BODY
%__NAME_protocol {singlefile|multifile}
ποΈ Per-package tunables
%_local_file_attrs NAME[:NAME ...]
%__TYPE_exclude DEPSTRING_RE
%__TYPE_exclude_from PATH_RE
%__NAME_TYPE_opts OPTS
π Notes
so TYPE lowkey has a whole roster, it can be one of conflicts, enhances, obsoletes, orderwithrequires, provides, recommends, requires, suggests and supplements. and FLAG? that one's just exeonly and magic_and_path, that's the whole list bestie π
π DESCRIPTION π
RPM runs a pluggable interface married to a file classifier, and together they sprinkle dependency info onto packages at build time. the system leans on specialized executables called generators β they're the ones doing the heavy lifting, extracting dependencies from files in their domain, which is called a file attribute. it's giving teamwork. and it complements the manual tags you already know and love β stuff like Requires or Provides over in rpm-spec(5) files π«Ά
π¦ FILE ATTRIBUTES π¦
a file attribute is basically a logical label RPM slaps onto one or more files in the buildroot. how does it decide? based on a set of matching rules and their tunables, all defined as macros. an attribute can stand for one single file type (hello, ELF π) or a whole broader domain, like everything installed into a specific location, or every file written in some particular programming language. versatile icon behavior.
these attributes are not the same as filesystem file attributes, jsyk. they only live in memory during package builds. one file can carry an arbitrary number of attributes, and one attribute can land on an arbitrary number of files. everyone's thriving, everyone's coexisting π
want to introduce a file attribute called NAME for use during package builds? drop an rpm-macrofile(5) named NAME.attr into the %{_fileattrsdir} directory. that file should define at least one of the matching rules described below, periodt.
π― Matching rules
%__NAME_path PATH_REβ match theregex(7)stringPATH_RE, macro-expanded on use, against filenames without the%{buildroot}prefix (like/bin/bash, for example).%__NAME_magic MAGIC_REβ match theregex(7)stringMAGIC_RE, macro-expanded on use, againstfilemagic(5).
to figure out a compatible MAGIC_RE, run:
file -z -e tokens /some/file
%__NAME_mime MIME_REβ match theregex(7)stringMIME_RE, macro-expanded on use, against MIME file types.
to figure out a compatible MIME_RE, run:
file --mime /some/file
%__NAME_exclude_path PATH_RE%__NAME_exclude_magic MAGIC_RE%__NAME_exclude_mime MIME_REβ filter out files matching the givenregex(7). these rules are the exclusion counterparts of the inclusion rules above, the little shadow selves π€
okay so here's the matching situation: matching is inclusive unless a flag changes it (flags are below, bestie). if the path matches, or the magic matches, or both match, the file is said to have the attribute in question β unless there's a matching exclusion rule (which is also inclusive by default) or a flag that prevents the match. and heads up: if both the magic and mime rules are defined, the magic rule gets ignored and a warning gets printed π
ποΈ Tunables
%__NAME_flags FLAGS%__NAME_exclude_flags FLAGSβ tweak the inclusion rules and the exclusion rules respectively.
FLAGS is a comma-separated list, and the possible values are:
exeonly: require executable bit setmagic_and_path: require both magic and path to match
β‘ GENERATORS β‘
a generator is an executable that reads filenames from standard input and writes dependencies of a single type to standard output, according to a protocol. it's written for one specific file attribute, and it gets defined as a macro inside the respective NAME.attr file. zero or more generators can be defined for a single file attribute β one for each supported type. so like, pick your roster, no pressure π
π§ Generator macros
%__NAME_conflicts COMMAND%__NAME_enhances COMMAND%__NAME_obsoletes COMMAND%__NAME_orderwithrequires COMMAND(Added: 4.17.0)%__NAME_provides COMMAND%__NAME_recommends COMMAND%__NAME_requires COMMAND%__NAME_suggests COMMAND%__NAME_supplements COMMAND
these generate dependencies of the respective type. COMMAND (a program name plus any arguments) gets executed, and RPM passes it one or more filenames that carry the file attribute NAME on standard input, then reads dependency strings from its standard output. for the whole tea on the input and output format, check Protocols π
π‘ Protocols
%__NAME_protocol PROTOCOLβ usePROTOCOLwhen running dependency generators for the file attributeNAME. this decides the standard input and standard output format that the generators have to implement.
PROTOCOL can be one of these two:
singlefile- stdin: one matching filename at a time
- stdout: dependency strings, one per line
multifile- stdin: all matching filenames at once, one per line
- stdout: dependency strings, one per line, with the original filename, prepended with
;(semicolon), printed on its own line before the dependencies for that file (Added: 4.20.0)
if this macro isn't defined at all, the singlefile protocol is the one that gets used. and for newly written generators, multifile is the recommended pick since it's more performant β go fast, bestie ποΈ
unlike thePATH_REin file attributes, generators receive filenames with the%{buildroot}prefix, so that they can actually access the real file contents on disk.
generators must always consume all of standard input. and for backwards compatibility reasons, generators should not make any assumptions about how many files get passed, regardless of which protocol is in use. stay flexible β¨
π€ Exported macros
on top of the globally defined macros, these following ones get automatically exported to generators, on a subpackage basis:
%{name}%{epoch}%{version}%{release}
Added: 4.15.0
πͺ Parametric generators
if a generator is declared as a parametric macro, then the macro itself gets called for dependency generation, with the filename as its first argument (%1). the macro expansion itself counts as the generated dependencies, one per line.
here's a trivial little example that creates provides from path basenames β and it's enormously faster than the equivalent traditional generator that shells out to execute a script calling basename(1):
%__foo_provides() %{basename:%{1}}
RPM's own macro primitives are kinda limited ngl, but busting out %{lua} unlocks writing complicated, macro-only generators. iconic.
see PARAMETRIC MACROS and Lua expansion in rpm-macros(7) for the details π
Added: 4.16.0
π External generators
%__find_TYPE COMMANDβ generate dependencies of the respectiveTYPE.COMMAND(a program name plus any arguments) gets executed, and RPM passes it the entire file list of the package at once, then reads dependency strings from its standard output. see Generator macros for the possibleTYPEvalues.
β οΈ okay so this one is a legacy, deprecated interface. it's only available for v4 packages for backwards compatibility, and it should not be used. packages built this way carry less data about their files β like no "color" information (which is vital for RPM's functionality on multiarch systems), no file type information, and no per-file dependency tracking. so like, please don't π
if you want to enable this interface anyway, define the macro:
%_use_internal_dependency_generator 0
π PER-PACKAGE TUNABLES π
these following macros can be used on a per-package basis β either by defining them straight up in the rpm-spec(5) file, or by passing them to rpmbuild(1) through the --define option:
%_local_file_attrs NAMESβ register file attributeNAMES(separated by colons) for the duration of the build. the respective file attribute and generator macros have to be defined separately, so don't forget that part.
this is super useful for running generators that are shipped by the package itself π«Ά
Added: 4.20.0
%__TYPE_exclude DEPSTRING_REβ filter out unwanted dependencies ofTYPEby matching theregex(7)stringDEPSTRING_RE, macro-expanded on use, against dependency strings. see Generator macros for the possibleTYPEvalues.
Example:
%define __requires_exclude ^lib.*$
%__TYPE_exclude_from PATH_REβ filter out unwanted dependencies ofTYPEby matching theregex(7)stringPATH_RE, macro-expanded on use, against filenames without the%{buildroot}prefix (like/bin/bash, for example). see Generator macros for the possibleTYPEvalues.
Example:
%define __provides_exclude_from ^%{_libdir}/mypkg/.*.so$
%__NAME_TYPE_opts OPTSβ pass additional command line switches to theTYPEgenerator. see Generator macros for the possibleTYPEvalues.
note that this macro should NOT be used when writing a file attribute file. instead, just pass the required arguments directly on the generator's command line when you define it. simplicity is the vibe β¨
π TROUBLESHOOTING π
π Displaying debug information
rpmbuild(1) and rpmdeps(1) both have a hidden --rpmfcdebug switch that turns on extra output for the dependency generation stage. the output format is currently roughly like this:
<file number> <on-disk path> <color info> <file attribute matches>
<list of dependencies associated with this file>
file attribute matches are the names of the rules that matched for the file, and that's exactly where rule troubleshooting typically starts: a file with no attributes will not have any dependencies attached. a whole snack with nothing on it, basically π
π Global excludes
global variants of the per-package exclusion macros can also be defined on the system:
%__global_TYPE_exclude DEPSTRING_RE%__global_TYPE_exclude_from PATH_RE
these apply to all package builds and thus may affect the output of a particular generator in ways you did not expect. so if something's acting cursed, make sure to inspect the contents of these macros first π
π EXAMPLES π
okay bestie this is the part where it all clicks, i promise π
πΈ Example 1. A trivial multifile generator πΈ
say we've got a %{_fileattrsdir}/frob.attr file and it looks exactly like this:
%__frob_provides %{_rpmconfigdir}/frobnize --provides
%__frob_requires %{_rpmconfigdir}/frobnize --requires
%__frob_protocol multifile
%__frob_path \.frob$
%__frob_magic ^.* a frob file .*$
so this file is defining a file attribute named frob, and it's got two generators hanging off it, and both of them call on a frobnize script that speaks the multifile protocol π
and the file attribute matches every file with the .frob suffix plus any file containing that "a frob file" magic string. both. either. slay β¨
and %{_rpmconfigdir}/frobnize looks like this:
#!/bin/bash
# Frob dependency extractor
# Type of dependency strings to print
mode=$1
# Process every file on standard input
while read -r file; do
# Print currently processed file as per multifile protocol
echo ";$file"
# Get basename and first line
name=$(basename $file | cut -f1 -d.)
line=$(head -n1 $file)
# Print dependency strings
case $mode in
--provides)
echo "frob($name)"
echo "frob($line)"
;;
--requires)
echo "bard($name)"
echo "bard($line)"
;;
esac
done
now imagine there's a frob.spec file that installs a file called hello.frob whose contents are "world", dropping it somewhere on the filesystem. when that spec gets built, the resulting package ends up with these provides and requires π
$ rpmbuild -bb /path/to/frob.spec
...
$ rpm -qp --provides --requires /path/to/frob.rpm
...
frob(hello)
frob(world)
bard(hello)
bard(world)
...
and here's the cute part π if the package had multiple files with the .frob suffix or the "a frob file" magic, the frobnize script would still only get executed once, with all the matching filenames passed in at the same time. efficiency, she ate β
lowkey important though bestie: if that generator ever decided to dip out of the while loop early, it would have to discard whatever input was still left over before exiting β that's the protocol, no cap π β and that cleanup can be done with this command placed after the loop:
cat > /dev/null
π¦ Example 2. Spec-local generators π¦
this spec file snippet brings in two spec-local file attributes, frob and bard, and they match literally any and all files. their generators use a frobnize and a bardize.sh script respectively β one shipped by the package itself, and one only included with the sources. iconic π
...
Source1: bardize.sh
...
%define _local_file_attrs frob:bard
%define __frob_provides %{buildroot}/%{_rpmconfigdir}/frobnize
%define __frob_path .*
%define __bard_provides %{SOURCE1}
%define __bard_path .*
...
π§ Example 3. Bundled file attributes and generators π§
%{_fileattrsdir}/*.attr
%{_rpmconfigdir}/*.req
%{_rpmconfigdir}/*.prov
this right here is a small, carefully curated set of file attributes and their generators that come bundled with RPM itself π they cover the core domains you'd find on a UNIX/Linux system β think ELF binaries, executable scripts, or sysusers.d(5) files. the essentials, periodt β¨
π SEE ALSO π
like, go read these too, they're all part of the lore π
and that's the whole page bestie, you made it to the end π«Άπ this was RPM 6.1.0, dated 2026-08-20 β go forth and generate dependencies, you absolute main character πβ¨
π¦ where this page comes from
- ubuntu stonking: rpm 6.1.0-1 Β· GPL-2.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms