Incorrect dependency resolution if package provider is not in pmaports
Related: https://gitlab.com/postmarketOS/pmaports/issues/404
Building mesa-git
fails at the moment:
$ pmbootstrap -v build mesa-git --arch aarch64 --force
[18:36:59] (native) install alpine-base
[18:37:00] (native) install qemu-aarch64
[18:37:00] Register qemu binfmt (aarch64)
[18:37:00] (buildroot_aarch64) install alpine-base
[18:37:02] (buildroot_aarch64) install abuild build-base ccache git
[18:37:09] NOTE: You can edit the 'arch=' line inside the APKBUILD
[18:37:09] NOTE: Alternatively, use --arch to build for another architecture ('pmbootstrap build --arch=armhf libdrm-grate')
[18:37:09] ERROR: Can't build 'libdrm-grate' for architecture aarch64
[18:37:09] See also: <https://postmarketos.org/troubleshooting>
Run 'pmbootstrap log' for details.
pmbootstrap log
: log.txt
It works fine with build --strict
but I believe abuild
handles the dependency resolution in that case.
If I understand the dependency resolution correctly, the following happens: (see pmb/parse/depends.py
)
Resolve dependency libdrm
:
-
package = package_from_aports(args, pkgname_depend = 'libdrm')
Look for an pmaport providinglibdrm
. Returnslibdrm-grate
, becauselibdrm
is only in Alpine. -
package = package_from_index(args, pkgname_depend = 'libdrm', pkgnames_install, package_aport = {...'libdrm-grate'...}, suffix)
Look for binary packages providinglibdrm
.-
provider = package_provider(args, pkgname_depend = 'libdrm', pkgnames_install, suffix)
Picklibdrm
from Alpine as the shortest provider. -
if (package_aport and pmb.parse.version.compare(package_aport["version"], provider["version"]) == 1):
Comparelibdrm
version2.4.100-r0
withlibdrm-grate
version2.4.100_git20191221-r0
libdrm
binary is outdated, returnlibdrm-grate
aport as provider.
-
So we are comparing package versions that don't really have anything to do with each other.
A naive fix would be:
diff --git a/pmb/parse/depends.py b/pmb/parse/depends.py
index 3010d505..39decc56 100644
--- a/pmb/parse/depends.py
+++ b/pmb/parse/depends.py
@@ -105,6 +105,13 @@ def package_from_index(args, pkgname_depend, pkgnames_install, package_aport,
if not provider:
return package_aport
+ # Check if we actually have an aport for the package we want to install
+ if package_aport and provider["pkgname"] != package_aport["pkgname"]:
+ logging.verbose(pkgname_depend + ": selected provider is " +
+ provider["pkgname"] + " but the aport is for " +
+ package_aport["pkgname"])
+ return provider
+
# Binary package outdated
if (package_aport and pmb.parse.version.compare(package_aport["version"],
provider["version"]) == 1):
to make sure the aport is actually for the binary package we have chosen. But I'm not sure if this works correctly if the provider is a sub-package.
Overall, (in my opinion) the current approach to resolve dependencies, i.e.
- Look for a single pmaport first (there could be several ones providing the same package!)
- Pick a binary package provider and compare the version with the (potentially unrelated) aport
doesn't really work correctly, especially if there are multiple providers.
I would suggest something like:
- Find all package providers
- Add binary package providers to the list
- Add aport package providers to the list (note: also need to consider
arch
)- If the package is already in the list
- Replace it? I.e. assume the aport is more up-to-date OR
- Compare the versions and pick latest
- Otherwise simply add as provider to the list (= no binary package)
- If the package is already in the list
- Pick a provider with the existing logic in
package_provider()
- Return it. Now we have either a binary package provider or an aport, because both were in the same list.
Does that make sense?