diff --git a/pmb/build/__init__.py b/pmb/build/__init__.py index 2ff3e1d9..47686600 100644 --- a/pmb/build/__init__.py +++ b/pmb/build/__init__.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: GPL-3.0-or-later from pmb.build.init import init, init_abuild_minimal, init_compiler from pmb.build.envkernel import package_kernel -from pmb.build.kconfig import menuconfig from pmb.build.newapkbuild import newapkbuild from pmb.build.other import copy_to_buildpath, get_status, index_repo from .backend import mount_pmaports diff --git a/pmb/build/kconfig.py b/pmb/build/kconfig.py index c37bd893..96279706 100644 --- a/pmb/build/kconfig.py +++ b/pmb/build/kconfig.py @@ -1,10 +1,11 @@ # Copyright 2023 Oliver Smith # SPDX-License-Identifier: GPL-3.0-or-later +import enum import os +from pathlib import Path from pmb.core.arch import Arch from pmb.core.context import get_context from pmb.helpers import logging -from pathlib import Path from typing import Any import pmb.build @@ -13,14 +14,38 @@ import pmb.build.checksum import pmb.chroot import pmb.chroot.apk import pmb.chroot.other -from pmb.types import PmbArgs import pmb.helpers.pmaports import pmb.helpers.run import pmb.parse from pmb.core import Chroot -def get_arch(apkbuild) -> Arch: +class KConfigUI(enum.Enum): + MENUCONFIG = "menuconfig" + XCONFIG = "xconfig" + NCONFIG = "nconfig" + + def is_graphical(self) -> bool: + match self: + case KConfigUI.MENUCONFIG | KConfigUI.NCONFIG: + return False + case KConfigUI.XCONFIG: + return True + + def depends(self) -> list[str]: + match self: + case KConfigUI.MENUCONFIG: + return ["ncurses-dev"] + case KConfigUI.NCONFIG: + return ["ncurses-dev"] + case KConfigUI.XCONFIG: + return ["qt5-qtbase-dev", "font-noto"] + + def __str__(self) -> str: + return self.value + + +def get_arch(apkbuild: dict[str, Any]) -> Arch: """Take the architecture from the APKBUILD or complain if it's ambiguous. This function only gets called if --arch is not set. @@ -109,66 +134,13 @@ def extract_and_patch_sources(pkgname: str, arch) -> None: ) -def menuconfig(args: PmbArgs, pkgname: str, use_oldconfig) -> None: - # Pkgname: allow omitting "linux-" prefix - if not pkgname.startswith("linux-"): - pkgname = "linux-" + pkgname - - # Read apkbuild +def _make(chroot: pmb.core.Chroot, make_command: str, env, pkgname, arch, apkbuild) -> None: aport = pmb.helpers.pmaports.find(pkgname) - apkbuild = pmb.parse.apkbuild(aport / "APKBUILD") - arch = args.arch or get_arch(apkbuild) - chroot = pmb.build.autodetect.chroot(apkbuild, arch) - cross = pmb.build.autodetect.crosscompile(apkbuild, arch) - hostspec = arch.alpine_triple() - - # Set up build tools and makedepends - pmb.build.init(chroot) - if cross: - pmb.build.init_compiler(get_context(), [], cross, arch) - - depends = apkbuild["makedepends"] + ["gcc", "make"] - copy_xauth = False - - if use_oldconfig: - kopt = "oldconfig" - else: - kopt = "menuconfig" - if args.xconfig: - depends += ["qt5-qtbase-dev", "font-noto"] - kopt = "xconfig" - copy_xauth = True - elif args.nconfig: - kopt = "nconfig" - depends += ["ncurses-dev"] - else: - depends += ["ncurses-dev"] - - pmb.chroot.apk.install(depends, Chroot.native()) - - # Copy host's .xauthority into native - if copy_xauth: - pmb.chroot.other.copy_xauthority(args) - - extract_and_patch_sources(pkgname, arch) - - # Check for background color variable - color = os.environ.get("MENUCONFIG_COLOR") - - # Run make menuconfig outputdir = get_outputdir(pkgname, apkbuild) - logging.info("(native) make " + kopt) - env = { - "ARCH": arch.kernel(), - "DISPLAY": os.environ.get("DISPLAY"), - "XAUTHORITY": "/home/pmos/.Xauthority", - } - if cross: - env["CROSS_COMPILE"] = f"{hostspec}-" - env["CC"] = f"{hostspec}-gcc" - if color: - env["MENUCONFIG_COLOR"] = color - pmb.chroot.user(["make", kopt], Chroot.native(), outputdir, output="tui", env=env) + + logging.info("(native) make " + make_command) + + pmb.chroot.user(["make", str(make_command)], chroot, outputdir, output="tui", env=env) # Find the updated config source = Chroot.native() / outputdir / ".config" @@ -181,3 +153,71 @@ def menuconfig(args: PmbArgs, pkgname: str, use_oldconfig) -> None: target = aport / config pmb.helpers.run.user(["cp", source, target]) pmb.build.checksum.update(pkgname) + + +def _init(pkgname: str, arch: Arch | None) -> tuple[str, Arch, Any, Chroot, dict[str, str]]: + """ + :returns: pkgname, arch, apkbuild, chroot, env + """ + # Pkgname: allow omitting "linux-" prefix + if not pkgname.startswith("linux-"): + pkgname = "linux-" + pkgname + + aport = pmb.helpers.pmaports.find(pkgname) + apkbuild = pmb.parse.apkbuild(aport / "APKBUILD") + + if arch is None: + arch = get_arch(apkbuild) + + chroot = pmb.build.autodetect.chroot(apkbuild, arch) + cross = pmb.build.autodetect.crosscompile(apkbuild, arch) + hostspec = arch.alpine_triple() + + # Set up build tools and makedepends + pmb.build.init(chroot) + if cross: + pmb.build.init_compiler(get_context(), [], cross, arch) + + depends = apkbuild["makedepends"] + ["gcc", "make"] + + pmb.chroot.apk.install(depends, chroot) + + extract_and_patch_sources(pkgname, arch) + + env = { + "ARCH": arch.kernel(), + } + + if cross: + env["CROSS_COMPILE"] = f"{hostspec}-" + env["CC"] = f"{hostspec}-gcc" + + return pkgname, arch, apkbuild, chroot, env + + +def migrate_config(pkgname: str, arch: Arch | None) -> None: + pkgname, arch, apkbuild, chroot, env = _init(pkgname, arch) + _make(chroot, "oldconfig", env, pkgname, arch, apkbuild) + pass + + +def edit_config(pkgname: str, arch: Arch | None, config_ui: KConfigUI) -> None: + pkgname, arch, apkbuild, chroot, env = _init(pkgname, arch) + + pmb.chroot.apk.install(config_ui.depends(), chroot) + + # Copy host's .xauthority into native + if config_ui.is_graphical(): + pmb.chroot.other.copy_xauthority(chroot) + env["DISPLAY"] = os.environ.get("DISPLAY") or ":0" + env["XAUTHORITY"] = "/home/pmos/.Xauthority" + + # Check for background color variable + color = os.environ.get("MENUCONFIG_COLOR") + if color: + env["MENUCONFIG_COLOR"] = color + mode = os.environ.get("MENUCONFIG_MODE") + if mode: + env["MENUCONFIG_MODE"] = mode + + _make(chroot, str(config_ui), env, pkgname, arch, apkbuild) diff --git a/pmb/chroot/other.py b/pmb/chroot/other.py index f67fd8bc..624da409 100644 --- a/pmb/chroot/other.py +++ b/pmb/chroot/other.py @@ -4,7 +4,6 @@ import os from pmb.core.context import get_context from pmb.helpers import logging import pmb.chroot.apk -from pmb.types import PmbArgs import pmb.install from pmb.core import Chroot @@ -34,7 +33,7 @@ def kernel_flavor_installed(chroot: Chroot, autoinstall=True) -> str | None: return glob_result[0].name if glob_result else None -def copy_xauthority(args: PmbArgs) -> None: +def copy_xauthority(chroot: Chroot) -> None: """ Copy the host system's Xauthority file to the pmos user inside the chroot, so we can start X11 applications from there. @@ -60,7 +59,7 @@ def copy_xauthority(args: PmbArgs) -> None: ) # Copy to chroot and chown - copy = Chroot.native() / "home/pmos/.Xauthority" + copy = chroot / "home/pmos/.Xauthority" if os.path.exists(copy): pmb.helpers.run.root(["rm", copy]) pmb.helpers.run.root(["cp", original, copy]) diff --git a/pmb/commands/__init__.py b/pmb/commands/__init__.py index 506db173..d0549e63 100644 --- a/pmb/commands/__init__.py +++ b/pmb/commands/__init__.py @@ -19,8 +19,7 @@ from .test import Test from .pkgrel_bump import PkgrelBump from .pkgver_bump import PkgverBump from .pull import Pull -from .kconfig_check import KConfigCheck -from .kconfig_edit import KConfigEdit +from .kconfig import KConfigCheck, KConfigEdit, KConfigMigrate """New way to model pmbootstrap subcommands that can be invoked without PmbArgs.""" @@ -89,8 +88,10 @@ def run_command(args: PmbArgs): command = KConfigCheck( args.kconfig_check_details, args.file, args.package, args.keep_going ) - case "edit" | "migrate": - command = KConfigEdit(args.package[0], args.action_kconfig == "migrate") + case "edit": + command = KConfigEdit(args.package[0], args.arch, args.xconfig, args.nconfig) + case "migrate": + command = KConfigMigrate(args.package, args.arch) case _: raise NotImplementedError(f"Command '{args.action}' is not implemented.") diff --git a/pmb/commands/kconfig_check.py b/pmb/commands/kconfig.py similarity index 60% rename from pmb/commands/kconfig_check.py rename to pmb/commands/kconfig.py index 64b91ee0..94bce869 100644 --- a/pmb/commands/kconfig_check.py +++ b/pmb/commands/kconfig.py @@ -2,25 +2,25 @@ # SPDX-License-Identifier: GPL-3.0-or-later from __future__ import annotations -from pmb import commands -from pmb.core.context import get_context -from pmb.helpers.exceptions import NonBugError -import pmb.parse.kconfig + import pmb.helpers.git import pmb.config +import pmb.parse.kconfig import logging +from pmb import commands +from pmb.build.kconfig import KConfigUI +from pmb.core.arch import Arch +from pmb.core.context import get_context +from pmb.helpers.exceptions import NonBugError class KConfigCheck(commands.Command): - details: bool - file: str - packages: list[str] - keep_going: bool - - def __init__(self, details, file, packages, keep_going) -> None: + def __init__( + self, details: bool, file: str, pkgname: str | list[str], keep_going: bool + ) -> None: self.details = details self.file = file - self.packages = packages + self.pkgname_list = [pkgname] if isinstance(pkgname, str) else pkgname self.keep_going = keep_going def run(self) -> None: @@ -36,16 +36,16 @@ class KConfigCheck(commands.Command): raise NonBugError(error_msg) # Default to all kernel packages - if not self.packages: + if not self.pkgname_list: for pkg in pmb.helpers.pmaports.get_list(): if pkg.startswith("linux-"): - self.packages.append(pkg.split("linux-")[1]) + self.pkgname_list.append(pkg.split("linux-")[1]) # Iterate over all kernels error = False skipped = 0 - self.packages.sort() - for package in self.packages: + self.pkgname_list.sort() + for package in self.pkgname_list: if not get_context().force: pkgname = package if package.startswith("linux-") else f"linux-{package}" aport = pmb.helpers.pmaports.find(pkgname) @@ -68,3 +68,34 @@ class KConfigCheck(commands.Command): " (consider 'pmbootstrap kconfig check -f')" ) logging.info("kconfig check succeeded!") + + +class KConfigEdit(commands.Command): + def __init__( + self, pkgname: str, arch: Arch | None, use_xconfig: bool, use_nconfig: bool + ) -> None: + self.pkgname = pkgname + self.arch = arch + + if use_xconfig and use_nconfig: + raise AssertionError + + if use_xconfig: + self.chosen_ui = KConfigUI.XCONFIG + elif use_nconfig: + self.chosen_ui = KConfigUI.NCONFIG + else: + self.chosen_ui = KConfigUI.MENUCONFIG + + def run(self) -> None: + pmb.build.kconfig.edit_config(self.pkgname, self.arch, self.chosen_ui) + + +class KConfigMigrate(commands.Command): + def __init__(self, pkgname: str | list[str], arch: Arch | None) -> None: + self.pkgname_list = [pkgname] if isinstance(pkgname, str) else pkgname + self.arch = arch + + def run(self): + for pkgname in self.pkgname_list: + pmb.build.kconfig.migrate_config(pkgname, self.arch) diff --git a/pmb/commands/kconfig_edit.py b/pmb/commands/kconfig_edit.py deleted file mode 100644 index b3f0f195..00000000 --- a/pmb/commands/kconfig_edit.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2024 Oliver Smith -# SPDX-License-Identifier: GPL-3.0-or-later - -from __future__ import annotations -from pmb import commands -import pmb.build -import pmb.helpers.args - - -class KConfigEdit(commands.Command): - pkgname: str - use_oldconfig: bool - - def __init__(self, pkgname, use_oldconfig): - self.pkgname = pkgname - self.use_oldconfig = use_oldconfig - pass - - def run(self): - args = pmb.helpers.args.please_i_really_need_args() - pmb.build.menuconfig(args, self.pkgname, self.use_oldconfig) diff --git a/pmb/helpers/frontend.py b/pmb/helpers/frontend.py index b234541c..69b62fcb 100644 --- a/pmb/helpers/frontend.py +++ b/pmb/helpers/frontend.py @@ -191,7 +191,7 @@ def chroot(args: PmbArgs) -> None: # Xauthority env = {} if args.xauth: - pmb.chroot.other.copy_xauthority(args) + pmb.chroot.other.copy_xauthority(chroot) env["DISPLAY"] = os.environ.get("DISPLAY") env["XAUTHORITY"] = "/home/pmos/.Xauthority"