mirror of
https://gitlab.postmarketos.org/postmarketOS/pmbootstrap.git
synced 2025-07-13 03:19:47 +03:00
108 lines
3.3 KiB
Python
108 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, Optional, Union
|
|
|
|
import pmb.config
|
|
import pmb.chroot.apk
|
|
import pmb.helpers.pmaports
|
|
from pmb.core import Chroot
|
|
from pmb.core.context import 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"
|