Bug 1402784 - dnf builddep installs incorrect packages due to architecture differences
Summary: dnf builddep installs incorrect packages due to architecture differences
Keywords:
Status: CLOSED WONTFIX
Alias: None
Product: Fedora
Classification: Fedora
Component: dnf-plugins-core
Version: 25
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: rpm-software-management
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2016-12-08 10:50 UTC by Daniel Berrangé
Modified: 2018-06-15 07:17 UTC (History)
15 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2017-07-27 19:13:57 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Bugzilla 1404281 0 unspecified CLOSED dnf builddep --spec fails to recognize legitimate spec file 2021-02-22 00:41:40 UTC

Description Daniel Berrangé 2016-12-08 10:50:40 UTC
Description of problem:
If you run 'dnf builddep libvirt' on a Fedora 25 host, it will install alot of files, but crucially it misses out

	numactl-devel 
	numad 
	xen-devel 

so if you actually try to build libvirt after installing builddeps, it fails with a bunch of missing deps

# dnf builddep libvirt
enabling fedora-source repository
enabling updates-source repository
Last metadata expiration check: 0:22:27 ago on Thu Dec  8 10:20:09 2016.
Package gettext-0.19.8.1-3.fc25.x86_64 is already installed, skipping.
Package perl-4:5.24.0-379.fc25.x86_64 is already installed, skipping.
Package libxml2-devel-2.9.3-4.fc25.x86_64 is already installed, skipping.
Package ncurses-devel-6.0-6.20160709.fc25.x86_64 is already installed, skipping.
Package readline-devel-6.3-8.fc24.x86_64 is already installed, skipping.
Package git-2.9.3-1.fc25.x86_64 is already installed, skipping.
Package systemd-231-10.fc25.x86_64 is already installed, skipping.
Package libxslt-1.1.28-13.fc25.x86_64 is already installed, skipping.
Package libselinux-devel-2.5-13.fc25.x86_64 is already installed, skipping.
Package libcurl-devel-7.51.0-3.fc25.x86_64 is already installed, skipping.
Package dbus-devel-1:1.11.8-1.fc25.x86_64 is already installed, skipping.
Package python-2.7.12-7.fc25.x86_64 is already installed, skipping.
Package gnutls-devel-3.5.5-2.fc25.x86_64 is already installed, skipping.
Package libattr-devel-2.4.47-16.fc24.x86_64 is already installed, skipping.
Package gawk-4.1.3-8.fc25.x86_64 is already installed, skipping.
Package audit-libs-devel-2.6.7-1.fc25.x86_64 is already installed, skipping.
Package cyrus-sasl-devel-2.1.26-26.2.fc24.x86_64 is already installed, skipping.
Package libpcap-devel-14:1.7.4-2.fc24.x86_64 is already installed, skipping.
Package systemtap-sdt-devel-3.1-0.20160725git91bfb36.fc25.x86_64 is already installed, skipping.
Package device-mapper-devel-1.02.131-5.fc25.x86_64 is already installed, skipping.
Package libnl3-devel-3.2.28-3.fc25.x86_64 is already installed, skipping.
Package util-linux-2.28.2-1.fc25.x86_64 is already installed, skipping.
Package yajl-devel-2.1.0-5.fc24.x86_64 is already installed, skipping.
Package qemu-img-2:2.7.0-7.fc25.x86_64 is already installed, skipping.
Package augeas-1.7.0-1.fc25.x86_64 is already installed, skipping.
Package parted-devel-3.2-21.fc25.x86_64 is already installed, skipping.
Package avahi-devel-0.6.32-4.fc25.x86_64 is already installed, skipping.
Package ebtables-2.0.10-21.fc25.x86_64 is already installed, skipping.
Package iptables-1.6.0-2.fc25.x86_64 is already installed, skipping.
Package libtasn1-devel-4.9-1.fc25.x86_64 is already installed, skipping.
Package lvm2-2.02.161-5.fc25.x86_64 is already installed, skipping.
Package kmod-23-1.fc25.x86_64 is already installed, skipping.
Package nfs-utils-1:1.3.4-1.rc3.fc25.x86_64 is already installed, skipping.
Package ceph-devel-compat-1:10.2.2-3.fc25.x86_64 is already installed, skipping.
Package iscsi-initiator-utils-6.2.0.873-34.git4c1f2d9.fc25.x86_64 is already installed, skipping.
Package radvd-2.14-1.fc25.x86_64 is already installed, skipping.
Package scrub-2.5.2-8.fc24.x86_64 is already installed, skipping.
Package sheepdog-0.3.0-11.fc24.x86_64 is already installed, skipping.
Package xhtml1-dtds-1.0-20020801.13.fc24.1.noarch is already installed, skipping.
Package polkit-0.113-5.fc24.x86_64 is already installed, skipping.
Package dnsmasq-2.76-2.fc25.x86_64 is already installed, skipping.
Package libblkid-devel-2.28.2-1.fc25.x86_64 is already installed, skipping.
Package fuse-devel-2.9.7-1.fc25.x86_64 is already installed, skipping.
Package glusterfs-api-devel-3.9.0-1.fc25.x86_64 is already installed, skipping.
Package glusterfs-devel-3.9.0-1.fc25.x86_64 is already installed, skipping.
Package libcap-ng-devel-0.7.8-1.fc25.x86_64 is already installed, skipping.
Package libpciaccess-devel-0.13.4-3.fc24.x86_64 is already installed, skipping.
Package libssh2-devel-1.8.0-1.fc25.x86_64 is already installed, skipping.
Package libwsman-devel-2.6.2-7.fc25.x86_64 is already installed, skipping.
Package netcf-devel-0.2.8-4.fc24.x86_64 is already installed, skipping.
Package polkit-devel-0.113-5.fc24.x86_64 is already installed, skipping.
Package sanlock-devel-3.4.0-2.fc25.x86_64 is already installed, skipping.
Package systemd-devel-231-10.fc25.x86_64 is already installed, skipping.
Package wireshark-devel-2.2.2-2.fc25.x86_64 is already installed, skipping.
Dependencies resolved.
Nothing to do.
Complete!


