rpm: Filtering dependencies differently for different subpackages

Recently I was trying to work out how to filter rpm Requires/Provides dependencies differently for different subpackages. I was trying to produce a subpackage that was the same as another subpackage, but stripping out some library dependencies. Call the one subpackage foo and the other foo-nodeps. (Don’t ask why I was trying to do this.)

rpm has a way of hooking the dependency generation, as described in FilteringAutomaticDependencies at the Fedora wiki. This is pretty magical. You disable rpm’s internal dependency generation. You can then override the default external dependency generation scripts (if you want). Normally rpm uses find-requires and find-provides in /usr/lib/rpm, or /usr/lib/rpm/redhat on some Red Hat or Red Hat-derived systems. If you do override the scripts, it’s likely you’ll want to call them and filter their output.

When you define your own dependency generation scripts, they are applied to all subpackages. There is no information passed to the script to indicate which package/subpackage it is being call for. You can pass arbitrary parameters to your custom find-requires/find-provides scripts. But there are no macros that you can use to pass that in as a parameter (%name is always the main package’s name – there’s no %subpackage macro AFACIS).

A solution was to pass that information in via the filesystem. In the %install script I’d create a file per package. Something like this:

mkdir -p %{buildroot}/NOTINSTALLED
touch %{buildroot}/NOTINSTALLED/foo.ghost
touch %{buildroot}/NOTINSTALLED/foo-nodeps.ghost


Then in each package’s file list I’d put the appropriate file:

%files
...
%ghost /NOTINSTALLED/foo.ghost

%files nodeps
...
%ghost /NOTINSTALLED/foo-nodeps.ghost


The %ghost ensures that the file isn’t installed, but is still passed to the find-requires/find-provides scripts. A custom find-requires script can then find out which subpackage it’s being called for. Something like this:

cat > .files
if (grep -q -E '^/NOTINSTALLED/foo-nodeps.ghost\$' 2>/dev/null); then
# Filter out dependencies on libfoo
/usr/lib/rpm/find-requires | grep -v -E '^libfoo.so'
else
/usr/lib/rpm/find-requires
fi