pmbootstrap-meow/pmb/build/autodetect.py
Caleb Connolly dcc4137ee8
FIXUP: build: abstract CrossCompile type logic
* Make CrossCompile a proper enum type rather than a string literal,
* Introduce methods to get the correct host/build chroots depending on the
  cross compile type and target architecture.
* Remove autodetect.chroot() since it doesn't do what we expect, adjust
  all users to use cross.build_chroot() instead.
* Refactor package building to correctly use cross.host_chroot() and
  cross.build_chroot().

Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
Part-of: https://gitlab.postmarketos.org/postmarketOS/pmbootstrap/-/merge_requests/2568
2025-03-16 16:30:04 +01:00

96 lines
3.2 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
import pmb.config
import pmb.chroot.apk
import pmb.helpers.pmaports
from pmb.core.context import get_context
from pmb.meta import Cache
from pmb.types import Apkbuild, CrossCompile
def arch_from_deviceinfo(pkgname: str, aport: Path) -> Arch | None:
"""
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: str | Apkbuild) -> Arch:
"""
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 object. 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 crosscompile(apkbuild: Apkbuild, arch: Arch) -> CrossCompile:
"""Decide the type of compilation necessary to build a given APKBUILD."""
if not get_context().cross:
return CrossCompile.QEMU_ONLY
if not arch.cpu_emulation_required():
return CrossCompile.UNNECESSARY
if "pmb:cross-native" in apkbuild["options"]:
return CrossCompile.CROSS_NATIVE
if arch.is_native() or "pmb:cross-native2" in apkbuild["options"]:
return CrossCompile.CROSS_NATIVE2
if "!pmb:crossdirect" in apkbuild["options"]:
return CrossCompile.QEMU_ONLY
return CrossCompile.CROSSDIRECT