# fedpkg local
error: Failed build dependencies:
	numactl-devel is needed by libvirt-2.2.0-2.fc25.x86_64
	numad is needed by libvirt-2.2.0-2.fc25.x86_64
	xen-devel is needed by libvirt-2.2.0-2.fc25.x86_64


Now, dnf builddep is getting its data from the src.rpm in the Fedora sources yum repository. If we look at the src.rpm in question., we can see it does indeed miss the numa & xen deps:


$ wget https://kojipkgs.fedoraproject.org/packages/libvirt/2.2.0/2.fc25/src/libvirt-2.2.0-2.fc25.src.rpm

$ rpm -qp libvirt-2.2.0-2.fc25.src.rpm  --requires | grep -E '(xen|numa)'
$


Looking further we can see that, quite by luck, the src.rpm for libvirt in F25 was built on an arm7 host:

$ rpm -qp libvirt-2.2.0-2.fc25.src.rpm  -i | grep Build
Build Date  : Mon 14 Nov 2016 21:05:39 GMT
Build Host  : arm04-builder04.arm.fedoraproject.org


So whats happening is that  the Requires in the src.rpm are getting populated based on the BuildRequires in the spec, as interpreted for an arm7 host. When we then run dnf builddep on an x86_64 host, dnf is trying to install the build deps for an arm7 host, and so missing stuff. 

Conversely if the src.rpm had been built on an x86_64 host and we then tried dnf builddep on an arm7 host, it would try to install packages that don't exist in arm7 (numa/xen)

IOW, you cannot rely on the Requires from a src.rpm unless you are 100% sure the src.rpm was built on the same architecture as the current host.

To fix this, dnf needs to be rewritten so that it unpacks the src.rpm to extract the spec file, and then re-use its existing logic to pull BuildRequires from the spec file. This will ensure it evaluates the conditional BuildRequires according to the current host architecture.

Version-Release number of selected component (if applicable):
python3-dnf-plugins-core-0.1.21-4.fc25.noarch

How reproducible:
Always

Steps to Reproduce:
1. Install a bare F25 host
2. dnf builddep libvirt
2. fedpkg co -a libvirt
3. cd libvirt && git checkout f25
4. fedpkg local

Actual results:
error: Failed build dependencies:
	numactl-devel is needed by libvirt-2.2.0-2.fc25.x86_64
	numad is needed by libvirt-2.2.0-2.fc25.x86_64
	xen-devel is needed by libvirt-2.2.0-2.fc25.x86_64


Expected results:
Build completes 

Additional info:

