forked from Mirror/pmbootstrap
Rename build.package() to build.packages() and take a list of packages to build, since every caller was inside a for loop this simplifies usage and let's us give nicer log output by doing all the builds first, so log messages don't get lost in the middle. Behaviour is cleaned up so this shouuuuld work pretty well now. It properly descends into dependencies and will build dependencies even if the package given doesn't need building. Technically this was only done before during install where the dependencies were recursed in chroot.apk.install(). It probably makes the most sense to have a mode where it doesn't build dependencies but warns the user about it, at least when invoked via pmbootstrap build. Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
107 lines
3.3 KiB
Python
107 lines
3.3 KiB
Python
# Copyright 2023 Oliver Smith
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
from pathlib import Path
|
|
from pmb.core.arch import Arch
|
|
from pmb.helpers import logging
|
|
from typing import Any, Dict, Optional, Union
|
|
|
|
import pmb.config
|
|
import pmb.chroot.apk
|
|
import pmb.helpers.pmaports
|
|
from pmb.core import Chroot, ChrootType, get_context
|
|
from pmb.meta import Cache
|
|
|
|
|
|
# FIXME (#2324): type hint Arch
|
|
def arch_from_deviceinfo(pkgname, aport: Path) -> Optional[Arch]:
|
|
"""
|
|
The device- packages are noarch packages. But it only makes sense to build
|
|
them for the device's architecture, which is specified in the deviceinfo
|
|
file.
|
|
|
|
:returns: None (no deviceinfo file)
|
|
arch from the deviceinfo (e.g. "armhf")
|
|
"""
|
|
# Require a deviceinfo file in the aport
|
|
if not pkgname.startswith("device-"):
|
|
return None
|
|
deviceinfo = aport / "deviceinfo"
|
|
if not deviceinfo.exists():
|
|
return None
|
|
|
|
# Return its arch
|
|
device = pkgname.split("-", 1)[1]
|
|
arch = pmb.parse.deviceinfo(device).arch
|
|
logging.verbose(f"{pkgname}: arch from deviceinfo: {arch}")
|
|
return arch
|
|
|
|
|
|
@Cache("package")
|
|
def arch(package: Union[str, Dict[str, Any]]):
|
|
"""
|
|
Find a good default in case the user did not specify for which architecture
|
|
a package should be built.
|
|
|
|
:param package: The name of the package or parsed APKBUILD
|
|
|
|
:returns: arch string like "x86_64" or "armhf". Preferred order, depending
|
|
on what is supported by the APKBUILD:
|
|
* native arch
|
|
* device arch (this will be preferred instead if build_default_device_arch is true)
|
|
* first arch in the APKBUILD
|
|
"""
|
|
pkgname = package["pkgname"] if isinstance(package, dict) else package
|
|
aport = pmb.helpers.pmaports.find(pkgname)
|
|
if not aport:
|
|
raise FileNotFoundError(f"APKBUILD not found for {pkgname}")
|
|
ret = arch_from_deviceinfo(pkgname, aport)
|
|
if ret:
|
|
return ret
|
|
|
|
apkbuild = pmb.parse.apkbuild(aport) if isinstance(package, str) else package
|
|
arches = apkbuild["arch"]
|
|
deviceinfo = pmb.parse.deviceinfo()
|
|
|
|
if get_context().config.build_default_device_arch:
|
|
preferred_arch = deviceinfo.arch
|
|
preferred_arch_2nd = Arch.native()
|
|
else:
|
|
preferred_arch = Arch.native()
|
|
preferred_arch_2nd = deviceinfo.arch
|
|
|
|
if "noarch" in arches or "all" in arches or preferred_arch in arches:
|
|
return preferred_arch
|
|
|
|
if preferred_arch_2nd in arches:
|
|
return preferred_arch_2nd
|
|
|
|
try:
|
|
arch_str = apkbuild["arch"][0]
|
|
return Arch.from_str(arch_str) if arch_str else Arch.native()
|
|
except IndexError:
|
|
return Arch.native()
|
|
|
|
|
|
def chroot(apkbuild: Dict[str, str], arch: Arch) -> Chroot:
|
|
if arch == Arch.native():
|
|
return Chroot.native()
|
|
|
|
if "pmb:cross-native" in apkbuild["options"]:
|
|
return Chroot.native()
|
|
|
|
return Chroot.buildroot(arch)
|
|
|
|
|
|
def crosscompile(apkbuild, arch: Arch):
|
|
"""
|
|
:returns: None, "native", "crossdirect"
|
|
"""
|
|
if not get_context().cross:
|
|
return None
|
|
if not arch.cpu_emulation_required():
|
|
return None
|
|
if arch.is_native() or "pmb:cross-native" in apkbuild["options"]:
|
|
return "native"
|
|
if "!pmb:crossdirect" in apkbuild["options"]:
|
|
return None
|
|
return "crossdirect"
|