In an RPM spec file, when a file isn't found, how to find out which %files line is at fault?

Craig Ringer asked:

I’m working with a very macro-heavy RPM spec file, and when building it’s producing an error I can’t seem to track down:

File not found: /var/tmp/pkgnamehere/mockbuild/usr/com/pgsql

(I’ve replaced the full package buildroot path with “pkgnamehere” above, but it’s otherwise unedited).

There’s no /usr/com/pgsql anywhere in %files, nor in fact any /com/ at all.

Presumably this is the result of macro expansion. The trouble is … how does one find out which %files line corresponds to a given missing file? It doesn’t say “File from %files on line 554 not found: ” or anything useful like that.

The many of the actual %files lines look like:

%config(noreplace) %{_initrddir}/%{oname}-%{majorversion}

so a simple text search isn’t useful here.

It’s possible to rpm --eval each line, but that’s pretty painful with over 300 files lines and the need to define all the input macros.


$ rpm --version
RPM version 4.11.2
$ lsb_release -a
LSB Version:    :core-4.1-amd64:core-4.1-ia32:core-4.1-noarch:cxx-4.1-amd64:cxx-4.1-ia32:cxx-4.1-noarch:desktop-4.1-amd64:desktop-4.1-ia32:desktop-4.1-noarch:languages-4.1-amd64:languages-4.1-noarch:printing-4.1-amd64:printing-4.1-noarch
Distributor ID: Fedora
Description:    Fedora release 20 (Heisenbug)
Release:        20
Codename:       Heisenbug
$ mock --version

Courtesy of this SO answer, rpmspec -P will expand and print out a spec. However, it hasn’t shed any light:

$ rpmspec -P unified-rpm/postgresql94.spec | grep '/com/'

in that there seems to be a mystery file here.

Courtesy of this SO answer, rpmspec -P will expand and print out a spec.

It looked fine on the build machine – then I figured out it was actually an issue within the CentOS 5 mock sandbox.

There there’s no rpmspec, so it’s not easy to tell what’s up. However I stumbled over this bug which suggests that it’s an issue with RPM on RHEL5. Sure enough, in the sandbox:

<mock-chroot>[root@ayaki BUILD]# rpm --eval '%_sharedstatedir'

to which I say …. what!?

So the immediate issue can be worked around with:

%if 0%{rhel5}
%define _sharedstatedir /var/lib

or perhaps:

%if "%{_sharedstatedir}" == "/usr/com"
# See
%define _sharedstatedir /var/lib

… but anyway, the underlying question remains: How do you get RPM to tell you which %files line corresponds to a missing file?

My answer:

The problem is not Fedora 20, nor is it Mock. It’s RHEL 5.

The RPM macro %{_sharedstatedir} was set to %{prefix}/com in both RHEL 4 and RHEL 5. The problem is that the macro was never used to build those distributions, so nobody paid any attention to its value. It only became an issue when people began backporting packages from later Fedora which did use the macro.

And, of course, because RHEL is a “stable” enterprise distribution which aims to not break compatibility during its lifecycle, this will never be changed.

The macro works as you expect in RHEL 6 and 7.

If you still have to support RHEL 5 boxes, you (and everyone else) are stuck with workarounds like the ones you already proposed. The simple and clean one is the first one you suggested:

%if 0%{rhel5}
%define _sharedstatedir /var/lib

I don’t see any point to referencing that particular bug, since it doesn’t actually explain the problem, nor give a workaround.

View the full question and answer on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.