Comment 1 Igor Gnatenko 2016-12-08 10:52:58 UTC
> To fix this, dnf needs to be rewritten so that it unpacks the src.rpm to extract the spec file, and then re-use its existing logic to pull BuildRequires from the spec file. This will ensure it evaluates the conditional BuildRequires according to the current host architecture.

This is totally wrong approach. But we will check why it doesn't install all builddeps.

Comment 2 Daniel Berrangé 2016-12-08 10:56:23 UTC
(In reply to Igor Gnatenko from comment #1)
> > To fix this, dnf needs to be rewritten so that it unpacks the src.rpm to extract the spec file, and then re-use its existing logic to pull BuildRequires from the spec file. This will ensure it evaluates the conditional BuildRequires according to the current host architecture.
> 
> This is totally wrong approach. But we will check why it doesn't install all
> builddeps.

It doesn't install all builddeps simply because the information source it is using (Requires from src.rpm) is incorrect. This can be clearly seen by just querying the src.rpm directly with rpm. AFAIK, there's nothing dnf can do to fix this lack of information in src.rpm deps as RPM does not embed conditional logic in its binary src.rpm Requires. The spec file inside the src.rpm is only place dnf can get the correct information.

Comment 3 Igor Gnatenko 2016-12-08 10:57:46 UTC
(In reply to Daniel Berrange from comment #2)
> (In reply to Igor Gnatenko from comment #1)
> > > To fix this, dnf needs to be rewritten so that it unpacks the src.rpm to extract the spec file, and then re-use its existing logic to pull BuildRequires from the spec file. This will ensure it evaluates the conditional BuildRequires according to the current host architecture.
> > 
> > This is totally wrong approach. But we will check why it doesn't install all
> > builddeps.
> 
> It doesn't install all builddeps simply because the information source it is
> using (Requires from src.rpm) is incorrect. This can be clearly seen by just
> querying the src.rpm directly with rpm. AFAIK, there's nothing dnf can do to
> fix this lack of information in src.rpm deps as RPM does not embed
> conditional logic in its binary src.rpm Requires. The spec file inside the
> src.rpm is only place dnf can get the correct information.
then it's clearly bug in RPM.

Comment 4 Daniel Berrangé 2016-12-08 11:06:38 UTC
(In reply to Igor Gnatenko from comment #3)
> (In reply to Daniel Berrange from comment #2)
> > It doesn't install all builddeps simply because the information source it is
> > using (Requires from src.rpm) is incorrect. This can be clearly seen by just
> > querying the src.rpm directly with rpm. AFAIK, there's nothing dnf can do to
> > fix this lack of information in src.rpm deps as RPM does not embed
> > conditional logic in its binary src.rpm Requires. The spec file inside the
> > src.rpm is only place dnf can get the correct information.
> then it's clearly bug in RPM.

It really isn't - its an inherent limitation of the src.rpm Requires information. When creating the src.rpm RPM has to evaluate the spec file to expand the various %ifdef conditionals to determin which BuildRequires are relevant for the src.rpm Requires. It can only evaluate this based on the host environment it is using to create the src.rpm. There's no practical way to evaluate what such conditionals would produce for an x86_64 host, when running on an arm7 host, or vica-verca.

If dnf really wants to use src.rpms as the basis for builddep, then Fedora would have to ship src.rpms per-architecture in its repos, so it could fetch the src.rpm corresponding to the current architecture its installing on.

Comment 5 Michael Mráka 2016-12-08 11:30:38 UTC
If Requires from src.rpm does not work for you use

 # dnf builddep libvirt.spec 

to install BuildRequires from the spec.

Comment 6 Panu Matilainen 2016-12-08 13:06:44 UTC
Here we go again... :) Igor, I suggest you see bug 554854 and bug 771938 and bug 664427 for some background.

The short version is that mostly everybody assumes an src.rpm to be an arch-independent construct when it is not, never was. It even says so if you look at the ARCH tag. Using dependencies from src.rpm works just fine but ONLY if that src.rpm was generated on the same architecture, distro version etc.

So with infra like Fedora where one src.rpm is shared for all architectures, you have two choices:
- download the src.rpm and regenerate it with eg 'rpmbuild -rs --nodeps foo.src.rpm' 
- download the src.rpm and fish the spec out of it

For Fedora packages a third possibility exists as well: fetching the spec out of dist-git to avoid having to download the entire src.rpm. It's a well-known location with easy nvr -> tag mapping so it wouldn't even be hard.

Anyway, back to dnf-plugins-core.

Comment 7 Michael Mráka 2016-12-12 12:30:27 UTC
But is it possible to get correct BuildRequires from spec if there are macros and/or %ifs used?

Comment 8 Panu Matilainen 2016-12-12 13:05:45 UTC
Well, where do you think the dependencies in src.rpm come from? By parsing the spec with all its macros and %ifs etc - of course you need to use rpm API to do that but then builddep already supports parsing the spec, doesn't it?

Generally speaking its easy to create a spec that is completely unparseable without its build-requires installed but that'd make the spec broken for any machine processing anyway.

Comment 9 Michael Mráka 2016-12-12 13:20:36 UTC
(In reply to Panu Matilainen from comment #8)
> Well, where do you think the dependencies in src.rpm come from? By parsing
> the spec with all its macros and %ifs etc - of course you need to use rpm
> API to do that but then builddep already supports parsing the spec, doesn't
> it?

Sure, but macro on build host can vary from macros on my workstation so parsing spec locally I'll see a different output than build host did.

E.g.: My system is F25 and in addition to F25 repos I have also F24 repos configured and enabled. Now when I parse a spec from F24 src.rpm package its Release says 1%{dist} which will be wrongly expanded to 1.f25 on my system...

> Generally speaking its easy to create a spec that is completely unparseable
> without its build-requires installed but that'd make the spec broken for any
> machine processing anyway.

Comment 10 Daniel Berrangé 2016-12-12 13:31:13 UTC
(In reply to Michael Mráka from comment #9)
> (In reply to Panu Matilainen from comment #8)
> > Well, where do you think the dependencies in src.rpm come from? By parsing
> > the spec with all its macros and %ifs etc - of course you need to use rpm
> > API to do that but then builddep already supports parsing the spec, doesn't
> > it?
> 
> Sure, but macro on build host can vary from macros on my workstation so
> parsing spec locally I'll see a different output than build host did.
> 
> E.g.: My system is F25 and in addition to F25 repos I have also F24 repos
> configured and enabled. Now when I parse a spec from F24 src.rpm package its
> Release says 1%{dist} which will be wrongly expanded to 1.f25 on my system...

dnf builddep doesn't need to care about that. Its job is merely to get build deps installed suitable for the environment in which dnf builddep is run. If you want the macros to evaluate in a particular manner then you need to run dnf builddep in a suitable environment for your needs. ie if you're trying to rebuild a f24 RPM on f25, then you likely *want* %dist to evaluate to f25. If you want it to evaluate differently then use dnf builddep inside a chroot containing a suitable environment.  This is all better that what it does today wrt to reading src.rpm instead of the spec file.

Comment 11 Panu Matilainen 2016-12-12 13:38:50 UTC
Yes, macros and conditionals can and do vary between hosts due to a number of reasons and that's how it should be. Many specs have conditionals to support building with different distros and versions and the only way to get the correct dependencies and other settings is to parse the spec on the targeted distro/version - it's not rare to have a build-dependency on version X+1 which doesn't even exist on X, etc.

Comment 12 David Woodhouse 2016-12-13 12:28:27 UTC
Random drive-by comment: Many of those 'BuildRequires: foo-devel' in libvirt.spec look like they're violating the packaging guidelines, and should be 'BuildRequires: pkgconfig(foo)' instead.

Comment 13 Igor Gnatenko 2016-12-13 12:30:54 UTC
(In reply to David Woodhouse from comment #12)
> Random drive-by comment: Many of those 'BuildRequires: foo-devel' in
> libvirt.spec look like they're violating the packaging guidelines, and
> should be 'BuildRequires: pkgconfig(foo)' instead.
Not really. you use pkgconfig(foo) when package wants foo.pc, otherwise you use foo-devel. Anyway it's not mandatory.

Comment 14 Nikos Mavrogiannopoulos 2016-12-13 14:24:01 UTC
Trying to work-around the builddep brokeness with src.rpm using the .spec file does not work. #1404281 relates to this one.

Comment 15 Igor Gnatenko 2017-07-27 19:13:57 UTC
Sorry, but this needs to be worked by release engineering to provide arch-dependent SRPMs. DNF will *not* download srpms, unpack them and so on.


Note You need to log in before you can comment on or make changes to this bug.